aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/masm/assembler/MacroAssemblerMIPS.h32
-rw-r--r--src/3rdparty/masm/disassembler/Mips32Disassembler.cpp56
-rw-r--r--src/3rdparty/masm/disassembler/mips32/Mips32Opcode.cpp620
-rw-r--r--src/3rdparty/masm/disassembler/mips32/Mips32Opcode.h78
-rw-r--r--src/3rdparty/masm/masm-defs.pri1
-rw-r--r--src/3rdparty/masm/masm.pri3
-rw-r--r--src/3rdparty/masm/stubs/Options.cpp2
-rw-r--r--src/3rdparty/masm/wtf/FilePrintStream.cpp3
-rw-r--r--src/3rdparty/masm/wtf/Platform.h2
-rw-r--r--src/imports/builtins.qmltypes1605
-rw-r--r--src/imports/folderlistmodel/fileinfothread.cpp3
-rw-r--r--src/imports/folderlistmodel/fileinfothread_p.h11
-rw-r--r--src/imports/folderlistmodel/fileproperty_p.h11
-rw-r--r--src/imports/folderlistmodel/plugins.qmltypes273
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.cpp16
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.h3
-rw-r--r--src/imports/imports.pro33
-rw-r--r--src/imports/localstorage/plugin.cpp44
-rw-r--r--src/imports/localstorage/plugins.qmltypes3
-rw-r--r--src/imports/models/models.pro2
-rw-r--r--src/imports/models/plugins.qmltypes54
-rw-r--r--src/imports/particles/plugins.qmltypes207
-rw-r--r--src/imports/qtqml/plugins.qmltypes222
-rw-r--r--src/imports/qtqml/qmldir2
-rw-r--r--src/imports/qtqml/qtqml.pro14
-rw-r--r--src/imports/qtquick2/plugins.qmltypes2083
-rw-r--r--src/imports/qtquick2/qtquick2.pro1
-rw-r--r--src/imports/settings/plugins.qmltypes3
-rw-r--r--src/imports/settings/qqmlsettings_p.h11
-rw-r--r--src/imports/statemachine/plugins.qmltypes12
-rw-r--r--src/imports/testlib/TestCase.qml16
-rw-r--r--src/imports/testlib/plugins.qmltypes21
-rw-r--r--src/imports/window/plugins.qmltypes19
-rw-r--r--src/imports/xmllistmodel/plugins.qmltypes268
-rw-r--r--src/imports/xmllistmodel/qqmlxmllistmodel.cpp4
-rw-r--r--src/imports/xmllistmodel/qqmlxmllistmodel_p.h11
-rw-r--r--src/particles/qquickage_p.h11
-rw-r--r--src/particles/qquickangledirection_p.h11
-rw-r--r--src/particles/qquickcumulativedirection_p.h11
-rw-r--r--src/particles/qquickcustomaffector_p.h11
-rw-r--r--src/particles/qquickcustomparticle.cpp4
-rw-r--r--src/particles/qquickcustomparticle_p.h11
-rw-r--r--src/particles/qquickdirection_p.h11
-rw-r--r--src/particles/qquickellipseextruder_p.h11
-rw-r--r--src/particles/qquickfriction_p.h11
-rw-r--r--src/particles/qquickgravity_p.h11
-rw-r--r--src/particles/qquickgroupgoal_p.h11
-rw-r--r--src/particles/qquickimageparticle.cpp4
-rw-r--r--src/particles/qquickimageparticle_p.h15
-rw-r--r--src/particles/qquickitemparticle_p.h11
-rw-r--r--src/particles/qquicklineextruder_p.h11
-rw-r--r--src/particles/qquickmaskextruder_p.h11
-rw-r--r--src/particles/qquickparticleaffector_p.h11
-rw-r--r--src/particles/qquickparticleemitter_p.h13
-rw-r--r--src/particles/qquickparticleextruder_p.h11
-rw-r--r--src/particles/qquickparticlegroup_p.h11
-rw-r--r--src/particles/qquickparticlepainter_p.h11
-rw-r--r--src/particles/qquickparticlesmodule_p.h11
-rw-r--r--src/particles/qquickparticlesystem.cpp5
-rw-r--r--src/particles/qquickparticlesystem_p.h11
-rw-r--r--src/particles/qquickpointattractor_p.h15
-rw-r--r--src/particles/qquickpointdirection_p.h11
-rw-r--r--src/particles/qquickrectangleextruder_p.h11
-rw-r--r--src/particles/qquickspritegoal_p.h11
-rw-r--r--src/particles/qquicktargetdirection_p.h11
-rw-r--r--src/particles/qquicktrailemitter_p.h13
-rw-r--r--src/particles/qquickturbulence.cpp10
-rw-r--r--src/particles/qquickturbulence_p.h11
-rw-r--r--src/particles/qquickv4particledata.cpp7
-rw-r--r--src/particles/qquickv4particledata_p.h13
-rw-r--r--src/particles/qquickwander_p.h13
-rw-r--r--src/particles/qtquickparticlesglobal_p.h11
-rw-r--r--src/plugins/plugins.pro2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp (renamed from src/qml/debugger/qdebugmessageservice.cpp)62
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.h (renamed from src/qml/debugger/qdebugmessageservice_p.h)21
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro34
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservice.json3
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp (renamed from src/plugins/qmltooling/shared/qmlinspectorconstants.h)46
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.h (renamed from src/qml/jsruntime/qv4qmlextensions_p.h)27
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp (renamed from src/qml/debugger/qqmlenginedebugservice.cpp)130
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h (renamed from src/qml/debugger/qqmlenginedebugservice_p.h)37
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp804
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.h (renamed from src/qml/debugger/qv4debugservice_p.h)73
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp (renamed from src/qml/qml/qqmlwatcher.cpp)6
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.h (renamed from src/qml/qml/qqmlwatcher_p.h)6
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp474
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h180
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp253
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h97
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp931
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h128
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/abstracttool.cpp (renamed from src/plugins/qmltooling/shared/abstracttool.cpp)4
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/abstracttool.h (renamed from src/plugins/qmltooling/shared/abstracttool.h)3
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp (renamed from src/plugins/qmltooling/shared/abstractviewinspector.cpp)21
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.h (renamed from src/plugins/qmltooling/shared/abstractviewinspector.h)12
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/highlight.cpp (renamed from src/plugins/qmltooling/qmldbg_qtquick2/highlight.cpp)6
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/highlight.h (renamed from src/plugins/qmltooling/qmldbg_qtquick2/highlight.h)5
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp (renamed from src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.cpp)13
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/inspecttool.h (renamed from src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.h)10
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro27
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp127
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.json3
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservicefactory.h (renamed from src/qml/debugger/qqmlinspectorinterface_p.h)30
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.cpp (renamed from src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp)14
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.h (renamed from src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.h)7
-rw-r--r--src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp157
-rw-r--r--src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.json3
-rw-r--r--src/plugins/qmltooling/qmldbg_local/qlocalclientconnectionfactory.h52
-rw-r--r--src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro20
-rw-r--r--src/plugins/qmltooling/qmldbg_native/qmldbg_native.pro12
-rw-r--r--src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp383
-rw-r--r--src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.json3
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro28
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp (renamed from src/qml/debugger/qqmlenginecontrolservice.cpp)18
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.h (renamed from src/qml/debugger/qqmlenginecontrolservice_p.h)8
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp123
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h (renamed from src/qml/debugger/qqmlconfigurabledebugservice_p_p.h)31
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp (renamed from src/qml/debugger/qqmlprofilerservice.cpp)183
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h (renamed from src/qml/debugger/qqmlprofilerservice_p.h)28
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.json3
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.cpp (renamed from src/qml/jsruntime/qv4qmlextensions.cpp)20
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.h62
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp (renamed from src/qml/debugger/qv4profileradapter.cpp)90
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h (renamed from src/qml/debugger/qv4profileradapter_p.h)15
-rw-r--r--src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro27
-rw-r--r--src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.cpp78
-rw-r--r--src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.h70
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro22
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp693
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qqmldebugserver.json3
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qqmldebugserverfactory.h65
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pri14
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro18
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp196
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h77
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.json3
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnectionfactory.h52
-rw-r--r--src/plugins/qmltooling/qmltooling.pro15
-rw-r--r--src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h106
-rw-r--r--src/plugins/qmltooling/shared/qqmldebugserver.h62
-rw-r--r--src/plugins/qmltooling/shared/qqmldebugserverconnection.h (renamed from src/qml/debugger/qqmldebugserverconnection_p.h)26
-rw-r--r--src/qml/Qt5QmlConfigExtras.cmake.in5
-rw-r--r--src/qml/animations/qabstractanimationjob_p.h11
-rw-r--r--src/qml/animations/qanimationgroupjob_p.h11
-rw-r--r--src/qml/animations/qanimationjobutil_p.h11
-rw-r--r--src/qml/animations/qcontinuinganimationgroupjob_p.h11
-rw-r--r--src/qml/animations/qparallelanimationgroupjob_p.h11
-rw-r--r--src/qml/animations/qpauseanimationjob_p.h11
-rw-r--r--src/qml/animations/qsequentialanimationgroupjob_p.h11
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp37
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h16
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp154
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h20
-rw-r--r--src/qml/compiler/qv4codegen.cpp3
-rw-r--r--src/qml/compiler/qv4codegen_p.h11
-rw-r--r--src/qml/compiler/qv4compileddata.cpp2
-rw-r--r--src/qml/compiler/qv4compileddata_p.h11
-rw-r--r--src/qml/compiler/qv4compiler.cpp7
-rw-r--r--src/qml/compiler/qv4compiler_p.h11
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h105
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp110
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h19
-rw-r--r--src/qml/compiler/qv4isel_p.cpp55
-rw-r--r--src/qml/compiler/qv4isel_p.h19
-rw-r--r--src/qml/compiler/qv4isel_util_p.h11
-rw-r--r--src/qml/compiler/qv4jsir.cpp24
-rw-r--r--src/qml/compiler/qv4jsir_p.h65
-rw-r--r--src/qml/compiler/qv4ssa.cpp165
-rw-r--r--src/qml/compiler/qv4ssa_p.h11
-rw-r--r--src/qml/debugger/debugger.pri31
-rw-r--r--src/qml/debugger/qqmlconfigurabledebugservice.cpp88
-rw-r--r--src/qml/debugger/qqmldebug.cpp122
-rw-r--r--src/qml/debugger/qqmldebug.h2
-rw-r--r--src/qml/debugger/qqmldebugconnector.cpp160
-rw-r--r--src/qml/debugger/qqmldebugconnector_p.h98
-rw-r--r--src/qml/debugger/qqmldebugpluginmanager_p.h95
-rw-r--r--src/qml/debugger/qqmldebugserver.cpp787
-rw-r--r--src/qml/debugger/qqmldebugserver_p.h104
-rw-r--r--src/qml/debugger/qqmldebugservice.cpp252
-rw-r--r--src/qml/debugger/qqmldebugservice_p.h42
-rw-r--r--src/qml/debugger/qqmldebugservicefactory_p.h (renamed from src/qml/debugger/qqmldebugservice_p_p.h)24
-rw-r--r--src/qml/debugger/qqmldebugserviceinterfaces.cpp44
-rw-r--r--src/qml/debugger/qqmldebugserviceinterfaces_p.h146
-rw-r--r--src/qml/debugger/qqmlinspectorservice.cpp181
-rw-r--r--src/qml/debugger/qqmlprofiler.cpp85
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h37
-rw-r--r--src/qml/debugger/qv4debugservice.cpp1265
-rw-r--r--src/qml/doc/qtqml.qdocconf2
-rw-r--r--src/qml/doc/snippets/qml/qtBinding.2.qml2
-rw-r--r--src/qml/doc/src/cppintegration/definetypes.qdoc3
-rw-r--r--src/qml/doc/src/cppintegration/exposecppattributes.qdoc4
-rw-r--r--src/qml/doc/src/external-resources.qdoc7
-rw-r--r--src/qml/doc/src/javascript/hostenvironment.qdoc2
-rw-r--r--src/qml/doc/src/javascript/qmlglobalobject.qdoc2
-rw-r--r--src/qml/doc/src/javascript/resources.qdoc14
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/basics.qdoc2
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc3
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/propertybinding.qdoc2
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/signals.qdoc4
-rw-r--r--src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc2
-rw-r--r--src/qml/jit/qv4assembler.cpp24
-rw-r--r--src/qml/jit/qv4assembler_p.h57
-rw-r--r--src/qml/jit/qv4binop.cpp63
-rw-r--r--src/qml/jit/qv4binop_p.h11
-rw-r--r--src/qml/jit/qv4isel_masm.cpp222
-rw-r--r--src/qml/jit/qv4isel_masm_p.h19
-rw-r--r--src/qml/jit/qv4regalloc.cpp47
-rw-r--r--src/qml/jit/qv4regalloc_p.h11
-rw-r--r--src/qml/jit/qv4registerinfo_p.h11
-rw-r--r--src/qml/jit/qv4targetplatform_p.h76
-rw-r--r--src/qml/jit/qv4unop_p.h11
-rw-r--r--src/qml/jsapi/qjsengine.cpp139
-rw-r--r--src/qml/jsapi/qjsengine.h16
-rw-r--r--src/qml/jsapi/qjsvalue.cpp33
-rw-r--r--src/qml/jsapi/qjsvalue_p.h2
-rw-r--r--src/qml/jsapi/qjsvalueiterator.cpp39
-rw-r--r--src/qml/jsapi/qjsvalueiterator_p.h21
-rw-r--r--src/qml/jsruntime/jsruntime.pri6
-rw-r--r--src/qml/jsruntime/qv4alloca_p.h11
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp62
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h24
-rw-r--r--src/qml/jsruntime/qv4arraybuffer.cpp27
-rw-r--r--src/qml/jsruntime/qv4arraybuffer_p.h20
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp139
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h64
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp37
-rw-r--r--src/qml/jsruntime/qv4arrayobject_p.h15
-rw-r--r--src/qml/jsruntime/qv4booleanobject.cpp19
-rw-r--r--src/qml/jsruntime/qv4booleanobject_p.h15
-rw-r--r--src/qml/jsruntime/qv4context.cpp403
-rw-r--r--src/qml/jsruntime/qv4context_p.h83
-rw-r--r--src/qml/jsruntime/qv4dataview.cpp44
-rw-r--r--src/qml/jsruntime/qv4dataview_p.h20
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp175
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h41
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp645
-rw-r--r--src/qml/jsruntime/qv4debugging_p.h140
-rw-r--r--src/qml/jsruntime/qv4engine.cpp826
-rw-r--r--src/qml/jsruntime/qv4engine_p.h382
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp214
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h124
-rw-r--r--src/qml/jsruntime/qv4executableallocator_p.h11
-rw-r--r--src/qml/jsruntime/qv4function.cpp35
-rw-r--r--src/qml/jsruntime/qv4function_p.h18
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp261
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h87
-rw-r--r--src/qml/jsruntime/qv4global_p.h18
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp87
-rw-r--r--src/qml/jsruntime/qv4globalobject_p.h15
-rw-r--r--src/qml/jsruntime/qv4identifier_p.h11
-rw-r--r--src/qml/jsruntime/qv4identifiertable.cpp16
-rw-r--r--src/qml/jsruntime/qv4identifiertable_p.h17
-rw-r--r--src/qml/jsruntime/qv4include.cpp35
-rw-r--r--src/qml/jsruntime/qv4include_p.h8
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp87
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h14
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp162
-rw-r--r--src/qml/jsruntime/qv4jsonobject_p.h65
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp161
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h31
-rw-r--r--src/qml/jsruntime/qv4managed.cpp30
-rw-r--r--src/qml/jsruntime/qv4managed_p.h134
-rw-r--r--src/qml/jsruntime/qv4math_p.h11
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp14
-rw-r--r--src/qml/jsruntime/qv4mathobject_p.h13
-rw-r--r--src/qml/jsruntime/qv4memberdata.cpp31
-rw-r--r--src/qml/jsruntime/qv4memberdata_p.h14
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp21
-rw-r--r--src/qml/jsruntime/qv4numberobject_p.h15
-rw-r--r--src/qml/jsruntime/qv4object.cpp376
-rw-r--r--src/qml/jsruntime/qv4object_p.h199
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp47
-rw-r--r--src/qml/jsruntime/qv4objectiterator_p.h24
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp78
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h15
-rw-r--r--src/qml/jsruntime/qv4persistent.cpp95
-rw-r--r--src/qml/jsruntime/qv4persistent_p.h39
-rw-r--r--src/qml/jsruntime/qv4profiling.cpp47
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h22
-rw-r--r--src/qml/jsruntime/qv4property_p.h24
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp320
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h45
-rw-r--r--src/qml/jsruntime/qv4regexp.cpp25
-rw-r--r--src/qml/jsruntime/qv4regexp_p.h14
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp117
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h50
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp328
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h47
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h205
-rw-r--r--src/qml/jsruntime/qv4script.cpp164
-rw-r--r--src/qml/jsruntime/qv4script_p.h61
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp51
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h5
-rw-r--r--src/qml/jsruntime/qv4serialize.cpp22
-rw-r--r--src/qml/jsruntime/qv4serialize_p.h2
-rw-r--r--src/qml/jsruntime/qv4sparsearray.cpp11
-rw-r--r--src/qml/jsruntime/qv4sparsearray_p.h23
-rw-r--r--src/qml/jsruntime/qv4string.cpp4
-rw-r--r--src/qml/jsruntime/qv4string_p.h25
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp100
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h39
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp57
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h30
-rw-r--r--src/qml/jsruntime/qv4util_p.h11
-rw-r--r--src/qml/jsruntime/qv4value.cpp78
-rw-r--r--src/qml/jsruntime/qv4value_inl_p.h293
-rw-r--r--src/qml/jsruntime/qv4value_p.h472
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp15
-rw-r--r--src/qml/jsruntime/qv4variantobject_p.h9
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp83
-rw-r--r--src/qml/jsruntime/qv4vme_moth_p.h11
-rw-r--r--src/qml/memory/memory.pri14
-rw-r--r--src/qml/memory/qv4heap_p.h140
-rw-r--r--src/qml/memory/qv4mm.cpp (renamed from src/qml/jsruntime/qv4mm.cpp)181
-rw-r--r--src/qml/memory/qv4mm_p.h (renamed from src/qml/jsruntime/qv4mm_p.h)188
-rw-r--r--src/qml/parser/qqmljs.g19
-rw-r--r--src/qml/parser/qqmljsast_p.h8
-rw-r--r--src/qml/parser/qqmljsglobal_p.h11
-rw-r--r--src/qml/parser/qqmljsmemorypool_p.h24
-rw-r--r--src/qml/qml.pro4
-rw-r--r--src/qml/qml/ftw/ftw.pri2
-rw-r--r--src/qml/qml/ftw/qqmlpool_p.h270
-rw-r--r--src/qml/qml/ftw/qqmlrefcount_p.h25
-rw-r--r--src/qml/qml/ftw/qqmlthread.cpp27
-rw-r--r--src/qml/qml/ftw/qqmlthread_p.h2
-rw-r--r--src/qml/qml/qml.pri4
-rw-r--r--src/qml/qml/qqmlabstractbinding.cpp170
-rw-r--r--src/qml/qml/qqmlabstractbinding_p.h140
-rw-r--r--src/qml/qml/qqmlabstractexpression.cpp93
-rw-r--r--src/qml/qml/qqmlabstractexpression_p.h116
-rw-r--r--src/qml/qml/qqmlaccessors_p.h11
-rw-r--r--src/qml/qml/qqmlbinding.cpp434
-rw-r--r--src/qml/qml/qqmlbinding_p.h65
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp318
-rw-r--r--src/qml/qml/qqmlboundsignal_p.h78
-rw-r--r--src/qml/qml/qqmlcomponent.cpp132
-rw-r--r--src/qml/qml/qqmlcomponent.h5
-rw-r--r--src/qml/qml/qqmlcomponent_p.h2
-rw-r--r--src/qml/qml/qqmlcomponentattached_p.h11
-rw-r--r--src/qml/qml/qqmlcontext.cpp11
-rw-r--r--src/qml/qml/qqmlcontext.h1
-rw-r--r--src/qml/qml/qqmlcontext_p.h6
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp203
-rw-r--r--src/qml/qml/qqmlcontextwrapper_p.h36
-rw-r--r--src/qml/qml/qqmlcustomparser.cpp31
-rw-r--r--src/qml/qml/qqmlcustomparser_p.h18
-rw-r--r--src/qml/qml/qqmldata_p.h20
-rw-r--r--src/qml/qml/qqmldirparser.cpp30
-rw-r--r--src/qml/qml/qqmlengine.cpp161
-rw-r--r--src/qml/qml/qqmlengine.h4
-rw-r--r--src/qml/qml/qqmlengine_p.h34
-rw-r--r--src/qml/qml/qqmlexpression.cpp34
-rw-r--r--src/qml/qml/qqmlexpression_p.h12
-rw-r--r--src/qml/qml/qqmlfileselector.cpp6
-rw-r--r--src/qml/qml/qqmlfileselector_p.h2
-rw-r--r--src/qml/qml/qqmlglobal.cpp62
-rw-r--r--src/qml/qml/qqmlglobal_p.h41
-rw-r--r--src/qml/qml/qqmlimport.cpp85
-rw-r--r--src/qml/qml/qqmlimport_p.h2
-rw-r--r--src/qml/qml/qqmlinfo.cpp28
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp172
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h101
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp23
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h10
-rw-r--r--src/qml/qml/qqmllocale.cpp34
-rw-r--r--src/qml/qml/qqmllocale_p.h30
-rw-r--r--src/qml/qml/qqmlmemoryprofiler.cpp4
-rw-r--r--src/qml/qml/qqmlmemoryprofiler_p.h11
-rw-r--r--src/qml/qml/qqmlmetatype.cpp153
-rw-r--r--src/qml/qml/qqmlmetatype_p.h23
-rw-r--r--src/qml/qml/qqmlnotifier_p.h23
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp111
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h17
-rw-r--r--src/qml/qml/qqmlopenmetaobject.cpp55
-rw-r--r--src/qml/qml/qqmlopenmetaobject_p.h16
-rw-r--r--src/qml/qml/qqmlplatform_p.h11
-rw-r--r--src/qml/qml/qqmlproperty.cpp474
-rw-r--r--src/qml/qml/qqmlproperty_p.h38
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp166
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h25
-rw-r--r--src/qml/qml/qqmlpropertyvalueinterceptor_p.h2
-rw-r--r--src/qml/qml/qqmlproxymetaobject.cpp6
-rw-r--r--src/qml/qml/qqmlproxymetaobject_p.h2
-rw-r--r--src/qml/qml/qqmlscriptstring_p.h11
-rw-r--r--src/qml/qml/qqmltypeloader.cpp201
-rw-r--r--src/qml/qml/qqmltypeloader_p.h15
-rw-r--r--src/qml/qml/qqmltypenamecache.cpp2
-rw-r--r--src/qml/qml/qqmltypenotavailable_p.h11
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp29
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h6
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp4
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h2
-rw-r--r--src/qml/qml/qqmlvaluetypeproxybinding.cpp97
-rw-r--r--src/qml/qml/qqmlvaluetypeproxybinding_p.h20
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp105
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h7
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp1202
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h124
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp305
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp176
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h13
-rw-r--r--src/qml/qml/v8/qv4domerrors.cpp2
-rw-r--r--src/qml/qml/v8/qv4sqlerrors.cpp2
-rw-r--r--src/qml/qml/v8/qv8engine.cpp86
-rw-r--r--src/qml/qml/v8/qv8engine_p.h27
-rw-r--r--src/qml/types/qqmlbind.cpp137
-rw-r--r--src/qml/types/qqmlbind_p.h11
-rw-r--r--src/qml/types/qqmlconnections.cpp2
-rw-r--r--src/qml/types/qqmlconnections_p.h11
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp65
-rw-r--r--src/qml/types/qqmldelegatemodel_p.h13
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h9
-rw-r--r--src/qml/types/qqmlinstantiator.cpp4
-rw-r--r--src/qml/types/qqmlinstantiator_p.h11
-rw-r--r--src/qml/types/qqmlitemmodels.qdoc40
-rw-r--r--src/qml/types/qqmlitemselectionmodel.qdoc4
-rw-r--r--src/qml/types/qqmllistmodel.cpp214
-rw-r--r--src/qml/types/qqmllistmodel_p.h17
-rw-r--r--src/qml/types/qqmllistmodel_p_p.h77
-rw-r--r--src/qml/types/qqmlmodelsmodule.cpp1
-rw-r--r--src/qml/types/qqmlmodelsmodule_p.h11
-rw-r--r--src/qml/types/qqmlobjectmodel.cpp204
-rw-r--r--src/qml/types/qqmlobjectmodel_p.h26
-rw-r--r--src/qml/types/qqmltimer_p.h11
-rw-r--r--src/qml/types/qquickpackage_p.h11
-rw-r--r--src/qml/types/qquickworkerscript.cpp28
-rw-r--r--src/qml/util/qqmladaptormodel.cpp23
-rw-r--r--src/qml/util/qqmladaptormodel_p.h11
-rw-r--r--src/qml/util/qqmllistaccessor_p.h11
-rw-r--r--src/qml/util/qqmllistcompositor_p.h12
-rw-r--r--src/qml/util/qqmlpropertymap.cpp3
-rw-r--r--src/qmldevtools/qmldevtools.pro1
-rw-r--r--src/qmldevtools/qtqmldevtoolsglobal_p.h17
-rw-r--r--src/qmltest/qmltest.pro4
-rw-r--r--src/qmltest/qtestoptions_p.h11
-rw-r--r--src/qmltest/quicktest.cpp2
-rw-r--r--src/qmltest/quicktest.h11
-rw-r--r--src/qmltest/quicktestevent.cpp45
-rw-r--r--src/qmltest/quicktestevent_p.h14
-rw-r--r--src/qmltest/quicktestresult.cpp21
-rw-r--r--src/qmltest/quicktestresult_p.h13
-rw-r--r--src/quick/accessible/qaccessiblequickitem.cpp9
-rw-r--r--src/quick/accessible/qaccessiblequickitem_p.h11
-rw-r--r--src/quick/accessible/qaccessiblequickview_p.h11
-rw-r--r--src/quick/accessible/qquickaccessiblefactory_p.h11
-rw-r--r--src/quick/designer/designer.pri25
-rw-r--r--src/quick/designer/qqmldesignermetaobject.cpp340
-rw-r--r--src/quick/designer/qqmldesignermetaobject_p.h105
-rw-r--r--src/quick/designer/qquickdesignercustomobjectdata.cpp286
-rw-r--r--src/quick/designer/qquickdesignercustomobjectdata_p.h100
-rw-r--r--src/quick/designer/qquickdesignersupport.cpp (renamed from src/quick/designer/designersupport.cpp)96
-rw-r--r--src/quick/designer/qquickdesignersupport_p.h (renamed from src/quick/designer/designersupport.h)22
-rw-r--r--src/quick/designer/qquickdesignersupportitems.cpp320
-rw-r--r--src/quick/designer/qquickdesignersupportitems_p.h (renamed from src/qml/debugger/qqmlconfigurabledebugservice_p.h)50
-rw-r--r--src/quick/designer/qquickdesignersupportmetainfo.cpp (renamed from src/qml/qml/ftw/qqmlpool.cpp)63
-rw-r--r--src/quick/designer/qquickdesignersupportmetainfo_p.h64
-rw-r--r--src/quick/designer/qquickdesignersupportproperties.cpp233
-rw-r--r--src/quick/designer/qquickdesignersupportproperties_p.h98
-rw-r--r--src/quick/designer/qquickdesignersupportpropertychanges.cpp135
-rw-r--r--src/quick/designer/qquickdesignersupportpropertychanges_p.h70
-rw-r--r--src/quick/designer/qquickdesignersupportstates.cpp119
-rw-r--r--src/quick/designer/qquickdesignersupportstates_p.h76
-rw-r--r--src/quick/designer/qquickdesignerwindowmanager.cpp (renamed from src/quick/designer/designerwindowmanager.cpp)25
-rw-r--r--src/quick/designer/qquickdesignerwindowmanager_p.h (renamed from src/quick/designer/designerwindowmanager_p.h)4
-rw-r--r--src/quick/doc/qtquick.qdocconf2
-rw-r--r--src/quick/doc/src/concepts/effects/sprites.qdoc7
-rw-r--r--src/quick/doc/src/concepts/effects/transformations.qdoc2
-rw-r--r--src/quick/doc/src/concepts/input/textinput.qdoc7
-rw-r--r--src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc17
-rw-r--r--src/quick/doc/src/concepts/positioning/anchors.qdoc2
-rw-r--r--src/quick/doc/src/concepts/positioning/layouts.qdoc3
-rw-r--r--src/quick/doc/src/concepts/statesanimations/animations.qdoc30
-rw-r--r--src/quick/doc/src/concepts/statesanimations/states.qdoc3
-rw-r--r--src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc6
-rw-r--r--src/quick/doc/src/examples.qdoc2
-rw-r--r--src/quick/items/context2d/qquickcanvascontext_p.h11
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp21
-rw-r--r--src/quick/items/context2d/qquickcanvasitem_p.h15
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp81
-rw-r--r--src/quick/items/context2d/qquickcontext2d_p.h13
-rw-r--r--src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h11
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture_p.h11
-rw-r--r--src/quick/items/context2d/qquickcontext2dtile_p.h11
-rw-r--r--src/quick/items/items.pri1
-rw-r--r--src/quick/items/qquickaccessibleattached_p.h11
-rw-r--r--src/quick/items/qquickanchors.cpp28
-rw-r--r--src/quick/items/qquickanchors_p.h11
-rw-r--r--src/quick/items/qquickanimatedimage_p.h11
-rw-r--r--src/quick/items/qquickanimatedsprite_p.h13
-rw-r--r--src/quick/items/qquickborderimage_p.h13
-rw-r--r--src/quick/items/qquickclipnode_p.h11
-rw-r--r--src/quick/items/qquickdrag.cpp1
-rw-r--r--src/quick/items/qquickdrag_p.h14
-rw-r--r--src/quick/items/qquickdroparea.cpp4
-rw-r--r--src/quick/items/qquickdroparea_p.h14
-rw-r--r--src/quick/items/qquickevents.cpp5
-rw-r--r--src/quick/items/qquickflickable.cpp47
-rw-r--r--src/quick/items/qquickflickable_p.h13
-rw-r--r--src/quick/items/qquickflickable_p_p.h1
-rw-r--r--src/quick/items/qquickflickablebehavior_p.h11
-rw-r--r--src/quick/items/qquickflipable.cpp17
-rw-r--r--src/quick/items/qquickflipable_p.h13
-rw-r--r--src/quick/items/qquickfocusscope_p.h11
-rw-r--r--src/quick/items/qquickframebufferobject.cpp31
-rw-r--r--src/quick/items/qquickframebufferobject.h5
-rw-r--r--src/quick/items/qquickgridview.cpp14
-rw-r--r--src/quick/items/qquickgridview_p.h15
-rw-r--r--src/quick/items/qquickimage.cpp5
-rw-r--r--src/quick/items/qquickimage_p.h19
-rw-r--r--src/quick/items/qquickimagebase.cpp70
-rw-r--r--src/quick/items/qquickimagebase_p.h13
-rw-r--r--src/quick/items/qquickimplicitsizeitem_p.h11
-rw-r--r--src/quick/items/qquickimplicitsizeitem_p_p.h2
-rw-r--r--src/quick/items/qquickitem.cpp329
-rw-r--r--src/quick/items/qquickitem.h2
-rw-r--r--src/quick/items/qquickitem_p.h50
-rw-r--r--src/quick/items/qquickitemanimation_p.h13
-rw-r--r--src/quick/items/qquickitemchangelistener_p.h8
-rw-r--r--src/quick/items/qquickitemsmodule.cpp21
-rw-r--r--src/quick/items/qquickitemsmodule_p.h11
-rw-r--r--src/quick/items/qquickitemview.cpp119
-rw-r--r--src/quick/items/qquickitemview_p.h24
-rw-r--r--src/quick/items/qquickitemview_p_p.h23
-rw-r--r--src/quick/items/qquickitemviewtransition.cpp1
-rw-r--r--src/quick/items/qquickitemviewtransition_p.h23
-rw-r--r--src/quick/items/qquicklistview.cpp166
-rw-r--r--src/quick/items/qquicklistview_p.h25
-rw-r--r--src/quick/items/qquickloader.cpp9
-rw-r--r--src/quick/items/qquickloader_p.h13
-rw-r--r--src/quick/items/qquickloader_p_p.h3
-rw-r--r--src/quick/items/qquickmousearea.cpp1
-rw-r--r--src/quick/items/qquickmousearea_p.h11
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp14
-rw-r--r--src/quick/items/qquickmultipointtoucharea_p.h12
-rw-r--r--src/quick/items/qquickopenglinfo_p.h3
-rw-r--r--src/quick/items/qquickpainteditem.cpp126
-rw-r--r--src/quick/items/qquickpainteditem.h8
-rw-r--r--src/quick/items/qquickpainteditem_p.h14
-rw-r--r--src/quick/items/qquickpathview.cpp169
-rw-r--r--src/quick/items/qquickpathview_p.h18
-rw-r--r--src/quick/items/qquickpathview_p_p.h5
-rw-r--r--src/quick/items/qquickpincharea_p.h13
-rw-r--r--src/quick/items/qquickpositioners.cpp319
-rw-r--r--src/quick/items/qquickpositioners_p.h57
-rw-r--r--src/quick/items/qquickpositioners_p_p.h23
-rw-r--r--src/quick/items/qquickrectangle_p.h15
-rw-r--r--src/quick/items/qquickrendercontrol.cpp20
-rw-r--r--src/quick/items/qquickrendercontrol_p.h1
-rw-r--r--src/quick/items/qquickrepeater.cpp47
-rw-r--r--src/quick/items/qquickrepeater_p.h11
-rw-r--r--src/quick/items/qquickscalegrid_p_p.h12
-rw-r--r--src/quick/items/qquickscreen_p.h11
-rw-r--r--src/quick/items/qquickshadereffect_p.h15
-rw-r--r--src/quick/items/qquickshadereffectmesh_p.h11
-rw-r--r--src/quick/items/qquickshadereffectnode.cpp6
-rw-r--r--src/quick/items/qquickshadereffectnode_p.h11
-rw-r--r--src/quick/items/qquickshadereffectsource.cpp34
-rw-r--r--src/quick/items/qquickshadereffectsource_p.h27
-rw-r--r--src/quick/items/qquicksprite_p.h11
-rw-r--r--src/quick/items/qquickspriteengine_p.h11
-rw-r--r--src/quick/items/qquickspritesequence_p.h11
-rw-r--r--src/quick/items/qquickstateoperations.cpp201
-rw-r--r--src/quick/items/qquickstateoperations_p.h19
-rw-r--r--src/quick/items/qquicktext.cpp438
-rw-r--r--src/quick/items/qquicktext_p.h62
-rw-r--r--src/quick/items/qquicktext_p_p.h61
-rw-r--r--src/quick/items/qquicktextcontrol.cpp22
-rw-r--r--src/quick/items/qquicktextcontrol_p_p.h3
-rw-r--r--src/quick/items/qquicktextdocument.cpp148
-rw-r--r--src/quick/items/qquicktextdocument_p.h101
-rw-r--r--src/quick/items/qquicktextedit.cpp303
-rw-r--r--src/quick/items/qquicktextedit_p.h66
-rw-r--r--src/quick/items/qquicktextedit_p_p.h35
-rw-r--r--src/quick/items/qquicktextinput.cpp479
-rw-r--r--src/quick/items/qquicktextinput_p.h96
-rw-r--r--src/quick/items/qquicktextinput_p_p.h28
-rw-r--r--src/quick/items/qquicktextnode.cpp45
-rw-r--r--src/quick/items/qquicktextnode_p.h15
-rw-r--r--src/quick/items/qquicktextnodeengine.cpp5
-rw-r--r--src/quick/items/qquicktextnodeengine_p.h13
-rw-r--r--src/quick/items/qquicktranslate_p.h11
-rw-r--r--src/quick/items/qquickview.cpp33
-rw-r--r--src/quick/items/qquickview.h3
-rw-r--r--src/quick/items/qquickview_p.h23
-rw-r--r--src/quick/items/qquickwindow.cpp178
-rw-r--r--src/quick/items/qquickwindow.h8
-rw-r--r--src/quick/items/qquickwindow_p.h2
-rw-r--r--src/quick/items/qquickwindowattached_p.h11
-rw-r--r--src/quick/items/qquickwindowmodule_p.h11
-rw-r--r--src/quick/qtquick2.cpp16
-rw-r--r--src/quick/qtquick2_p.h11
-rw-r--r--src/quick/scenegraph/coreapi/qsgabstractrenderer_p.h11
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp87
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h35
-rw-r--r--src/quick/scenegraph/coreapi/qsggeometry_p.h11
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterial.cpp2
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterialshader_p.h11
-rw-r--r--src/quick/scenegraph/coreapi/qsgnode.cpp2
-rw-r--r--src/quick/scenegraph/coreapi/qsgnode_p.h11
-rw-r--r--src/quick/scenegraph/coreapi/qsgnodeupdater.cpp18
-rw-r--r--src/quick/scenegraph/coreapi/qsgnodeupdater_p.h11
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer.cpp11
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer_p.h11
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp4
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h14
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp105
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h21
-rw-r--r--src/quick/scenegraph/qsgcontextplugin_p.h11
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h11
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.cpp13
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.h11
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p_p.h11
-rw-r--r--src/quick/scenegraph/qsgdefaultimagenode.cpp5
-rw-r--r--src/quick/scenegraph/qsgdefaultimagenode_p.h11
-rw-r--r--src/quick/scenegraph/qsgdefaultlayer.cpp25
-rw-r--r--src/quick/scenegraph/qsgdefaultlayer_p.h21
-rw-r--r--src/quick/scenegraph/qsgdefaultrectanglenode_p.h11
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode.cpp6
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp11
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.h11
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h11
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp35
-rw-r--r--src/quick/scenegraph/qsgrenderloop_p.h13
-rw-r--r--src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp655
-rw-r--r--src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h124
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp65
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop_p.h12
-rw-r--r--src/quick/scenegraph/qsgwindowsrenderloop.cpp3
-rw-r--r--src/quick/scenegraph/qsgwindowsrenderloop_p.h11
-rw-r--r--src/quick/scenegraph/scenegraph.pri2
-rw-r--r--src/quick/scenegraph/shaders/rendernode_core.frag4
-rw-r--r--src/quick/scenegraph/shaders/styledtext_core.frag6
-rw-r--r--src/quick/scenegraph/util/qsgareaallocator_p.h11
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp22
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture_p.h14
-rw-r--r--src/quick/scenegraph/util/qsgdefaultpainternode.cpp62
-rw-r--r--src/quick/scenegraph/util/qsgdefaultpainternode_p.h40
-rw-r--r--src/quick/scenegraph/util/qsgdepthstencilbuffer_p.h11
-rw-r--r--src/quick/scenegraph/util/qsgdistancefieldutil.cpp21
-rw-r--r--src/quick/scenegraph/util/qsgdistancefieldutil_p.h11
-rw-r--r--src/quick/scenegraph/util/qsgengine.cpp15
-rw-r--r--src/quick/scenegraph/util/qsgengine.h3
-rw-r--r--src/quick/scenegraph/util/qsgengine_p.h11
-rw-r--r--src/quick/scenegraph/util/qsgshadersourcebuilder.cpp2
-rw-r--r--src/quick/scenegraph/util/qsgshadersourcebuilder_p.h11
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp2
-rw-r--r--src/quick/scenegraph/util/qsgtexture_p.h11
-rw-r--r--src/quick/scenegraph/util/qsgtexturematerial_p.h11
-rw-r--r--src/quick/scenegraph/util/qsgtextureprovider.cpp4
-rw-r--r--src/quick/util/qquickanimation.cpp49
-rw-r--r--src/quick/util/qquickanimation_p.h15
-rw-r--r--src/quick/util/qquickanimation_p_p.h4
-rw-r--r--src/quick/util/qquickanimationcontroller_p.h11
-rw-r--r--src/quick/util/qquickanimator.cpp2
-rw-r--r--src/quick/util/qquickanimator_p.h14
-rw-r--r--src/quick/util/qquickanimator_p_p.h11
-rw-r--r--src/quick/util/qquickanimatorcontroller.cpp9
-rw-r--r--src/quick/util/qquickanimatorcontroller_p.h11
-rw-r--r--src/quick/util/qquickanimatorjob.cpp7
-rw-r--r--src/quick/util/qquickanimatorjob_p.h49
-rw-r--r--src/quick/util/qquickapplication_p.h11
-rw-r--r--src/quick/util/qquickbehavior_p.h11
-rw-r--r--src/quick/util/qquickfontloader.cpp58
-rw-r--r--src/quick/util/qquickfontloader_p.h13
-rw-r--r--src/quick/util/qquickfontmetrics.cpp3
-rw-r--r--src/quick/util/qquickfontmetrics_p.h11
-rw-r--r--src/quick/util/qquickglobal.cpp277
-rw-r--r--src/quick/util/qquickimageprovider.cpp131
-rw-r--r--src/quick/util/qquickimageprovider.h32
-rw-r--r--src/quick/util/qquickpath_p.h13
-rw-r--r--src/quick/util/qquickpathinterpolator_p.h11
-rw-r--r--src/quick/util/qquickpixmapcache.cpp245
-rw-r--r--src/quick/util/qquickpixmapcache_p.h11
-rw-r--r--src/quick/util/qquickprofiler.cpp24
-rw-r--r--src/quick/util/qquickprofiler_p.h2
-rw-r--r--src/quick/util/qquickpropertychanges.cpp34
-rw-r--r--src/quick/util/qquickpropertychanges_p.h11
-rw-r--r--src/quick/util/qquickshortcut.cpp31
-rw-r--r--src/quick/util/qquickshortcut_p.h5
-rw-r--r--src/quick/util/qquicksmoothedanimation_p.h13
-rw-r--r--src/quick/util/qquickspringanimation_p.h11
-rw-r--r--src/quick/util/qquickstate.cpp49
-rw-r--r--src/quick/util/qquickstate_p.h23
-rw-r--r--src/quick/util/qquickstate_p_p.h10
-rw-r--r--src/quick/util/qquickstatechangescript.cpp2
-rw-r--r--src/quick/util/qquickstatechangescript_p.h13
-rw-r--r--src/quick/util/qquickstategroup_p.h11
-rw-r--r--src/quick/util/qquickstyledtext.cpp4
-rw-r--r--src/quick/util/qquickstyledtext_p.h11
-rw-r--r--src/quick/util/qquicksvgparser_p.h11
-rw-r--r--src/quick/util/qquicksystempalette_p.h13
-rw-r--r--src/quick/util/qquicktextmetrics.cpp2
-rw-r--r--src/quick/util/qquicktextmetrics_p.h11
-rw-r--r--src/quick/util/qquicktimeline.cpp2
-rw-r--r--src/quick/util/qquicktransition.cpp2
-rw-r--r--src/quick/util/qquicktransition_p.h11
-rw-r--r--src/quick/util/qquicktransitionmanager.cpp28
-rw-r--r--src/quick/util/qquicktransitionmanager_p_p.h6
-rw-r--r--src/quick/util/qquickutilmodule.cpp10
-rw-r--r--src/quick/util/qquickutilmodule_p.h11
-rw-r--r--src/quick/util/qquickvalidator.cpp221
-rw-r--r--src/quick/util/qquickvalidator_p.h (renamed from src/qml/debugger/qqmlinspectorservice_p.h)65
-rw-r--r--src/quick/util/qquickvaluetypes.cpp10
-rw-r--r--src/quick/util/qquickvaluetypes_p.h26
-rw-r--r--src/quick/util/util.pri6
-rw-r--r--src/quickwidgets/qquickwidget.cpp109
-rw-r--r--src/quickwidgets/qquickwidget.h3
-rw-r--r--src/quickwidgets/qquickwidget_p.h13
708 files changed, 28148 insertions, 17570 deletions
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h b/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h
index 03f8e2d71a..734e779c70 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h
@@ -359,6 +359,12 @@ public:
}
}
+ void mul32(Address src, RegisterID dest)
+ {
+ load32(src, dataTempRegister);
+ mul32(dataTempRegister, dest);
+ }
+
void neg32(RegisterID srcDest)
{
m_assembler.subu(srcDest, MIPSRegisters::zero, srcDest);
@@ -420,6 +426,12 @@ public:
store32(dataTempRegister, dest.m_ptr);
}
+ void or32(Address src, RegisterID dest)
+ {
+ load32(src, dataTempRegister);
+ or32(dataTempRegister, dest);
+ }
+
void rshift32(RegisterID shiftAmount, RegisterID dest)
{
m_assembler.srav(dest, dest, shiftAmount);
@@ -615,6 +627,12 @@ public:
m_assembler.xorInsn(dest, src, immTempRegister);
}
+ void xor32(Address src, RegisterID dest)
+ {
+ load32(src, dataTempRegister);
+ xor32(dataTempRegister, dest);
+ }
+
void sqrtDouble(FPRegisterID src, FPRegisterID dst)
{
m_assembler.sqrtd(dst, src);
@@ -2519,6 +2537,18 @@ public:
m_assembler.cvtdw(dest, fpTempRegister);
}
+ void convertUInt32ToDouble(RegisterID src, FPRegisterID dest, RegisterID scratch)
+ {
+ m_assembler.mtc1(src, fpTempRegister);
+ m_assembler.bltz(src, 2);
+ m_assembler.cvtdw(dest, fpTempRegister);
+ m_assembler.beq(MIPSRegisters::zero, MIPSRegisters::zero, 4);
+ m_assembler.lui(scratch, 0x4f80);
+ m_assembler.mtc1(scratch, fpTempRegister);
+ m_assembler.cvtds(fpTempRegister, fpTempRegister);
+ m_assembler.addd(dest, dest, fpTempRegister);
+ }
+
void convertFloatToDouble(FPRegisterID src, FPRegisterID dst)
{
m_assembler.cvtds(dst, src);
@@ -2761,7 +2791,7 @@ public:
return CodeLocationLabel();
}
- static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart, Address, void* initialValue)
+ static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel, Address, void*)
{
UNREACHABLE_FOR_PLATFORM();
}
diff --git a/src/3rdparty/masm/disassembler/Mips32Disassembler.cpp b/src/3rdparty/masm/disassembler/Mips32Disassembler.cpp
new file mode 100644
index 0000000000..af0a73b2cb
--- /dev/null
+++ b/src/3rdparty/masm/disassembler/Mips32Disassembler.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 Cisco Systems, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CISCO SYSTEMS, INC. ``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 CISCO SYSTEMS, INC. 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.
+ */
+
+#include "config.h"
+#include "Disassembler.h"
+
+#if USE(MIPS32_DISASSEMBLER)
+
+#include "mips32/Mips32Opcode.h"
+#include "MacroAssemblerCodeRef.h"
+
+namespace JSC {
+
+bool tryToDisassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out)
+{
+ Mips32Opcode mipsOpcode;
+
+ uint32_t* currentPC = reinterpret_cast<uint32_t*>(reinterpret_cast<uintptr_t>(codePtr.executableAddress()) & ~3);
+ uint32_t* endPC = currentPC + (size / sizeof(uint32_t));
+
+ while (currentPC < endPC) {
+ char pcString[12];
+ snprintf(pcString, sizeof(pcString), "0x%x", reinterpret_cast<unsigned>(currentPC));
+ out.printf("%s%10s: %s\n", prefix, pcString, mipsOpcode.disassemble(currentPC));
+ currentPC++;
+ }
+
+ return true;
+}
+
+} // namespace JSC
+
+#endif // USE(MIPS32_DISASSEMBLER)
+
diff --git a/src/3rdparty/masm/disassembler/mips32/Mips32Opcode.cpp b/src/3rdparty/masm/disassembler/mips32/Mips32Opcode.cpp
new file mode 100644
index 0000000000..164217eb55
--- /dev/null
+++ b/src/3rdparty/masm/disassembler/mips32/Mips32Opcode.cpp
@@ -0,0 +1,620 @@
+/*
+ * Copyright (C) 2015 Cisco Systems, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CISCO SYSTEMS, INC. ``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 CISCO SYSTEMS, INC. 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.
+ */
+
+#include "config.h"
+
+#if USE(MIPS32_DISASSEMBLER)
+
+#include "Mips32Opcode.h"
+
+#include <stdio.h>
+
+#define OPCODE_FMT "%s\t"
+#define COP1_OPCODE_FMT "%s.%s\t"
+#define FORMAT_INSTR(_format, ...) \
+ snprintf(m_formatBuffer, bufferSize - 1, _format, ##__VA_ARGS__)
+
+const char *Mips32Opcode::registerName(uint8_t r)
+{
+ static const char *gpRegisters[] = {
+ "zero", "AT", "v0", "v1", "a0", "a1", "a2", "a3",
+ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ "t8", "t9", "kt0", "kt1", "gp", "sp", "s8", "ra"
+ };
+
+ return (r < sizeof(gpRegisters)) ? gpRegisters[r] : "invalid";
+}
+
+const char *Mips32Opcode::fpRegisterName(uint8_t r)
+{
+ static const char *fpRegisters[] = {
+ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
+ "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
+ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
+ "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
+ };
+
+ return (r < sizeof(fpRegisters)) ? fpRegisters[r] : "invalid";
+}
+
+void Mips32Opcode::formatSpecialEncodingOpcode(uint8_t op1, uint8_t op2, uint8_t dest, uint8_t shift, uint8_t function)
+{
+ const char *opcode;
+ OpcodePrintFormat format = Unknown;
+ switch (function) {
+ case 0x00:
+ format = RdRtSa;
+ opcode = "sll";
+ break;
+ case 0x02:
+ format = RdRtSa;
+ opcode = "srl";
+ break;
+ case 0x03:
+ format = RdRtSa;
+ opcode = "sra";
+ break;
+ case 0x04:
+ format = RdRtRs;
+ opcode = "sllv";
+ break;
+ case 0x06:
+ format = RdRtRs;
+ opcode = "srlv";
+ break;
+ case 0x07:
+ format = RdRtRs;
+ opcode = "srav";
+ break;
+ case 0x08:
+ format = Rs;
+ opcode = "jr";
+ break;
+ case 0x09:
+ format = (dest != 0x1f) ? RdRs : Rs;
+ opcode = "jalr";
+ break;
+ case 0x10:
+ format = Rd;
+ opcode = "mfhi";
+ break;
+ case 0x11:
+ format = Rs;
+ opcode = "mthi";
+ break;
+ case 0x12:
+ format = Rd;
+ opcode = "mflo";
+ break;
+ case 0x13:
+ format = Rs;
+ opcode = "mtlo";
+ break;
+ case 0x18:
+ format = RsRt;
+ opcode = "mult";
+ break;
+ case 0x19:
+ format = RsRt;
+ opcode = "multu";
+ break;
+ case 0x1a:
+ format = RsRt;
+ opcode = "div";
+ break;
+ case 0x1b:
+ format = RsRt;
+ opcode = "divu";
+ break;
+ case 0x20:
+ format = RdRsRt;
+ opcode = "add";
+ break;
+ case 0x21:
+ if (op2) {
+ format = RdRsRt;
+ opcode = "addu";
+ } else {
+ format = RdRs;
+ opcode = "move";
+ }
+ break;
+ case 0x22:
+ format = RdRsRt;
+ opcode = "sub";
+ break;
+ case 0x23:
+ format = RdRsRt;
+ opcode = "subu";
+ break;
+ case 0x24:
+ format = RdRsRt;
+ opcode = "and";
+ break;
+ case 0x25:
+ format = RdRsRt;
+ opcode = "or";
+ break;
+ case 0x26:
+ format = RdRsRt;
+ opcode = "xor";
+ break;
+ case 0x27:
+ format = RdRsRt;
+ opcode = "nor";
+ break;
+ case 0x2a:
+ format = RdRsRt;
+ opcode = "slt";
+ break;
+ case 0x2b:
+ format = RdRsRt;
+ opcode = "sltu";
+ break;
+ }
+
+ switch (format) {
+ case Rs:
+ FORMAT_INSTR(OPCODE_FMT "%s", opcode, registerName(op1));
+ break;
+ case Rd:
+ FORMAT_INSTR(OPCODE_FMT "%s", opcode, registerName(dest));
+ break;
+ case RdRs:
+ FORMAT_INSTR(OPCODE_FMT "%s, %s", opcode, registerName(dest), registerName(op1));
+ break;
+ case RsRt:
+ FORMAT_INSTR(OPCODE_FMT "%s, %s", opcode, registerName(op1), registerName(op2));
+ break;
+ case RdRtRs:
+ FORMAT_INSTR(OPCODE_FMT "%s, %s, %s", opcode, registerName(dest), registerName(op2), registerName(op1));
+ break;
+ case RdRsRt:
+ FORMAT_INSTR(OPCODE_FMT "%s, %s, %s", opcode, registerName(dest), registerName(op1), registerName(op2));
+ break;
+ case RdRtSa:
+ FORMAT_INSTR(OPCODE_FMT "%s, %s, %d", opcode, registerName(dest), registerName(op2), shift);
+ break;
+ default:
+ FORMAT_INSTR("unknown special encoding opcode 0x%x", function);
+ break;
+ }
+}
+
+void Mips32Opcode::formatSpecial2EncodingOpcode(uint8_t op1, uint8_t op2, uint8_t dest, uint8_t function)
+{
+ if (function == 0x02) {
+ FORMAT_INSTR(OPCODE_FMT "%s, %s, %s", "mul", registerName(dest), registerName(op1), registerName(op2));
+ return;
+ }
+
+ FORMAT_INSTR("unknown special2 encoding opcode 0x%x", function);
+}
+
+void Mips32Opcode::formatJumpEncodingOpcode(uint32_t iOp, uint32_t index, uint32_t* opcodePtr)
+{
+ if ((iOp != 0x02) && (iOp != 0x03)) {
+ FORMAT_INSTR("unknown jump encoding opcode 0x%x", iOp);
+ return;
+ }
+
+ FORMAT_INSTR(OPCODE_FMT "0x%x", (iOp == 0x02) ? "j" : "jal",
+ (reinterpret_cast<unsigned>(opcodePtr+1) & 0xf0000000) | (index << 2));
+}
+
+void Mips32Opcode::formatREGIMMEncodingOpcode(uint8_t rs, uint8_t rt, int16_t imm, uint32_t* opcodePtr)
+{
+ const char *opcodes[] = { "bltz", "bgez", "bltzl", "bgezl" };
+ if (rt < sizeof(opcodes))
+ FORMAT_INSTR(OPCODE_FMT "%s, 0x%x", opcodes[rt], registerName(rs), reinterpret_cast<unsigned>(opcodePtr+1) + (imm << 2));
+ else
+ FORMAT_INSTR("unknown REGIMM encoding opcode 0x%x", rt);
+}
+
+void Mips32Opcode::formatImmediateEncodingOpcode(uint32_t iOp, uint8_t rs, uint8_t rt, int16_t imm, uint32_t* opcodePtr)
+{
+ const char *opcode;
+ OpcodePrintFormat format = Unknown;
+ switch (iOp) {
+ case 0x04:
+ if (!rs && !rt) {
+ format = Addr;
+ opcode = "b";
+ } else {
+ format = RsRtAddr;
+ opcode = "beq";
+ }
+ break;
+ case 0x05:
+ format = RsRtAddr;
+ opcode = "bne";
+ break;
+ case 0x06:
+ format = RsRtAddr;
+ opcode = "blez";
+ break;
+ case 0x07:
+ format = RsRtAddr;
+ opcode = "bgtz";
+ break;
+ case 0x08:
+ format = RtRsImm;
+ opcode = "addi";
+ break;
+ case 0x09:
+ if (rs) {
+ format = RtRsImm;
+ opcode = "addiu";
+ } else {
+ format = RtUImm;
+ opcode = "li";
+ }
+ break;
+ case 0x0a:
+ format = RtRsImm;
+ opcode = "slti";
+ break;
+ case 0x0b:
+ format = RtRsImm;
+ opcode = "sltiu";
+ break;
+ case 0x0c:
+ format = RtRsImm;
+ opcode = "andi";
+ break;
+ case 0x0d:
+ format = RtRsImm;
+ opcode = "ori";
+ break;
+ case 0x0e:
+ format = RtRsImm;
+ opcode = "xori";
+ break;
+ case 0x0f:
+ format = RtUImm;
+ opcode = "lui";
+ break;
+ case 0x20:
+ format = RtOffsetBase;
+ opcode = "lb";
+ break;
+ case 0x21:
+ format = RtOffsetBase;
+ opcode = "lh";
+ break;
+ case 0x22:
+ format = RtOffsetBase;
+ opcode = "lwl";
+ break;
+ case 0x23:
+ format = RtOffsetBase;
+ opcode = "lw";
+ break;
+ case 0x24:
+ format = RtOffsetBase;
+ opcode = "lbu";
+ break;
+ case 0x25:
+ format = RtOffsetBase;
+ opcode = "lhu";
+ break;
+ case 0x26:
+ format = RtOffsetBase;
+ opcode = "lwr";
+ break;
+ case 0x28:
+ format = RtOffsetBase;
+ opcode = "sb";
+ break;
+ case 0x29:
+ format = RtOffsetBase;
+ opcode = "sh";
+ break;
+ case 0x2a:
+ format = RtOffsetBase;
+ opcode = "swl";
+ break;
+ case 0x2b:
+ format = RtOffsetBase;
+ opcode = "sw";
+ break;
+ case 0x2e:
+ format = RtOffsetBase;
+ opcode = "swr";
+ break;
+ case 0x35:
+ format = FtOffsetBase;
+ opcode = "ldc1";
+ break;
+ case 0x3d:
+ format = FtOffsetBase;
+ opcode = "sdc1";
+ break;
+ }
+
+ switch (format) {
+ case Addr:
+ FORMAT_INSTR(OPCODE_FMT "0x%x", opcode, reinterpret_cast<unsigned>(opcodePtr+1) + (imm << 2));
+ break;
+ case RtUImm:
+ FORMAT_INSTR(OPCODE_FMT "%s, 0x%hx", opcode, registerName(rt), imm);
+ break;
+ case RtRsImm:
+ FORMAT_INSTR(OPCODE_FMT "%s, %s, %d", opcode, registerName(rt), registerName(rs), imm);
+ break;
+ case RsRtAddr:
+ FORMAT_INSTR(OPCODE_FMT "%s, %s, 0x%x", opcode, registerName(rs), registerName(rt),
+ reinterpret_cast<unsigned>(opcodePtr+1) + (imm << 2));
+ break;
+ case RtOffsetBase:
+ FORMAT_INSTR(OPCODE_FMT "%s, %d(%s)", opcode, registerName(rt), imm, registerName(rs));
+ break;
+ case FtOffsetBase:
+ FORMAT_INSTR(OPCODE_FMT "%s, %d(%s)", opcode, fpRegisterName(rt), imm, registerName(rs));
+ break;
+ default:
+ FORMAT_INSTR("unknown immediate encoding opcode 0x%x", iOp);
+ break;
+ }
+}
+
+void Mips32Opcode::formatCOP1Opcode(uint8_t fmt, uint8_t ft, uint8_t fs, uint8_t fd, uint8_t func)
+{
+ const char *opcode;
+ const char *suffix;
+ OpcodePrintFormat format = Unknown;
+
+ if (fmt < 0x10) {
+ switch (fmt) {
+ case 0x00:
+ opcode = "mfc1";
+ break;
+ case 0x04:
+ opcode = "mtc1";
+ break;
+ default:
+ FORMAT_INSTR("unknown COP1 rs 0x%x", fmt);
+ return;
+ }
+ FORMAT_INSTR(OPCODE_FMT "%s, %s", opcode, registerName(ft), fpRegisterName(fs));
+ return;
+ }
+
+ switch (fmt) {
+ case 0x10:
+ suffix = "s";
+ break;
+ case 0x11:
+ suffix = "d";
+ break;
+ case 0x14:
+ suffix = "w";
+ break;
+ case 0x15:
+ suffix = "l";
+ break;
+ case 0x16:
+ suffix = "ps";
+ break;
+ default:
+ FORMAT_INSTR("unknown COP1 fmt 0x%x", fmt);
+ return;
+ }
+
+ switch (func) {
+ case 0x00:
+ format = FdFsFt;
+ opcode = "add";
+ break;
+ case 0x01:
+ format = FdFsFt;
+ opcode = "sub";
+ break;
+ case 0x02:
+ format = FdFsFt;
+ opcode = "mul";
+ break;
+ case 0x03:
+ format = FdFsFt;
+ opcode = "div";
+ break;
+ case 0x04:
+ format = FdFs;
+ opcode = "sqrt";
+ break;
+ case 0x05:
+ format = FdFs;
+ opcode = "abs";
+ break;
+ case 0x06:
+ format = FdFs;
+ opcode = "mov";
+ break;
+ case 0x07:
+ format = FdFs;
+ opcode = "neg";
+ break;
+ case 0x08:
+ format = FdFs;
+ opcode = "round.l";
+ break;
+ case 0x09:
+ format = FdFs;
+ opcode = "trunc.l";
+ break;
+ case 0x0a:
+ format = FdFs;
+ opcode = "ceil.l";
+ break;
+ case 0x0b:
+ format = FdFs;
+ opcode = "floor.l";
+ break;
+ case 0x0c:
+ format = FdFs;
+ opcode = "round.w";
+ break;
+ case 0x0d:
+ format = FdFs;
+ opcode = "trunc.w";
+ break;
+ case 0x0e:
+ format = FdFs;
+ opcode = "ceil.w";
+ break;
+ case 0x0f:
+ format = FdFs;
+ opcode = "floor.w";
+ break;
+ case 0x20:
+ format = FdFs;
+ opcode = "cvt.s";
+ break;
+ case 0x21:
+ format = FdFs;
+ opcode = "cvt.d";
+ break;
+ case 0x24:
+ format = FdFs;
+ opcode = "cvt.w";
+ break;
+ case 0x25:
+ format = FdFs;
+ opcode = "cvt.l";
+ break;
+ }
+
+ switch (format) {
+ case FdFs:
+ FORMAT_INSTR(COP1_OPCODE_FMT "%s, %s", opcode, suffix, fpRegisterName(fd), fpRegisterName(fs));
+ break;
+ case FdFsFt:
+ FORMAT_INSTR(COP1_OPCODE_FMT "%s, %s, %s", opcode, suffix, fpRegisterName(fd), fpRegisterName(fs), fpRegisterName(ft));
+ break;
+ default:
+ FORMAT_INSTR("unknown COP1 opcode 0x%x", func);
+ break;
+ }
+}
+
+void Mips32Opcode::formatCOP1FPCompareOpcode(uint8_t fmt, uint8_t ft, uint8_t fs, uint8_t cc, uint8_t cond)
+{
+ const char *suffix;
+ static const char *opcodes[] = {
+ "c.f", "c.un", "c.eq", "c.ueq", "c.olt", "c.ult", "c.ole", "c.ule",
+ "c.sf", "c.ngle", "c.seq", "c.ngl", "c.lt", "c.nge", "c.le", "c.ngt"
+ };
+ ASSERT(cond < sizeof(opcdoes));
+
+ switch (fmt) {
+ case 0x10:
+ suffix = "s";
+ break;
+ case 0x11:
+ suffix = "d";
+ break;
+ case 0x16:
+ suffix = "ps";
+ break;
+ default:
+ FORMAT_INSTR("unknown COP1 fmt 0x%x", fmt);
+ return;
+ }
+
+ if (!cc)
+ FORMAT_INSTR(COP1_OPCODE_FMT "%s, %s", opcodes[cond], suffix, fpRegisterName(fs), fpRegisterName(ft));
+ else
+ FORMAT_INSTR(COP1_OPCODE_FMT "%d, %s, %s", opcodes[cond], suffix, cc, fpRegisterName(fs), fpRegisterName(ft));
+}
+
+void Mips32Opcode::formatCOP1BCOpcode(uint8_t cc, uint8_t ndtf, int16_t offset, uint32_t* opcodePtr)
+{
+ static const char *opcodes[] = { "bc1f", "bc1t", "bc1fl", "bc1tl" };
+ ASSERT(ndtf < sizeof(opcodes));
+
+ if (!cc)
+ FORMAT_INSTR(OPCODE_FMT "0x%x", opcodes[ndtf], reinterpret_cast<unsigned>(opcodePtr+1) + (offset << 2));
+ else
+ FORMAT_INSTR(OPCODE_FMT "%d, 0x%x", opcodes[ndtf], cc, reinterpret_cast<unsigned>(opcodePtr+1) + (offset << 2));
+}
+
+const char* Mips32Opcode::disassemble(uint32_t* opcodePtr)
+{
+ uint32_t opcode = *opcodePtr;
+ uint32_t iOp = (opcode >> 26) & 0x3f;
+
+ if (!opcode)
+ FORMAT_INSTR(OPCODE_FMT, "nop");
+ else if (!iOp) {
+ uint8_t op1 = (opcode >> 21) & 0x1f;
+ uint8_t op2 = (opcode >> 16) & 0x1f;
+ uint8_t dst = (opcode >> 11) & 0x1f;
+ uint8_t shft = (opcode >> 6) & 0x1f;
+ uint8_t func = opcode & 0x3f;
+ formatSpecialEncodingOpcode(op1, op2, dst, shft, func);
+ } else if ((iOp == 0x02) || (iOp == 0x03)) {
+ uint32_t index = opcode & 0x3ffffff;
+ formatJumpEncodingOpcode(iOp, index, opcodePtr);
+ } else if (iOp == 0x11) {
+ uint8_t fmt = (opcode >> 21) & 0x1f;
+ if (fmt == 0x08) {
+ uint8_t cc = (opcode >> 18) & 0x07;
+ uint8_t ndtf = (opcode >> 16) & 0x03;
+ int16_t offset = opcode & 0xffff;
+ formatCOP1BCOpcode(cc, ndtf, offset, opcodePtr);
+ } else if ((opcode & 0xf0) == 0x30) {
+ uint8_t ft = (opcode >> 16) & 0x1f;
+ uint8_t fs = (opcode >> 11) & 0x1f;
+ uint8_t cc = (opcode >> 8) & 0x07;
+ uint8_t cond = opcode & 0x0f;
+ formatCOP1FPCompareOpcode(fmt, ft, fs, cc, cond);
+ } else {
+ uint8_t ft = (opcode >> 16) & 0x1f;
+ uint8_t fs = (opcode >> 11) & 0x1f;
+ uint8_t fd = (opcode >> 6) & 0x1f;
+ uint8_t func = opcode & 0x3f;
+ formatCOP1Opcode(fmt, ft, fs, fd, func);
+ }
+ } else if (iOp == 0x1c) {
+ uint8_t op1 = (opcode >> 21) & 0x1f;
+ uint8_t op2 = (opcode >> 16) & 0x1f;
+ uint8_t dst = (opcode >> 11) & 0x1f;
+ uint8_t func = opcode & 0x3f;
+ formatSpecial2EncodingOpcode(op1, op2, dst, func);
+ } else {
+ uint8_t rs = (opcode >> 21) & 0x1f;
+ uint8_t rt = (opcode >> 16) & 0x1f;
+ int16_t imm = opcode & 0xffff;
+ if (iOp == 0x01)
+ formatREGIMMEncodingOpcode(rs, rt, imm, opcodePtr);
+ else
+ formatImmediateEncodingOpcode(iOp, rs, rt, imm, opcodePtr);
+ }
+
+ return m_formatBuffer;
+}
+
+#endif // USE(MIPS32_DISASSEMBLER)
diff --git a/src/3rdparty/masm/disassembler/mips32/Mips32Opcode.h b/src/3rdparty/masm/disassembler/mips32/Mips32Opcode.h
new file mode 100644
index 0000000000..c63fb1109a
--- /dev/null
+++ b/src/3rdparty/masm/disassembler/mips32/Mips32Opcode.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2015 Cisco Systems, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CISCO SYSTEMS, INC. ``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 CISCO SYSTEMS, INC. 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.
+ */
+
+#ifndef _MIPS32Opcode_h_
+#define _MIPS32Opcode_h_
+
+#if USE(MIPS32_DISASSEMBLER)
+
+#include <stdint.h>
+#include <wtf/Assertions.h>
+
+class Mips32Opcode {
+public:
+ Mips32Opcode() {}
+
+ const char* disassemble(uint32_t*);
+
+private:
+ enum OpcodePrintFormat {
+ Unknown = 0,
+ Rs,
+ Rd,
+ Addr,
+ RdRs,
+ RsRt,
+ RtUImm,
+ RdRtRs,
+ RdRsRt,
+ RdRtSa,
+ RtRsImm,
+ RsRtAddr,
+ RtOffsetBase,
+ FdFs,
+ FdFsFt,
+ FtOffsetBase
+ };
+
+ const char *registerName(uint8_t r);
+ const char *fpRegisterName(uint8_t r);
+ void formatSpecialEncodingOpcode(uint8_t op1, uint8_t op2, uint8_t dest, uint8_t shift, uint8_t function);
+ void formatSpecial2EncodingOpcode(uint8_t op1, uint8_t op2, uint8_t dest, uint8_t function);
+ void formatJumpEncodingOpcode(uint32_t iOp, uint32_t index, uint32_t* opcodePtr);
+ void formatREGIMMEncodingOpcode(uint8_t rs, uint8_t rt, int16_t imm, uint32_t* opcodePtr);
+ void formatImmediateEncodingOpcode(uint32_t iOp, uint8_t rs, uint8_t rt, int16_t imm, uint32_t* opcodePtr);
+ void formatCOP1Opcode(uint8_t fmt, uint8_t ft, uint8_t fs, uint8_t fd, uint8_t func);
+ void formatCOP1FPCompareOpcode(uint8_t fmt, uint8_t ft, uint8_t fs, uint8_t cc, uint8_t cond);
+ void formatCOP1BCOpcode(uint8_t cc, uint8_t ndtf, int16_t offset, uint32_t* opcodePtr);
+
+ static const int bufferSize = 81;
+
+ char m_formatBuffer[bufferSize];
+};
+
+#endif
+
+#endif // _MIPS32Opcode_h_
diff --git a/src/3rdparty/masm/masm-defs.pri b/src/3rdparty/masm/masm-defs.pri
index d0980c5312..f09a8329c9 100644
--- a/src/3rdparty/masm/masm-defs.pri
+++ b/src/3rdparty/masm/masm-defs.pri
@@ -26,6 +26,7 @@ INCLUDEPATH += $$PWD
disassembler {
if(isEqual(QT_ARCH, "i386")|isEqual(QT_ARCH, "x86_64")): DEFINES += WTF_USE_UDIS86=1
if(isEqual(QT_ARCH, "arm")): DEFINES += WTF_USE_ARMV7_DISASSEMBLER=1
+ if(isEqual(QT_ARCH, "mips")): DEFINES += WTF_USE_MIPS32_DISASSEMBLER=1
} else {
DEFINES += WTF_USE_UDIS86=0
}
diff --git a/src/3rdparty/masm/masm.pri b/src/3rdparty/masm/masm.pri
index 3497650f0c..04548fe8a3 100644
--- a/src/3rdparty/masm/masm.pri
+++ b/src/3rdparty/masm/masm.pri
@@ -59,6 +59,9 @@ contains(DEFINES, WTF_USE_UDIS86=1) {
SOURCES += $$PWD/disassembler/ARMv7Disassembler.cpp
SOURCES += $$PWD/disassembler/ARMv7/ARMv7DOpcode.cpp
HEADERS += $$PWD/disassembler/ARMv7/ARMv7DOpcode.h
+SOURCES += $$PWD/disassembler/Mips32Disassembler.cpp
+SOURCES += $$PWD/disassembler/mips32/Mips32Opcode.cpp
+HEADERS += $$PWD/disassembler/mips32/Mips32Opcode.h
SOURCES += $$PWD/yarr/*.cpp
HEADERS += $$PWD/yarr/*.h
diff --git a/src/3rdparty/masm/stubs/Options.cpp b/src/3rdparty/masm/stubs/Options.cpp
index 3b13e32218..76da55c387 100644
--- a/src/3rdparty/masm/stubs/Options.cpp
+++ b/src/3rdparty/masm/stubs/Options.cpp
@@ -40,7 +40,7 @@ namespace JSC {
bool Options::showDisassembly()
{
- static bool showCode = !qgetenv("QV4_SHOW_ASM").isNull();
+ static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_ASM");
return showCode;
}
diff --git a/src/3rdparty/masm/wtf/FilePrintStream.cpp b/src/3rdparty/masm/wtf/FilePrintStream.cpp
index b5ab25e0bf..45f1565f46 100644
--- a/src/3rdparty/masm/wtf/FilePrintStream.cpp
+++ b/src/3rdparty/masm/wtf/FilePrintStream.cpp
@@ -38,7 +38,8 @@ FilePrintStream::~FilePrintStream()
{
if (m_adoptionMode == Borrow)
return;
- fclose(m_file);
+ if (m_file)
+ fclose(m_file);
}
PassOwnPtr<FilePrintStream> FilePrintStream::open(const char* filename, const char* mode)
diff --git a/src/3rdparty/masm/wtf/Platform.h b/src/3rdparty/masm/wtf/Platform.h
index 3e2a51379c..f0612fe50e 100644
--- a/src/3rdparty/masm/wtf/Platform.h
+++ b/src/3rdparty/masm/wtf/Platform.h
@@ -735,7 +735,7 @@
#define WTF_USE_UDIS86 1
#endif
-#if !defined(ENABLE_DISASSEMBLER) && (USE(UDIS86) || USE(ARMV7_DISASSEMBLER))
+#if !defined(ENABLE_DISASSEMBLER) && (USE(UDIS86) || USE(ARMV7_DISASSEMBLER) || USE(MIPS32_DISASSEMBLER))
#define ENABLE_DISASSEMBLER 1
#endif
diff --git a/src/imports/builtins.qmltypes b/src/imports/builtins.qmltypes
new file mode 100644
index 0000000000..cca1c20d54
--- /dev/null
+++ b/src/imports/builtins.qmltypes
@@ -0,0 +1,1605 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable -builtins'
+
+Module {
+ dependencies: []
+ Component {
+ name: "Qt"
+ Enum {
+ name: "GlobalColor"
+ values: {
+ "color0": 0,
+ "color1": 1,
+ "black": 2,
+ "white": 3,
+ "darkGray": 4,
+ "gray": 5,
+ "lightGray": 6,
+ "red": 7,
+ "green": 8,
+ "blue": 9,
+ "cyan": 10,
+ "magenta": 11,
+ "yellow": 12,
+ "darkRed": 13,
+ "darkGreen": 14,
+ "darkBlue": 15,
+ "darkCyan": 16,
+ "darkMagenta": 17,
+ "darkYellow": 18,
+ "transparent": 19
+ }
+ }
+ Enum {
+ name: "KeyboardModifiers"
+ values: {
+ "NoModifier": 0,
+ "ShiftModifier": 33554432,
+ "ControlModifier": 67108864,
+ "AltModifier": 134217728,
+ "MetaModifier": 268435456,
+ "KeypadModifier": 536870912,
+ "GroupSwitchModifier": 1073741824,
+ "KeyboardModifierMask": -33554432
+ }
+ }
+ Enum {
+ name: "MouseButtons"
+ values: {
+ "NoButton": 0,
+ "LeftButton": 1,
+ "RightButton": 2,
+ "MidButton": 4,
+ "MiddleButton": 4,
+ "BackButton": 8,
+ "XButton1": 8,
+ "ExtraButton1": 8,
+ "ForwardButton": 16,
+ "XButton2": 16,
+ "ExtraButton2": 16,
+ "TaskButton": 32,
+ "ExtraButton3": 32,
+ "ExtraButton4": 64,
+ "ExtraButton5": 128,
+ "ExtraButton6": 256,
+ "ExtraButton7": 512,
+ "ExtraButton8": 1024,
+ "ExtraButton9": 2048,
+ "ExtraButton10": 4096,
+ "ExtraButton11": 8192,
+ "ExtraButton12": 16384,
+ "ExtraButton13": 32768,
+ "ExtraButton14": 65536,
+ "ExtraButton15": 131072,
+ "ExtraButton16": 262144,
+ "ExtraButton17": 524288,
+ "ExtraButton18": 1048576,
+ "ExtraButton19": 2097152,
+ "ExtraButton20": 4194304,
+ "ExtraButton21": 8388608,
+ "ExtraButton22": 16777216,
+ "ExtraButton23": 33554432,
+ "ExtraButton24": 67108864,
+ "AllButtons": 134217727,
+ "MaxMouseButton": 67108864,
+ "MouseButtonMask": -1
+ }
+ }
+ Enum {
+ name: "Orientation"
+ values: {
+ "Horizontal": 1,
+ "Vertical": 2
+ }
+ }
+ Enum {
+ name: "Orientations"
+ values: {
+ "Horizontal": 1,
+ "Vertical": 2
+ }
+ }
+ Enum {
+ name: "FocusPolicy"
+ values: {
+ "NoFocus": 0,
+ "TabFocus": 1,
+ "ClickFocus": 2,
+ "StrongFocus": 11,
+ "WheelFocus": 15
+ }
+ }
+ Enum {
+ name: "TabFocusBehavior"
+ values: {
+ "NoTabFocus": 0,
+ "TabFocusTextControls": 1,
+ "TabFocusListControls": 2,
+ "TabFocusAllControls": 255
+ }
+ }
+ Enum {
+ name: "SortOrder"
+ values: {
+ "AscendingOrder": 0,
+ "DescendingOrder": 1
+ }
+ }
+ Enum {
+ name: "Alignment"
+ values: {
+ "AlignLeft": 1,
+ "AlignLeading": 1,
+ "AlignRight": 2,
+ "AlignTrailing": 2,
+ "AlignHCenter": 4,
+ "AlignJustify": 8,
+ "AlignAbsolute": 16,
+ "AlignHorizontal_Mask": 31,
+ "AlignTop": 32,
+ "AlignBottom": 64,
+ "AlignVCenter": 128,
+ "AlignBaseline": 256,
+ "AlignVertical_Mask": 480,
+ "AlignCenter": 132
+ }
+ }
+ Enum {
+ name: "TextElideMode"
+ values: {
+ "ElideLeft": 0,
+ "ElideRight": 1,
+ "ElideMiddle": 2,
+ "ElideNone": 3
+ }
+ }
+ Enum {
+ name: "WindowType"
+ values: {
+ "Widget": 0,
+ "Window": 1,
+ "Dialog": 3,
+ "Sheet": 5,
+ "Drawer": 7,
+ "Popup": 9,
+ "Tool": 11,
+ "ToolTip": 13,
+ "SplashScreen": 15,
+ "Desktop": 17,
+ "SubWindow": 18,
+ "ForeignWindow": 33,
+ "CoverWindow": 65,
+ "WindowType_Mask": 255,
+ "MSWindowsFixedSizeDialogHint": 256,
+ "MSWindowsOwnDC": 512,
+ "BypassWindowManagerHint": 1024,
+ "X11BypassWindowManagerHint": 1024,
+ "FramelessWindowHint": 2048,
+ "WindowTitleHint": 4096,
+ "WindowSystemMenuHint": 8192,
+ "WindowMinimizeButtonHint": 16384,
+ "WindowMaximizeButtonHint": 32768,
+ "WindowMinMaxButtonsHint": 49152,
+ "WindowContextHelpButtonHint": 65536,
+ "WindowShadeButtonHint": 131072,
+ "WindowStaysOnTopHint": 262144,
+ "WindowTransparentForInput": 524288,
+ "WindowOverridesSystemGestures": 1048576,
+ "WindowDoesNotAcceptFocus": 2097152,
+ "MaximizeUsingFullscreenGeometryHint": 4194304,
+ "CustomizeWindowHint": 33554432,
+ "WindowStaysOnBottomHint": 67108864,
+ "WindowCloseButtonHint": 134217728,
+ "MacWindowToolBarButtonHint": 268435456,
+ "BypassGraphicsProxyWidget": 536870912,
+ "NoDropShadowWindowHint": 1073741824,
+ "WindowFullscreenButtonHint": -2147483648,
+ "WindowOkButtonHint": 524288,
+ "WindowCancelButtonHint": 1048576
+ }
+ }
+ Enum {
+ name: "WindowFlags"
+ values: {
+ "Widget": 0,
+ "Window": 1,
+ "Dialog": 3,
+ "Sheet": 5,
+ "Drawer": 7,
+ "Popup": 9,
+ "Tool": 11,
+ "ToolTip": 13,
+ "SplashScreen": 15,
+ "Desktop": 17,
+ "SubWindow": 18,
+ "ForeignWindow": 33,
+ "CoverWindow": 65,
+ "WindowType_Mask": 255,
+ "MSWindowsFixedSizeDialogHint": 256,
+ "MSWindowsOwnDC": 512,
+ "BypassWindowManagerHint": 1024,
+ "X11BypassWindowManagerHint": 1024,
+ "FramelessWindowHint": 2048,
+ "WindowTitleHint": 4096,
+ "WindowSystemMenuHint": 8192,
+ "WindowMinimizeButtonHint": 16384,
+ "WindowMaximizeButtonHint": 32768,
+ "WindowMinMaxButtonsHint": 49152,
+ "WindowContextHelpButtonHint": 65536,
+ "WindowShadeButtonHint": 131072,
+ "WindowStaysOnTopHint": 262144,
+ "WindowTransparentForInput": 524288,
+ "WindowOverridesSystemGestures": 1048576,
+ "WindowDoesNotAcceptFocus": 2097152,
+ "MaximizeUsingFullscreenGeometryHint": 4194304,
+ "CustomizeWindowHint": 33554432,
+ "WindowStaysOnBottomHint": 67108864,
+ "WindowCloseButtonHint": 134217728,
+ "MacWindowToolBarButtonHint": 268435456,
+ "BypassGraphicsProxyWidget": 536870912,
+ "NoDropShadowWindowHint": 1073741824,
+ "WindowFullscreenButtonHint": -2147483648,
+ "WindowOkButtonHint": 524288,
+ "WindowCancelButtonHint": 1048576
+ }
+ }
+ Enum {
+ name: "WindowState"
+ values: {
+ "WindowNoState": 0,
+ "WindowMinimized": 1,
+ "WindowMaximized": 2,
+ "WindowFullScreen": 4,
+ "WindowActive": 8
+ }
+ }
+ Enum {
+ name: "WindowStates"
+ values: {
+ "WindowNoState": 0,
+ "WindowMinimized": 1,
+ "WindowMaximized": 2,
+ "WindowFullScreen": 4,
+ "WindowActive": 8
+ }
+ }
+ Enum {
+ name: "ApplicationState"
+ values: {
+ "ApplicationSuspended": 0,
+ "ApplicationHidden": 1,
+ "ApplicationInactive": 2,
+ "ApplicationActive": 4
+ }
+ }
+ Enum {
+ name: "ScreenOrientation"
+ values: {
+ "PrimaryOrientation": 0,
+ "PortraitOrientation": 1,
+ "LandscapeOrientation": 2,
+ "InvertedPortraitOrientation": 4,
+ "InvertedLandscapeOrientation": 8
+ }
+ }
+ Enum {
+ name: "ScreenOrientations"
+ values: {
+ "PrimaryOrientation": 0,
+ "PortraitOrientation": 1,
+ "LandscapeOrientation": 2,
+ "InvertedPortraitOrientation": 4,
+ "InvertedLandscapeOrientation": 8
+ }
+ }
+ Enum {
+ name: "WidgetAttribute"
+ values: {
+ "WA_Disabled": 0,
+ "WA_UnderMouse": 1,
+ "WA_MouseTracking": 2,
+ "WA_ContentsPropagated": 3,
+ "WA_OpaquePaintEvent": 4,
+ "WA_NoBackground": 4,
+ "WA_StaticContents": 5,
+ "WA_LaidOut": 7,
+ "WA_PaintOnScreen": 8,
+ "WA_NoSystemBackground": 9,
+ "WA_UpdatesDisabled": 10,
+ "WA_Mapped": 11,
+ "WA_MacNoClickThrough": 12,
+ "WA_InputMethodEnabled": 14,
+ "WA_WState_Visible": 15,
+ "WA_WState_Hidden": 16,
+ "WA_ForceDisabled": 32,
+ "WA_KeyCompression": 33,
+ "WA_PendingMoveEvent": 34,
+ "WA_PendingResizeEvent": 35,
+ "WA_SetPalette": 36,
+ "WA_SetFont": 37,
+ "WA_SetCursor": 38,
+ "WA_NoChildEventsFromChildren": 39,
+ "WA_WindowModified": 41,
+ "WA_Resized": 42,
+ "WA_Moved": 43,
+ "WA_PendingUpdate": 44,
+ "WA_InvalidSize": 45,
+ "WA_MacBrushedMetal": 46,
+ "WA_MacMetalStyle": 46,
+ "WA_CustomWhatsThis": 47,
+ "WA_LayoutOnEntireRect": 48,
+ "WA_OutsideWSRange": 49,
+ "WA_GrabbedShortcut": 50,
+ "WA_TransparentForMouseEvents": 51,
+ "WA_PaintUnclipped": 52,
+ "WA_SetWindowIcon": 53,
+ "WA_NoMouseReplay": 54,
+ "WA_DeleteOnClose": 55,
+ "WA_RightToLeft": 56,
+ "WA_SetLayoutDirection": 57,
+ "WA_NoChildEventsForParent": 58,
+ "WA_ForceUpdatesDisabled": 59,
+ "WA_WState_Created": 60,
+ "WA_WState_CompressKeys": 61,
+ "WA_WState_InPaintEvent": 62,
+ "WA_WState_Reparented": 63,
+ "WA_WState_ConfigPending": 64,
+ "WA_WState_Polished": 66,
+ "WA_WState_DND": 67,
+ "WA_WState_OwnSizePolicy": 68,
+ "WA_WState_ExplicitShowHide": 69,
+ "WA_ShowModal": 70,
+ "WA_MouseNoMask": 71,
+ "WA_GroupLeader": 72,
+ "WA_NoMousePropagation": 73,
+ "WA_Hover": 74,
+ "WA_InputMethodTransparent": 75,
+ "WA_QuitOnClose": 76,
+ "WA_KeyboardFocusChange": 77,
+ "WA_AcceptDrops": 78,
+ "WA_DropSiteRegistered": 79,
+ "WA_ForceAcceptDrops": 79,
+ "WA_WindowPropagation": 80,
+ "WA_NoX11EventCompression": 81,
+ "WA_TintedBackground": 82,
+ "WA_X11OpenGLOverlay": 83,
+ "WA_AlwaysShowToolTips": 84,
+ "WA_MacOpaqueSizeGrip": 85,
+ "WA_SetStyle": 86,
+ "WA_SetLocale": 87,
+ "WA_MacShowFocusRect": 88,
+ "WA_MacNormalSize": 89,
+ "WA_MacSmallSize": 90,
+ "WA_MacMiniSize": 91,
+ "WA_LayoutUsesWidgetRect": 92,
+ "WA_StyledBackground": 93,
+ "WA_MSWindowsUseDirect3D": 94,
+ "WA_CanHostQMdiSubWindowTitleBar": 95,
+ "WA_MacAlwaysShowToolWindow": 96,
+ "WA_StyleSheet": 97,
+ "WA_ShowWithoutActivating": 98,
+ "WA_X11BypassTransientForHint": 99,
+ "WA_NativeWindow": 100,
+ "WA_DontCreateNativeAncestors": 101,
+ "WA_MacVariableSize": 102,
+ "WA_DontShowOnScreen": 103,
+ "WA_X11NetWmWindowTypeDesktop": 104,
+ "WA_X11NetWmWindowTypeDock": 105,
+ "WA_X11NetWmWindowTypeToolBar": 106,
+ "WA_X11NetWmWindowTypeMenu": 107,
+ "WA_X11NetWmWindowTypeUtility": 108,
+ "WA_X11NetWmWindowTypeSplash": 109,
+ "WA_X11NetWmWindowTypeDialog": 110,
+ "WA_X11NetWmWindowTypeDropDownMenu": 111,
+ "WA_X11NetWmWindowTypePopupMenu": 112,
+ "WA_X11NetWmWindowTypeToolTip": 113,
+ "WA_X11NetWmWindowTypeNotification": 114,
+ "WA_X11NetWmWindowTypeCombo": 115,
+ "WA_X11NetWmWindowTypeDND": 116,
+ "WA_MacFrameworkScaled": 117,
+ "WA_SetWindowModality": 118,
+ "WA_WState_WindowOpacitySet": 119,
+ "WA_TranslucentBackground": 120,
+ "WA_AcceptTouchEvents": 121,
+ "WA_WState_AcceptedTouchBeginEvent": 122,
+ "WA_TouchPadAcceptSingleTouchEvents": 123,
+ "WA_X11DoNotAcceptFocus": 126,
+ "WA_MacNoShadow": 127,
+ "WA_AlwaysStackOnTop": 128,
+ "WA_AttributeCount": 129
+ }
+ }
+ Enum {
+ name: "ApplicationAttribute"
+ values: {
+ "AA_ImmediateWidgetCreation": 0,
+ "AA_MSWindowsUseDirect3DByDefault": 1,
+ "AA_DontShowIconsInMenus": 2,
+ "AA_NativeWindows": 3,
+ "AA_DontCreateNativeWidgetSiblings": 4,
+ "AA_MacPluginApplication": 5,
+ "AA_DontUseNativeMenuBar": 6,
+ "AA_MacDontSwapCtrlAndMeta": 7,
+ "AA_Use96Dpi": 8,
+ "AA_X11InitThreads": 10,
+ "AA_SynthesizeTouchForUnhandledMouseEvents": 11,
+ "AA_SynthesizeMouseForUnhandledTouchEvents": 12,
+ "AA_UseHighDpiPixmaps": 13,
+ "AA_ForceRasterWidgets": 14,
+ "AA_UseDesktopOpenGL": 15,
+ "AA_UseOpenGLES": 16,
+ "AA_UseSoftwareOpenGL": 17,
+ "AA_ShareOpenGLContexts": 18,
+ "AA_SetPalette": 19,
+ "AA_EnableHighDpiScaling": 20,
+ "AA_DisableHighDpiScaling": 21,
+ "AA_AttributeCount": 22
+ }
+ }
+ Enum {
+ name: "ImageConversionFlags"
+ values: {
+ "ColorMode_Mask": 3,
+ "AutoColor": 0,
+ "ColorOnly": 3,
+ "MonoOnly": 2,
+ "AlphaDither_Mask": 12,
+ "ThresholdAlphaDither": 0,
+ "OrderedAlphaDither": 4,
+ "DiffuseAlphaDither": 8,
+ "NoAlpha": 12,
+ "Dither_Mask": 48,
+ "DiffuseDither": 0,
+ "OrderedDither": 16,
+ "ThresholdDither": 32,
+ "DitherMode_Mask": 192,
+ "AutoDither": 0,
+ "PreferDither": 64,
+ "AvoidDither": 128,
+ "NoOpaqueDetection": 256,
+ "NoFormatConversion": 512
+ }
+ }
+ Enum {
+ name: "BGMode"
+ values: {
+ "TransparentMode": 0,
+ "OpaqueMode": 1
+ }
+ }
+ Enum {
+ name: "Key"
+ values: {
+ "Key_Escape": 16777216,
+ "Key_Tab": 16777217,
+ "Key_Backtab": 16777218,
+ "Key_Backspace": 16777219,
+ "Key_Return": 16777220,
+ "Key_Enter": 16777221,
+ "Key_Insert": 16777222,
+ "Key_Delete": 16777223,
+ "Key_Pause": 16777224,
+ "Key_Print": 16777225,
+ "Key_SysReq": 16777226,
+ "Key_Clear": 16777227,
+ "Key_Home": 16777232,
+ "Key_End": 16777233,
+ "Key_Left": 16777234,
+ "Key_Up": 16777235,
+ "Key_Right": 16777236,
+ "Key_Down": 16777237,
+ "Key_PageUp": 16777238,
+ "Key_PageDown": 16777239,
+ "Key_Shift": 16777248,
+ "Key_Control": 16777249,
+ "Key_Meta": 16777250,
+ "Key_Alt": 16777251,
+ "Key_CapsLock": 16777252,
+ "Key_NumLock": 16777253,
+ "Key_ScrollLock": 16777254,
+ "Key_F1": 16777264,
+ "Key_F2": 16777265,
+ "Key_F3": 16777266,
+ "Key_F4": 16777267,
+ "Key_F5": 16777268,
+ "Key_F6": 16777269,
+ "Key_F7": 16777270,
+ "Key_F8": 16777271,
+ "Key_F9": 16777272,
+ "Key_F10": 16777273,
+ "Key_F11": 16777274,
+ "Key_F12": 16777275,
+ "Key_F13": 16777276,
+ "Key_F14": 16777277,
+ "Key_F15": 16777278,
+ "Key_F16": 16777279,
+ "Key_F17": 16777280,
+ "Key_F18": 16777281,
+ "Key_F19": 16777282,
+ "Key_F20": 16777283,
+ "Key_F21": 16777284,
+ "Key_F22": 16777285,
+ "Key_F23": 16777286,
+ "Key_F24": 16777287,
+ "Key_F25": 16777288,
+ "Key_F26": 16777289,
+ "Key_F27": 16777290,
+ "Key_F28": 16777291,
+ "Key_F29": 16777292,
+ "Key_F30": 16777293,
+ "Key_F31": 16777294,
+ "Key_F32": 16777295,
+ "Key_F33": 16777296,
+ "Key_F34": 16777297,
+ "Key_F35": 16777298,
+ "Key_Super_L": 16777299,
+ "Key_Super_R": 16777300,
+ "Key_Menu": 16777301,
+ "Key_Hyper_L": 16777302,
+ "Key_Hyper_R": 16777303,
+ "Key_Help": 16777304,
+ "Key_Direction_L": 16777305,
+ "Key_Direction_R": 16777312,
+ "Key_Space": 32,
+ "Key_Any": 32,
+ "Key_Exclam": 33,
+ "Key_QuoteDbl": 34,
+ "Key_NumberSign": 35,
+ "Key_Dollar": 36,
+ "Key_Percent": 37,
+ "Key_Ampersand": 38,
+ "Key_Apostrophe": 39,
+ "Key_ParenLeft": 40,
+ "Key_ParenRight": 41,
+ "Key_Asterisk": 42,
+ "Key_Plus": 43,
+ "Key_Comma": 44,
+ "Key_Minus": 45,
+ "Key_Period": 46,
+ "Key_Slash": 47,
+ "Key_0": 48,
+ "Key_1": 49,
+ "Key_2": 50,
+ "Key_3": 51,
+ "Key_4": 52,
+ "Key_5": 53,
+ "Key_6": 54,
+ "Key_7": 55,
+ "Key_8": 56,
+ "Key_9": 57,
+ "Key_Colon": 58,
+ "Key_Semicolon": 59,
+ "Key_Less": 60,
+ "Key_Equal": 61,
+ "Key_Greater": 62,
+ "Key_Question": 63,
+ "Key_At": 64,
+ "Key_A": 65,
+ "Key_B": 66,
+ "Key_C": 67,
+ "Key_D": 68,
+ "Key_E": 69,
+ "Key_F": 70,
+ "Key_G": 71,
+ "Key_H": 72,
+ "Key_I": 73,
+ "Key_J": 74,
+ "Key_K": 75,
+ "Key_L": 76,
+ "Key_M": 77,
+ "Key_N": 78,
+ "Key_O": 79,
+ "Key_P": 80,
+ "Key_Q": 81,
+ "Key_R": 82,
+ "Key_S": 83,
+ "Key_T": 84,
+ "Key_U": 85,
+ "Key_V": 86,
+ "Key_W": 87,
+ "Key_X": 88,
+ "Key_Y": 89,
+ "Key_Z": 90,
+ "Key_BracketLeft": 91,
+ "Key_Backslash": 92,
+ "Key_BracketRight": 93,
+ "Key_AsciiCircum": 94,
+ "Key_Underscore": 95,
+ "Key_QuoteLeft": 96,
+ "Key_BraceLeft": 123,
+ "Key_Bar": 124,
+ "Key_BraceRight": 125,
+ "Key_AsciiTilde": 126,
+ "Key_nobreakspace": 160,
+ "Key_exclamdown": 161,
+ "Key_cent": 162,
+ "Key_sterling": 163,
+ "Key_currency": 164,
+ "Key_yen": 165,
+ "Key_brokenbar": 166,
+ "Key_section": 167,
+ "Key_diaeresis": 168,
+ "Key_copyright": 169,
+ "Key_ordfeminine": 170,
+ "Key_guillemotleft": 171,
+ "Key_notsign": 172,
+ "Key_hyphen": 173,
+ "Key_registered": 174,
+ "Key_macron": 175,
+ "Key_degree": 176,
+ "Key_plusminus": 177,
+ "Key_twosuperior": 178,
+ "Key_threesuperior": 179,
+ "Key_acute": 180,
+ "Key_mu": 181,
+ "Key_paragraph": 182,
+ "Key_periodcentered": 183,
+ "Key_cedilla": 184,
+ "Key_onesuperior": 185,
+ "Key_masculine": 186,
+ "Key_guillemotright": 187,
+ "Key_onequarter": 188,
+ "Key_onehalf": 189,
+ "Key_threequarters": 190,
+ "Key_questiondown": 191,
+ "Key_Agrave": 192,
+ "Key_Aacute": 193,
+ "Key_Acircumflex": 194,
+ "Key_Atilde": 195,
+ "Key_Adiaeresis": 196,
+ "Key_Aring": 197,
+ "Key_AE": 198,
+ "Key_Ccedilla": 199,
+ "Key_Egrave": 200,
+ "Key_Eacute": 201,
+ "Key_Ecircumflex": 202,
+ "Key_Ediaeresis": 203,
+ "Key_Igrave": 204,
+ "Key_Iacute": 205,
+ "Key_Icircumflex": 206,
+ "Key_Idiaeresis": 207,
+ "Key_ETH": 208,
+ "Key_Ntilde": 209,
+ "Key_Ograve": 210,
+ "Key_Oacute": 211,
+ "Key_Ocircumflex": 212,
+ "Key_Otilde": 213,
+ "Key_Odiaeresis": 214,
+ "Key_multiply": 215,
+ "Key_Ooblique": 216,
+ "Key_Ugrave": 217,
+ "Key_Uacute": 218,
+ "Key_Ucircumflex": 219,
+ "Key_Udiaeresis": 220,
+ "Key_Yacute": 221,
+ "Key_THORN": 222,
+ "Key_ssharp": 223,
+ "Key_division": 247,
+ "Key_ydiaeresis": 255,
+ "Key_AltGr": 16781571,
+ "Key_Multi_key": 16781600,
+ "Key_Codeinput": 16781623,
+ "Key_SingleCandidate": 16781628,
+ "Key_MultipleCandidate": 16781629,
+ "Key_PreviousCandidate": 16781630,
+ "Key_Mode_switch": 16781694,
+ "Key_Kanji": 16781601,
+ "Key_Muhenkan": 16781602,
+ "Key_Henkan": 16781603,
+ "Key_Romaji": 16781604,
+ "Key_Hiragana": 16781605,
+ "Key_Katakana": 16781606,
+ "Key_Hiragana_Katakana": 16781607,
+ "Key_Zenkaku": 16781608,
+ "Key_Hankaku": 16781609,
+ "Key_Zenkaku_Hankaku": 16781610,
+ "Key_Touroku": 16781611,
+ "Key_Massyo": 16781612,
+ "Key_Kana_Lock": 16781613,
+ "Key_Kana_Shift": 16781614,
+ "Key_Eisu_Shift": 16781615,
+ "Key_Eisu_toggle": 16781616,
+ "Key_Hangul": 16781617,
+ "Key_Hangul_Start": 16781618,
+ "Key_Hangul_End": 16781619,
+ "Key_Hangul_Hanja": 16781620,
+ "Key_Hangul_Jamo": 16781621,
+ "Key_Hangul_Romaja": 16781622,
+ "Key_Hangul_Jeonja": 16781624,
+ "Key_Hangul_Banja": 16781625,
+ "Key_Hangul_PreHanja": 16781626,
+ "Key_Hangul_PostHanja": 16781627,
+ "Key_Hangul_Special": 16781631,
+ "Key_Dead_Grave": 16781904,
+ "Key_Dead_Acute": 16781905,
+ "Key_Dead_Circumflex": 16781906,
+ "Key_Dead_Tilde": 16781907,
+ "Key_Dead_Macron": 16781908,
+ "Key_Dead_Breve": 16781909,
+ "Key_Dead_Abovedot": 16781910,
+ "Key_Dead_Diaeresis": 16781911,
+ "Key_Dead_Abovering": 16781912,
+ "Key_Dead_Doubleacute": 16781913,
+ "Key_Dead_Caron": 16781914,
+ "Key_Dead_Cedilla": 16781915,
+ "Key_Dead_Ogonek": 16781916,
+ "Key_Dead_Iota": 16781917,
+ "Key_Dead_Voiced_Sound": 16781918,
+ "Key_Dead_Semivoiced_Sound": 16781919,
+ "Key_Dead_Belowdot": 16781920,
+ "Key_Dead_Hook": 16781921,
+ "Key_Dead_Horn": 16781922,
+ "Key_Back": 16777313,
+ "Key_Forward": 16777314,
+ "Key_Stop": 16777315,
+ "Key_Refresh": 16777316,
+ "Key_VolumeDown": 16777328,
+ "Key_VolumeMute": 16777329,
+ "Key_VolumeUp": 16777330,
+ "Key_BassBoost": 16777331,
+ "Key_BassUp": 16777332,
+ "Key_BassDown": 16777333,
+ "Key_TrebleUp": 16777334,
+ "Key_TrebleDown": 16777335,
+ "Key_MediaPlay": 16777344,
+ "Key_MediaStop": 16777345,
+ "Key_MediaPrevious": 16777346,
+ "Key_MediaNext": 16777347,
+ "Key_MediaRecord": 16777348,
+ "Key_MediaPause": 16777349,
+ "Key_MediaTogglePlayPause": 16777350,
+ "Key_HomePage": 16777360,
+ "Key_Favorites": 16777361,
+ "Key_Search": 16777362,
+ "Key_Standby": 16777363,
+ "Key_OpenUrl": 16777364,
+ "Key_LaunchMail": 16777376,
+ "Key_LaunchMedia": 16777377,
+ "Key_Launch0": 16777378,
+ "Key_Launch1": 16777379,
+ "Key_Launch2": 16777380,
+ "Key_Launch3": 16777381,
+ "Key_Launch4": 16777382,
+ "Key_Launch5": 16777383,
+ "Key_Launch6": 16777384,
+ "Key_Launch7": 16777385,
+ "Key_Launch8": 16777386,
+ "Key_Launch9": 16777387,
+ "Key_LaunchA": 16777388,
+ "Key_LaunchB": 16777389,
+ "Key_LaunchC": 16777390,
+ "Key_LaunchD": 16777391,
+ "Key_LaunchE": 16777392,
+ "Key_LaunchF": 16777393,
+ "Key_MonBrightnessUp": 16777394,
+ "Key_MonBrightnessDown": 16777395,
+ "Key_KeyboardLightOnOff": 16777396,
+ "Key_KeyboardBrightnessUp": 16777397,
+ "Key_KeyboardBrightnessDown": 16777398,
+ "Key_PowerOff": 16777399,
+ "Key_WakeUp": 16777400,
+ "Key_Eject": 16777401,
+ "Key_ScreenSaver": 16777402,
+ "Key_WWW": 16777403,
+ "Key_Memo": 16777404,
+ "Key_LightBulb": 16777405,
+ "Key_Shop": 16777406,
+ "Key_History": 16777407,
+ "Key_AddFavorite": 16777408,
+ "Key_HotLinks": 16777409,
+ "Key_BrightnessAdjust": 16777410,
+ "Key_Finance": 16777411,
+ "Key_Community": 16777412,
+ "Key_AudioRewind": 16777413,
+ "Key_BackForward": 16777414,
+ "Key_ApplicationLeft": 16777415,
+ "Key_ApplicationRight": 16777416,
+ "Key_Book": 16777417,
+ "Key_CD": 16777418,
+ "Key_Calculator": 16777419,
+ "Key_ToDoList": 16777420,
+ "Key_ClearGrab": 16777421,
+ "Key_Close": 16777422,
+ "Key_Copy": 16777423,
+ "Key_Cut": 16777424,
+ "Key_Display": 16777425,
+ "Key_DOS": 16777426,
+ "Key_Documents": 16777427,
+ "Key_Excel": 16777428,
+ "Key_Explorer": 16777429,
+ "Key_Game": 16777430,
+ "Key_Go": 16777431,
+ "Key_iTouch": 16777432,
+ "Key_LogOff": 16777433,
+ "Key_Market": 16777434,
+ "Key_Meeting": 16777435,
+ "Key_MenuKB": 16777436,
+ "Key_MenuPB": 16777437,
+ "Key_MySites": 16777438,
+ "Key_News": 16777439,
+ "Key_OfficeHome": 16777440,
+ "Key_Option": 16777441,
+ "Key_Paste": 16777442,
+ "Key_Phone": 16777443,
+ "Key_Calendar": 16777444,
+ "Key_Reply": 16777445,
+ "Key_Reload": 16777446,
+ "Key_RotateWindows": 16777447,
+ "Key_RotationPB": 16777448,
+ "Key_RotationKB": 16777449,
+ "Key_Save": 16777450,
+ "Key_Send": 16777451,
+ "Key_Spell": 16777452,
+ "Key_SplitScreen": 16777453,
+ "Key_Support": 16777454,
+ "Key_TaskPane": 16777455,
+ "Key_Terminal": 16777456,
+ "Key_Tools": 16777457,
+ "Key_Travel": 16777458,
+ "Key_Video": 16777459,
+ "Key_Word": 16777460,
+ "Key_Xfer": 16777461,
+ "Key_ZoomIn": 16777462,
+ "Key_ZoomOut": 16777463,
+ "Key_Away": 16777464,
+ "Key_Messenger": 16777465,
+ "Key_WebCam": 16777466,
+ "Key_MailForward": 16777467,
+ "Key_Pictures": 16777468,
+ "Key_Music": 16777469,
+ "Key_Battery": 16777470,
+ "Key_Bluetooth": 16777471,
+ "Key_WLAN": 16777472,
+ "Key_UWB": 16777473,
+ "Key_AudioForward": 16777474,
+ "Key_AudioRepeat": 16777475,
+ "Key_AudioRandomPlay": 16777476,
+ "Key_Subtitle": 16777477,
+ "Key_AudioCycleTrack": 16777478,
+ "Key_Time": 16777479,
+ "Key_Hibernate": 16777480,
+ "Key_View": 16777481,
+ "Key_TopMenu": 16777482,
+ "Key_PowerDown": 16777483,
+ "Key_Suspend": 16777484,
+ "Key_ContrastAdjust": 16777485,
+ "Key_LaunchG": 16777486,
+ "Key_LaunchH": 16777487,
+ "Key_TouchpadToggle": 16777488,
+ "Key_TouchpadOn": 16777489,
+ "Key_TouchpadOff": 16777490,
+ "Key_MicMute": 16777491,
+ "Key_Red": 16777492,
+ "Key_Green": 16777493,
+ "Key_Yellow": 16777494,
+ "Key_Blue": 16777495,
+ "Key_ChannelUp": 16777496,
+ "Key_ChannelDown": 16777497,
+ "Key_Guide": 16777498,
+ "Key_Info": 16777499,
+ "Key_Settings": 16777500,
+ "Key_MicVolumeUp": 16777501,
+ "Key_MicVolumeDown": 16777502,
+ "Key_New": 16777504,
+ "Key_Open": 16777505,
+ "Key_Find": 16777506,
+ "Key_Undo": 16777507,
+ "Key_Redo": 16777508,
+ "Key_MediaLast": 16842751,
+ "Key_Select": 16842752,
+ "Key_Yes": 16842753,
+ "Key_No": 16842754,
+ "Key_Cancel": 16908289,
+ "Key_Printer": 16908290,
+ "Key_Execute": 16908291,
+ "Key_Sleep": 16908292,
+ "Key_Play": 16908293,
+ "Key_Zoom": 16908294,
+ "Key_Exit": 16908298,
+ "Key_Context1": 17825792,
+ "Key_Context2": 17825793,
+ "Key_Context3": 17825794,
+ "Key_Context4": 17825795,
+ "Key_Call": 17825796,
+ "Key_Hangup": 17825797,
+ "Key_Flip": 17825798,
+ "Key_ToggleCallHangup": 17825799,
+ "Key_VoiceDial": 17825800,
+ "Key_LastNumberRedial": 17825801,
+ "Key_Camera": 17825824,
+ "Key_CameraFocus": 17825825,
+ "Key_unknown": 33554431
+ }
+ }
+ Enum {
+ name: "ArrowType"
+ values: {
+ "NoArrow": 0,
+ "UpArrow": 1,
+ "DownArrow": 2,
+ "LeftArrow": 3,
+ "RightArrow": 4
+ }
+ }
+ Enum {
+ name: "PenStyle"
+ values: {
+ "NoPen": 0,
+ "SolidLine": 1,
+ "DashLine": 2,
+ "DotLine": 3,
+ "DashDotLine": 4,
+ "DashDotDotLine": 5,
+ "CustomDashLine": 6
+ }
+ }
+ Enum {
+ name: "PenCapStyle"
+ values: {
+ "FlatCap": 0,
+ "SquareCap": 16,
+ "RoundCap": 32,
+ "MPenCapStyle": 48
+ }
+ }
+ Enum {
+ name: "PenJoinStyle"
+ values: {
+ "MiterJoin": 0,
+ "BevelJoin": 64,
+ "RoundJoin": 128,
+ "SvgMiterJoin": 256,
+ "MPenJoinStyle": 448
+ }
+ }
+ Enum {
+ name: "BrushStyle"
+ values: {
+ "NoBrush": 0,
+ "SolidPattern": 1,
+ "Dense1Pattern": 2,
+ "Dense2Pattern": 3,
+ "Dense3Pattern": 4,
+ "Dense4Pattern": 5,
+ "Dense5Pattern": 6,
+ "Dense6Pattern": 7,
+ "Dense7Pattern": 8,
+ "HorPattern": 9,
+ "VerPattern": 10,
+ "CrossPattern": 11,
+ "BDiagPattern": 12,
+ "FDiagPattern": 13,
+ "DiagCrossPattern": 14,
+ "LinearGradientPattern": 15,
+ "RadialGradientPattern": 16,
+ "ConicalGradientPattern": 17,
+ "TexturePattern": 24
+ }
+ }
+ Enum {
+ name: "SizeMode"
+ values: {
+ "AbsoluteSize": 0,
+ "RelativeSize": 1
+ }
+ }
+ Enum {
+ name: "CursorShape"
+ values: {
+ "ArrowCursor": 0,
+ "UpArrowCursor": 1,
+ "CrossCursor": 2,
+ "WaitCursor": 3,
+ "IBeamCursor": 4,
+ "SizeVerCursor": 5,
+ "SizeHorCursor": 6,
+ "SizeBDiagCursor": 7,
+ "SizeFDiagCursor": 8,
+ "SizeAllCursor": 9,
+ "BlankCursor": 10,
+ "SplitVCursor": 11,
+ "SplitHCursor": 12,
+ "PointingHandCursor": 13,
+ "ForbiddenCursor": 14,
+ "WhatsThisCursor": 15,
+ "BusyCursor": 16,
+ "OpenHandCursor": 17,
+ "ClosedHandCursor": 18,
+ "DragCopyCursor": 19,
+ "DragMoveCursor": 20,
+ "DragLinkCursor": 21,
+ "LastCursor": 21,
+ "BitmapCursor": 24,
+ "CustomCursor": 25
+ }
+ }
+ Enum {
+ name: "TextFormat"
+ values: {
+ "PlainText": 0,
+ "RichText": 1,
+ "AutoText": 2
+ }
+ }
+ Enum {
+ name: "AspectRatioMode"
+ values: {
+ "IgnoreAspectRatio": 0,
+ "KeepAspectRatio": 1,
+ "KeepAspectRatioByExpanding": 2
+ }
+ }
+ Enum {
+ name: "DockWidgetArea"
+ values: {
+ "LeftDockWidgetArea": 1,
+ "RightDockWidgetArea": 2,
+ "TopDockWidgetArea": 4,
+ "BottomDockWidgetArea": 8,
+ "DockWidgetArea_Mask": 15,
+ "AllDockWidgetAreas": 15,
+ "NoDockWidgetArea": 0
+ }
+ }
+ Enum {
+ name: "DockWidgetAreas"
+ values: {
+ "LeftDockWidgetArea": 1,
+ "RightDockWidgetArea": 2,
+ "TopDockWidgetArea": 4,
+ "BottomDockWidgetArea": 8,
+ "DockWidgetArea_Mask": 15,
+ "AllDockWidgetAreas": 15,
+ "NoDockWidgetArea": 0
+ }
+ }
+ Enum {
+ name: "ToolBarArea"
+ values: {
+ "LeftToolBarArea": 1,
+ "RightToolBarArea": 2,
+ "TopToolBarArea": 4,
+ "BottomToolBarArea": 8,
+ "ToolBarArea_Mask": 15,
+ "AllToolBarAreas": 15,
+ "NoToolBarArea": 0
+ }
+ }
+ Enum {
+ name: "ToolBarAreas"
+ values: {
+ "LeftToolBarArea": 1,
+ "RightToolBarArea": 2,
+ "TopToolBarArea": 4,
+ "BottomToolBarArea": 8,
+ "ToolBarArea_Mask": 15,
+ "AllToolBarAreas": 15,
+ "NoToolBarArea": 0
+ }
+ }
+ Enum {
+ name: "DateFormat"
+ values: {
+ "TextDate": 0,
+ "ISODate": 1,
+ "SystemLocaleDate": 2,
+ "LocalDate": 2,
+ "LocaleDate": 3,
+ "SystemLocaleShortDate": 4,
+ "SystemLocaleLongDate": 5,
+ "DefaultLocaleShortDate": 6,
+ "DefaultLocaleLongDate": 7,
+ "RFC2822Date": 8
+ }
+ }
+ Enum {
+ name: "TimeSpec"
+ values: {
+ "LocalTime": 0,
+ "UTC": 1,
+ "OffsetFromUTC": 2,
+ "TimeZone": 3
+ }
+ }
+ Enum {
+ name: "DayOfWeek"
+ values: {
+ "Monday": 1,
+ "Tuesday": 2,
+ "Wednesday": 3,
+ "Thursday": 4,
+ "Friday": 5,
+ "Saturday": 6,
+ "Sunday": 7
+ }
+ }
+ Enum {
+ name: "ScrollBarPolicy"
+ values: {
+ "ScrollBarAsNeeded": 0,
+ "ScrollBarAlwaysOff": 1,
+ "ScrollBarAlwaysOn": 2
+ }
+ }
+ Enum {
+ name: "CaseSensitivity"
+ values: {
+ "CaseInsensitive": 0,
+ "CaseSensitive": 1
+ }
+ }
+ Enum {
+ name: "Corner"
+ values: {
+ "TopLeftCorner": 0,
+ "TopRightCorner": 1,
+ "BottomLeftCorner": 2,
+ "BottomRightCorner": 3
+ }
+ }
+ Enum {
+ name: "Edge"
+ values: {
+ "TopEdge": 1,
+ "LeftEdge": 2,
+ "RightEdge": 4,
+ "BottomEdge": 8
+ }
+ }
+ Enum {
+ name: "Edges"
+ values: {
+ "TopEdge": 1,
+ "LeftEdge": 2,
+ "RightEdge": 4,
+ "BottomEdge": 8
+ }
+ }
+ Enum {
+ name: "ConnectionType"
+ values: {
+ "AutoConnection": 0,
+ "DirectConnection": 1,
+ "QueuedConnection": 2,
+ "BlockingQueuedConnection": 3,
+ "UniqueConnection": 128
+ }
+ }
+ Enum {
+ name: "ShortcutContext"
+ values: {
+ "WidgetShortcut": 0,
+ "WindowShortcut": 1,
+ "ApplicationShortcut": 2,
+ "WidgetWithChildrenShortcut": 3
+ }
+ }
+ Enum {
+ name: "FillRule"
+ values: {
+ "OddEvenFill": 0,
+ "WindingFill": 1
+ }
+ }
+ Enum {
+ name: "MaskMode"
+ values: {
+ "MaskInColor": 0,
+ "MaskOutColor": 1
+ }
+ }
+ Enum {
+ name: "ClipOperation"
+ values: {
+ "NoClip": 0,
+ "ReplaceClip": 1,
+ "IntersectClip": 2
+ }
+ }
+ Enum {
+ name: "ItemSelectionMode"
+ values: {
+ "ContainsItemShape": 0,
+ "IntersectsItemShape": 1,
+ "ContainsItemBoundingRect": 2,
+ "IntersectsItemBoundingRect": 3
+ }
+ }
+ Enum {
+ name: "ItemSelectionOperation"
+ values: {
+ "ReplaceSelection": 0,
+ "AddToSelection": 1
+ }
+ }
+ Enum {
+ name: "TransformationMode"
+ values: {
+ "FastTransformation": 0,
+ "SmoothTransformation": 1
+ }
+ }
+ Enum {
+ name: "Axis"
+ values: {
+ "XAxis": 0,
+ "YAxis": 1,
+ "ZAxis": 2
+ }
+ }
+ Enum {
+ name: "FocusReason"
+ values: {
+ "MouseFocusReason": 0,
+ "TabFocusReason": 1,
+ "BacktabFocusReason": 2,
+ "ActiveWindowFocusReason": 3,
+ "PopupFocusReason": 4,
+ "ShortcutFocusReason": 5,
+ "MenuBarFocusReason": 6,
+ "OtherFocusReason": 7,
+ "NoFocusReason": 8
+ }
+ }
+ Enum {
+ name: "ContextMenuPolicy"
+ values: {
+ "NoContextMenu": 0,
+ "DefaultContextMenu": 1,
+ "ActionsContextMenu": 2,
+ "CustomContextMenu": 3,
+ "PreventContextMenu": 4
+ }
+ }
+ Enum {
+ name: "InputMethodQuery"
+ values: {
+ "ImEnabled": 1,
+ "ImCursorRectangle": 2,
+ "ImMicroFocus": 2,
+ "ImFont": 4,
+ "ImCursorPosition": 8,
+ "ImSurroundingText": 16,
+ "ImCurrentSelection": 32,
+ "ImMaximumTextLength": 64,
+ "ImAnchorPosition": 128,
+ "ImHints": 256,
+ "ImPreferredLanguage": 512,
+ "ImAbsolutePosition": 1024,
+ "ImTextBeforeCursor": 2048,
+ "ImTextAfterCursor": 4096,
+ "ImEnterKeyType": 8192,
+ "ImPlatformData": -2147483648,
+ "ImQueryInput": 186,
+ "ImQueryAll": -1
+ }
+ }
+ Enum {
+ name: "InputMethodQueries"
+ values: {
+ "ImEnabled": 1,
+ "ImCursorRectangle": 2,
+ "ImMicroFocus": 2,
+ "ImFont": 4,
+ "ImCursorPosition": 8,
+ "ImSurroundingText": 16,
+ "ImCurrentSelection": 32,
+ "ImMaximumTextLength": 64,
+ "ImAnchorPosition": 128,
+ "ImHints": 256,
+ "ImPreferredLanguage": 512,
+ "ImAbsolutePosition": 1024,
+ "ImTextBeforeCursor": 2048,
+ "ImTextAfterCursor": 4096,
+ "ImEnterKeyType": 8192,
+ "ImPlatformData": -2147483648,
+ "ImQueryInput": 186,
+ "ImQueryAll": -1
+ }
+ }
+ Enum {
+ name: "InputMethodHint"
+ values: {
+ "ImhNone": 0,
+ "ImhHiddenText": 1,
+ "ImhSensitiveData": 2,
+ "ImhNoAutoUppercase": 4,
+ "ImhPreferNumbers": 8,
+ "ImhPreferUppercase": 16,
+ "ImhPreferLowercase": 32,
+ "ImhNoPredictiveText": 64,
+ "ImhDate": 128,
+ "ImhTime": 256,
+ "ImhPreferLatin": 512,
+ "ImhMultiLine": 1024,
+ "ImhDigitsOnly": 65536,
+ "ImhFormattedNumbersOnly": 131072,
+ "ImhUppercaseOnly": 262144,
+ "ImhLowercaseOnly": 524288,
+ "ImhDialableCharactersOnly": 1048576,
+ "ImhEmailCharactersOnly": 2097152,
+ "ImhUrlCharactersOnly": 4194304,
+ "ImhLatinOnly": 8388608,
+ "ImhExclusiveInputMask": -65536
+ }
+ }
+ Enum {
+ name: "InputMethodHints"
+ values: {
+ "ImhNone": 0,
+ "ImhHiddenText": 1,
+ "ImhSensitiveData": 2,
+ "ImhNoAutoUppercase": 4,
+ "ImhPreferNumbers": 8,
+ "ImhPreferUppercase": 16,
+ "ImhPreferLowercase": 32,
+ "ImhNoPredictiveText": 64,
+ "ImhDate": 128,
+ "ImhTime": 256,
+ "ImhPreferLatin": 512,
+ "ImhMultiLine": 1024,
+ "ImhDigitsOnly": 65536,
+ "ImhFormattedNumbersOnly": 131072,
+ "ImhUppercaseOnly": 262144,
+ "ImhLowercaseOnly": 524288,
+ "ImhDialableCharactersOnly": 1048576,
+ "ImhEmailCharactersOnly": 2097152,
+ "ImhUrlCharactersOnly": 4194304,
+ "ImhLatinOnly": 8388608,
+ "ImhExclusiveInputMask": -65536
+ }
+ }
+ Enum {
+ name: "EnterKeyType"
+ values: {
+ "EnterKeyDefault": 0,
+ "EnterKeyReturn": 1,
+ "EnterKeyDone": 2,
+ "EnterKeyGo": 3,
+ "EnterKeySend": 4,
+ "EnterKeySearch": 5,
+ "EnterKeyNext": 6,
+ "EnterKeyPrevious": 7
+ }
+ }
+ Enum {
+ name: "ToolButtonStyle"
+ values: {
+ "ToolButtonIconOnly": 0,
+ "ToolButtonTextOnly": 1,
+ "ToolButtonTextBesideIcon": 2,
+ "ToolButtonTextUnderIcon": 3,
+ "ToolButtonFollowStyle": 4
+ }
+ }
+ Enum {
+ name: "LayoutDirection"
+ values: {
+ "LeftToRight": 0,
+ "RightToLeft": 1,
+ "LayoutDirectionAuto": 2
+ }
+ }
+ Enum {
+ name: "DropAction"
+ values: {
+ "CopyAction": 1,
+ "MoveAction": 2,
+ "LinkAction": 4,
+ "ActionMask": 255,
+ "TargetMoveAction": 32770,
+ "IgnoreAction": 0
+ }
+ }
+ Enum {
+ name: "DropActions"
+ values: {
+ "CopyAction": 1,
+ "MoveAction": 2,
+ "LinkAction": 4,
+ "ActionMask": 255,
+ "TargetMoveAction": 32770,
+ "IgnoreAction": 0
+ }
+ }
+ Enum {
+ name: "CheckState"
+ values: {
+ "Unchecked": 0,
+ "PartiallyChecked": 1,
+ "Checked": 2
+ }
+ }
+ Enum {
+ name: "ItemDataRole"
+ values: {
+ "DisplayRole": 0,
+ "DecorationRole": 1,
+ "EditRole": 2,
+ "ToolTipRole": 3,
+ "StatusTipRole": 4,
+ "WhatsThisRole": 5,
+ "FontRole": 6,
+ "TextAlignmentRole": 7,
+ "BackgroundColorRole": 8,
+ "BackgroundRole": 8,
+ "TextColorRole": 9,
+ "ForegroundRole": 9,
+ "CheckStateRole": 10,
+ "AccessibleTextRole": 11,
+ "AccessibleDescriptionRole": 12,
+ "SizeHintRole": 13,
+ "InitialSortOrderRole": 14,
+ "DisplayPropertyRole": 27,
+ "DecorationPropertyRole": 28,
+ "ToolTipPropertyRole": 29,
+ "StatusTipPropertyRole": 30,
+ "WhatsThisPropertyRole": 31,
+ "UserRole": 256
+ }
+ }
+ Enum {
+ name: "ItemFlags"
+ values: {
+ "NoItemFlags": 0,
+ "ItemIsSelectable": 1,
+ "ItemIsEditable": 2,
+ "ItemIsDragEnabled": 4,
+ "ItemIsDropEnabled": 8,
+ "ItemIsUserCheckable": 16,
+ "ItemIsEnabled": 32,
+ "ItemIsAutoTristate": 64,
+ "ItemIsTristate": 64,
+ "ItemNeverHasChildren": 128,
+ "ItemIsUserTristate": 256
+ }
+ }
+ Enum {
+ name: "MatchFlags"
+ values: {
+ "MatchExactly": 0,
+ "MatchContains": 1,
+ "MatchStartsWith": 2,
+ "MatchEndsWith": 3,
+ "MatchRegExp": 4,
+ "MatchWildcard": 5,
+ "MatchFixedString": 8,
+ "MatchCaseSensitive": 16,
+ "MatchWrap": 32,
+ "MatchRecursive": 64
+ }
+ }
+ Enum {
+ name: "WindowModality"
+ values: {
+ "NonModal": 0,
+ "WindowModal": 1,
+ "ApplicationModal": 2
+ }
+ }
+ Enum {
+ name: "TextInteractionFlag"
+ values: {
+ "NoTextInteraction": 0,
+ "TextSelectableByMouse": 1,
+ "TextSelectableByKeyboard": 2,
+ "LinksAccessibleByMouse": 4,
+ "LinksAccessibleByKeyboard": 8,
+ "TextEditable": 16,
+ "TextEditorInteraction": 19,
+ "TextBrowserInteraction": 13
+ }
+ }
+ Enum {
+ name: "TextInteractionFlags"
+ values: {
+ "NoTextInteraction": 0,
+ "TextSelectableByMouse": 1,
+ "TextSelectableByKeyboard": 2,
+ "LinksAccessibleByMouse": 4,
+ "LinksAccessibleByKeyboard": 8,
+ "TextEditable": 16,
+ "TextEditorInteraction": 19,
+ "TextBrowserInteraction": 13
+ }
+ }
+ Enum {
+ name: "SizeHint"
+ values: {
+ "MinimumSize": 0,
+ "PreferredSize": 1,
+ "MaximumSize": 2,
+ "MinimumDescent": 3,
+ "NSizeHints": 4
+ }
+ }
+ Enum {
+ name: "TouchPointStates"
+ values: {
+ "TouchPointPressed": 1,
+ "TouchPointMoved": 2,
+ "TouchPointStationary": 4,
+ "TouchPointReleased": 8
+ }
+ }
+ Enum {
+ name: "GestureState"
+ values: {
+ "NoGesture": 0,
+ "GestureStarted": 1,
+ "GestureUpdated": 2,
+ "GestureFinished": 3,
+ "GestureCanceled": 4
+ }
+ }
+ Enum {
+ name: "GestureType"
+ values: {
+ "TapGesture": 1,
+ "TapAndHoldGesture": 2,
+ "PanGesture": 3,
+ "PinchGesture": 4,
+ "SwipeGesture": 5,
+ "CustomGesture": 256,
+ "LastGestureType": -1
+ }
+ }
+ Enum {
+ name: "NativeGestureType"
+ values: {
+ "BeginNativeGesture": 0,
+ "EndNativeGesture": 1,
+ "PanNativeGesture": 2,
+ "ZoomNativeGesture": 3,
+ "SmartZoomNativeGesture": 4,
+ "RotateNativeGesture": 5,
+ "SwipeNativeGesture": 6
+ }
+ }
+ Enum {
+ name: "CursorMoveStyle"
+ values: {
+ "LogicalMoveStyle": 0,
+ "VisualMoveStyle": 1
+ }
+ }
+ Enum {
+ name: "TimerType"
+ values: {
+ "PreciseTimer": 0,
+ "CoarseTimer": 1,
+ "VeryCoarseTimer": 2
+ }
+ }
+ Enum {
+ name: "ScrollPhase"
+ values: {
+ "ScrollBegin": 1,
+ "ScrollUpdate": 2,
+ "ScrollEnd": 3
+ }
+ }
+ Enum {
+ name: "MouseEventSource"
+ values: {
+ "MouseEventNotSynthesized": 0,
+ "MouseEventSynthesizedBySystem": 1,
+ "MouseEventSynthesizedByQt": 2,
+ "MouseEventSynthesizedByApplication": 3
+ }
+ }
+ Enum {
+ name: "MouseEventFlag"
+ values: {
+ "MouseEventCreatedDoubleClick": 1,
+ "MouseEventFlagMask": 255
+ }
+ }
+ }
+ Component { name: "QEasingCurve"; prototype: "QQmlEasingValueType" }
+}
diff --git a/src/imports/folderlistmodel/fileinfothread.cpp b/src/imports/folderlistmodel/fileinfothread.cpp
index e1db7834ec..ebdfba42a8 100644
--- a/src/imports/folderlistmodel/fileinfothread.cpp
+++ b/src/imports/folderlistmodel/fileinfothread.cpp
@@ -251,7 +251,8 @@ void FileInfoThread::getFileInfos(const QString &path)
fileInfoList = currentDir.entryInfoList(nameFilters, filter, sortFlags);
if (!fileInfoList.isEmpty()) {
- foreach (QFileInfo info, fileInfoList) {
+ filePropertyList.reserve(fileInfoList.count());
+ foreach (const QFileInfo &info, fileInfoList) {
//qDebug() << "Adding file : " << info.fileName() << "to list ";
filePropertyList << FileProperty(info);
}
diff --git a/src/imports/folderlistmodel/fileinfothread_p.h b/src/imports/folderlistmodel/fileinfothread_p.h
index ee325fa50b..b375584ff8 100644
--- a/src/imports/folderlistmodel/fileinfothread_p.h
+++ b/src/imports/folderlistmodel/fileinfothread_p.h
@@ -34,6 +34,17 @@
#ifndef FILEINFOTHREAD_P_H
#define FILEINFOTHREAD_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
diff --git a/src/imports/folderlistmodel/fileproperty_p.h b/src/imports/folderlistmodel/fileproperty_p.h
index d514ad55bc..3ec8cc0c00 100644
--- a/src/imports/folderlistmodel/fileproperty_p.h
+++ b/src/imports/folderlistmodel/fileproperty_p.h
@@ -34,6 +34,17 @@
#ifndef FILEPROPERTY_P_H
#define FILEPROPERTY_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QFileInfo>
#include <QDateTime>
diff --git a/src/imports/folderlistmodel/plugins.qmltypes b/src/imports/folderlistmodel/plugins.qmltypes
index a55d3a3499..02127c63cb 100644
--- a/src/imports/folderlistmodel/plugins.qmltypes
+++ b/src/imports/folderlistmodel/plugins.qmltypes
@@ -1,4 +1,4 @@
-import QtQuick.tooling 1.1
+import QtQuick.tooling 1.2
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
@@ -7,6 +7,272 @@ import QtQuick.tooling 1.1
// 'qmlplugindump -nonrelocatable Qt.labs.folderlistmodel 2.1'
Module {
+ dependencies: []
+ Component {
+ name: "QAbstractItemModel"
+ prototype: "QObject"
+ Enum {
+ name: "LayoutChangeHint"
+ values: {
+ "NoLayoutChangeHint": 0,
+ "VerticalSortHint": 1,
+ "HorizontalSortHint": 2
+ }
+ }
+ Signal {
+ name: "dataChanged"
+ Parameter { name: "topLeft"; type: "QModelIndex" }
+ Parameter { name: "bottomRight"; type: "QModelIndex" }
+ Parameter { name: "roles"; type: "QVector<int>" }
+ }
+ Signal {
+ name: "dataChanged"
+ Parameter { name: "topLeft"; type: "QModelIndex" }
+ Parameter { name: "bottomRight"; type: "QModelIndex" }
+ }
+ Signal {
+ name: "headerDataChanged"
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "layoutChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ Parameter { name: "hint"; type: "QAbstractItemModel::LayoutChangeHint" }
+ }
+ Signal {
+ name: "layoutChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ }
+ Signal { name: "layoutChanged" }
+ Signal {
+ name: "layoutAboutToBeChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ Parameter { name: "hint"; type: "QAbstractItemModel::LayoutChangeHint" }
+ }
+ Signal {
+ name: "layoutAboutToBeChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ }
+ Signal { name: "layoutAboutToBeChanged" }
+ Signal {
+ name: "rowsAboutToBeInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsAboutToBeRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal { name: "modelAboutToBeReset" }
+ Signal { name: "modelReset" }
+ Signal {
+ name: "rowsAboutToBeMoved"
+ Parameter { name: "sourceParent"; type: "QModelIndex" }
+ Parameter { name: "sourceStart"; type: "int" }
+ Parameter { name: "sourceEnd"; type: "int" }
+ Parameter { name: "destinationParent"; type: "QModelIndex" }
+ Parameter { name: "destinationRow"; type: "int" }
+ }
+ Signal {
+ name: "rowsMoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "start"; type: "int" }
+ Parameter { name: "end"; type: "int" }
+ Parameter { name: "destination"; type: "QModelIndex" }
+ Parameter { name: "row"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeMoved"
+ Parameter { name: "sourceParent"; type: "QModelIndex" }
+ Parameter { name: "sourceStart"; type: "int" }
+ Parameter { name: "sourceEnd"; type: "int" }
+ Parameter { name: "destinationParent"; type: "QModelIndex" }
+ Parameter { name: "destinationColumn"; type: "int" }
+ }
+ Signal {
+ name: "columnsMoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "start"; type: "int" }
+ Parameter { name: "end"; type: "int" }
+ Parameter { name: "destination"; type: "QModelIndex" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method { name: "submit"; type: "bool" }
+ Method { name: "revert" }
+ Method {
+ name: "hasIndex"
+ type: "bool"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "hasIndex"
+ type: "bool"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method {
+ name: "index"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "index"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method {
+ name: "parent"
+ type: "QModelIndex"
+ Parameter { name: "child"; type: "QModelIndex" }
+ }
+ Method {
+ name: "sibling"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "idx"; type: "QModelIndex" }
+ }
+ Method {
+ name: "rowCount"
+ type: "int"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "rowCount"; type: "int" }
+ Method {
+ name: "columnCount"
+ type: "int"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "columnCount"; type: "int" }
+ Method {
+ name: "hasChildren"
+ type: "bool"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "hasChildren"; type: "bool" }
+ Method {
+ name: "data"
+ type: "QVariant"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "data"
+ type: "QVariant"
+ Parameter { name: "index"; type: "QModelIndex" }
+ }
+ Method {
+ name: "setData"
+ type: "bool"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "setData"
+ type: "bool"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "value"; type: "QVariant" }
+ }
+ Method {
+ name: "headerData"
+ type: "QVariant"
+ Parameter { name: "section"; type: "int" }
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "headerData"
+ type: "QVariant"
+ Parameter { name: "section"; type: "int" }
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ }
+ Method {
+ name: "fetchMore"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "canFetchMore"
+ type: "bool"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "flags"
+ type: "Qt::ItemFlags"
+ Parameter { name: "index"; type: "QModelIndex" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "hits"; type: "int" }
+ Parameter { name: "flags"; type: "Qt::MatchFlags" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "hits"; type: "int" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ }
+ }
+ Component { name: "QAbstractListModel"; prototype: "QAbstractItemModel" }
Component {
name: "QQuickFolderListModel"
prototype: "QAbstractListModel"
@@ -52,5 +318,10 @@ Module {
Parameter { name: "idx"; type: "int" }
Parameter { name: "property"; type: "string" }
}
+ Method {
+ name: "indexOf"
+ type: "int"
+ Parameter { name: "file"; type: "QUrl" }
+ }
}
}
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
index 80b32e64ef..8bfbf09769 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
@@ -197,7 +197,7 @@ QString QQuickFolderListModelPrivate::resolvePath(const QUrl &path)
QUrl localUrl = QUrl(localPath);
QString fullPath = localUrl.path();
if (localUrl.scheme().length())
- fullPath = localUrl.scheme() + ":" + fullPath;
+ fullPath = localUrl.scheme() + QLatin1Char(':') + fullPath;
return QDir::cleanPath(fullPath);
}
@@ -788,6 +788,20 @@ QVariant QQuickFolderListModel::get(int idx, const QString &property) const
return QVariant();
}
+/*!
+ \qmlmethod int FolderListModel::indexOf(url file)
+ \since 5.6
+
+ Get the index of the given file URL if the model contains it,
+ or -1 if not.
+*/
+int QQuickFolderListModel::indexOf(const QUrl &file) const
+{
+ Q_D(const QQuickFolderListModel);
+ FileProperty toFind(QFileInfo(file.toLocalFile()));
+ return d->data.indexOf(toFind);
+}
+
#include "moc_qquickfolderlistmodel.cpp"
//![code]
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.h b/src/imports/folderlistmodel/qquickfolderlistmodel.h
index 63ed528556..fcfec56c87 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.h
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.h
@@ -109,9 +109,9 @@ public:
void setNameFilters(const QStringList &filters);
enum SortField { Unsorted, Name, Time, Size, Type };
+ Q_ENUM(SortField)
SortField sortField() const;
void setSortField(SortField field);
- Q_ENUMS(SortField)
bool sortReversed() const;
void setSortReversed(bool rev);
@@ -132,6 +132,7 @@ public:
Q_INVOKABLE bool isFolder(int index) const;
Q_INVOKABLE QVariant get(int idx, const QString &property) const;
+ Q_INVOKABLE int indexOf(const QUrl &file) const;
//![parserstatus]
virtual void classBegin();
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
index d0d47aa38c..f7002f9ed5 100644
--- a/src/imports/imports.pro
+++ b/src/imports/imports.pro
@@ -1,6 +1,7 @@
TEMPLATE = subdirs
SUBDIRS += \
+ qtqml \
folderlistmodel \
localstorage \
models \
@@ -16,3 +17,35 @@ qtHaveModule(quick) {
}
qtHaveModule(xmlpatterns) : SUBDIRS += xmllistmodel
+
+
+QMLTYPEFILE = builtins.qmltypes
+
+# install rule
+builtins.files = $$QMLTYPEFILE
+builtins.path = $$[QT_INSTALL_QML]
+INSTALLS += builtins
+
+# copy to build directory
+!force_independent:if(!debug_and_release|!build_all|CONFIG(release, debug|release)) {
+ defineReplace(qmlModStripSrcDir) {
+ return($$relative_path($$1, $$_PRO_FILE_PWD_))
+ }
+
+ qmltypes2build.input = QMLTYPEFILE
+ qmltypes2build.output = $$[QT_INSTALL_QML]/${QMAKE_FUNC_FILE_IN_qmlModStripSrcDir}
+ !contains(TEMPLATE, vc.*): qmltypes2build.variable_out = PRE_TARGETDEPS
+ qmltypes2build.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
+ qmltypes2build.name = COPY ${QMAKE_FILE_IN}
+ qmltypes2build.CONFIG = no_link no_clean
+
+ QMAKE_EXTRA_COMPILERS += qmltypes2build
+}
+
+# qmltypes target
+!cross_compile:if(build_pass|!debug_and_release) {
+ qtPrepareTool(QMLPLUGINDUMP, qmlplugindump)
+
+ qmltypes.commands = $$QMLPLUGINDUMP -builtins > $$PWD/$$QMLTYPEFILE
+ QMAKE_EXTRA_TARGETS += qmltypes
+}
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp
index b0ba3f9228..ada50774a7 100644
--- a/src/imports/localstorage/plugin.cpp
+++ b/src/imports/localstorage/plugin.cpp
@@ -68,7 +68,7 @@ QT_BEGIN_NAMESPACE
QV4::ScopedString v(scope, scope.engine->newString(desc)); \
QV4::ScopedObject ex(scope, scope.engine->newErrorObject(v)); \
ex->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("code"))).getPointer(), QV4::ScopedValue(scope, Primitive::fromInt32(error))); \
- args->setReturnValue(ctx->engine()->throwError(ex)); \
+ args->setReturnValue(scope.engine->throwError(ex)); \
return; \
}
@@ -97,7 +97,10 @@ namespace QV4 {
namespace Heap {
struct QQmlSqlDatabaseWrapper : public Object {
enum Type { Database, Query, Rows };
- QQmlSqlDatabaseWrapper(ExecutionEngine *e);
+ QQmlSqlDatabaseWrapper()
+ {
+ type = Database;
+ }
Type type;
QSqlDatabase database;
@@ -120,13 +123,13 @@ public:
static Heap::QQmlSqlDatabaseWrapper *create(QV4::ExecutionEngine *engine)
{
- return engine->memoryManager->alloc<QQmlSqlDatabaseWrapper>(engine);
+ return engine->memoryManager->allocObject<QQmlSqlDatabaseWrapper>();
}
~QQmlSqlDatabaseWrapper() {
}
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
};
}
@@ -135,11 +138,7 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QV4::QQmlSqlDatabaseWrapper);
-QV4::Heap::QQmlSqlDatabaseWrapper::QQmlSqlDatabaseWrapper(ExecutionEngine *e)
- : QV4::Heap::Object(e)
-{
- type = Database;
-}
+
static ReturnedValue qmlsqldatabase_version(CallContext *ctx)
{
@@ -214,7 +213,7 @@ static QString qmlsqldatabase_databaseFile(const QString& connectionName, QV4::E
return qmlsqldatabase_databasesPath(engine) + QDir::separator() + connectionName;
}
-static ReturnedValue qmlsqldatabase_rows_index(QQmlSqlDatabaseWrapper *r, ExecutionEngine *v4, quint32 index, bool *hasProperty = 0)
+static ReturnedValue qmlsqldatabase_rows_index(const QQmlSqlDatabaseWrapper *r, ExecutionEngine *v4, quint32 index, bool *hasProperty = 0)
{
Scope scope(v4);
@@ -238,15 +237,14 @@ static ReturnedValue qmlsqldatabase_rows_index(QQmlSqlDatabaseWrapper *r, Execut
}
}
-ReturnedValue QQmlSqlDatabaseWrapper::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue QQmlSqlDatabaseWrapper::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
- QV4::Scope scope(static_cast<QQmlSqlDatabaseWrapper *>(m)->engine());
Q_ASSERT(m->as<QQmlSqlDatabaseWrapper>());
- QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, static_cast<QQmlSqlDatabaseWrapper *>(m));
+ const QQmlSqlDatabaseWrapper *r = static_cast<const QQmlSqlDatabaseWrapper *>(m);
if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
return Object::getIndexed(m, index, hasProperty);
- return qmlsqldatabase_rows_index(r, scope.engine, index, hasProperty);
+ return qmlsqldatabase_rows_index(r, r->engine(), index, hasProperty);
}
static ReturnedValue qmlsqldatabase_rows_item(CallContext *ctx)
@@ -285,13 +283,13 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
if (query.prepare(sql)) {
if (ctx->argc() > 1) {
ScopedValue values(scope, ctx->args()[1]);
- if (values->asArrayObject()) {
+ if (values->as<ArrayObject>()) {
ScopedArrayObject array(scope, values);
quint32 size = array->getLength();
QV4::ScopedValue v(scope);
for (quint32 ii = 0; ii < size; ++ii)
query.bindValue(ii, scope.engine->toVariant((v = array->getIndexed(ii)), -1));
- } else if (values->asObject()) {
+ } else if (values->as<Object>()) {
ScopedObject object(scope, values);
ObjectIterator it(scope, object, ObjectIterator::WithProtoChain|ObjectIterator::EnumerableOnly);
ScopedValue key(scope);
@@ -304,7 +302,7 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
if (key->isString()) {
query.bindValue(key->stringValue()->toQString(), v);
} else {
- assert(key->isInteger());
+ Q_ASSERT(key->isInteger());
query.bindValue(key->integerValue(), v);
}
}
@@ -401,7 +399,7 @@ static ReturnedValue qmlsqldatabase_changeVersion(CallContext *ctx)
db.transaction();
ScopedCallData callData(scope, 1);
- callData->thisObject = scope.engine->globalObject();
+ callData->thisObject = scope.engine->globalObject;
callData->args[0] = w;
TransactionRollback rollbackOnException(&db, &w->d()->inTransaction);
@@ -433,7 +431,7 @@ static ReturnedValue qmlsqldatabase_transaction_shared(CallContext *ctx, bool re
if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Database)
V4THROW_REFERENCE("Not a SQLDatabase object");
- FunctionObject *callback = ctx->argc() ? ctx->args()[0].asFunctionObject() : 0;
+ const FunctionObject *callback = ctx->argc() ? ctx->args()[0].as<FunctionObject>() : 0;
if (!callback)
V4THROW_SQL(SQLEXCEPTION_UNKNOWN_ERR, QQmlEngine::tr("transaction: missing callback"));
@@ -450,7 +448,7 @@ static ReturnedValue qmlsqldatabase_transaction_shared(CallContext *ctx, bool re
db.transaction();
if (callback) {
ScopedCallData callData(scope, 1);
- callData->thisObject = scope.engine->globalObject();
+ callData->thisObject = scope.engine->globalObject;
callData->args[0] = w;
TransactionRollback rollbackOnException(&db, &w->d()->inTransaction);
callback->call(callData);
@@ -660,7 +658,6 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
{
#ifndef QT_NO_SETTINGS
QV4::Scope scope(args->v4engine());
- QV4::ScopedContext ctx(scope, args->v4engine()->currentContext());
if (scope.engine->qmlEngine()->offlineStoragePath().isEmpty())
V4THROW_SQL2(SQLEXCEPTION_DATABASE_ERR, QQmlEngine::tr("SQL: can't create database, offline storage is disabled."));
@@ -673,7 +670,7 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
QString dbversion = (v = (*args)[1])->toQStringNoThrow();
QString dbdescription = (v = (*args)[2])->toQStringNoThrow();
int dbestimatedsize = (v = (*args)[3])->toInt32();
- FunctionObject *dbcreationCallback = (v = (*args)[4])->asFunctionObject();
+ FunctionObject *dbcreationCallback = (v = (*args)[4])->as<FunctionObject>();
QCryptographicHash md5(QCryptographicHash::Md5);
md5.addData(dbname.toUtf8());
@@ -722,9 +719,8 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
db->d()->version = version;
if (created && dbcreationCallback) {
- Scope scope(ctx);
ScopedCallData callData(scope, 1);
- callData->thisObject = scope.engine->globalObject();
+ callData->thisObject = scope.engine->globalObject;
callData->args[0] = db;
dbcreationCallback->call(callData);
}
diff --git a/src/imports/localstorage/plugins.qmltypes b/src/imports/localstorage/plugins.qmltypes
index ff4c897f58..7d81cdf6f4 100644
--- a/src/imports/localstorage/plugins.qmltypes
+++ b/src/imports/localstorage/plugins.qmltypes
@@ -1,4 +1,4 @@
-import QtQuick.tooling 1.1
+import QtQuick.tooling 1.2
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
@@ -7,6 +7,7 @@ import QtQuick.tooling 1.1
// 'qmlplugindump -nonrelocatable QtQuick.LocalStorage 2.0'
Module {
+ dependencies: []
Component {
name: "QQuickLocalStorage"
prototype: "QObject"
diff --git a/src/imports/models/models.pro b/src/imports/models/models.pro
index 6a2952cd82..c94ba833ad 100644
--- a/src/imports/models/models.pro
+++ b/src/imports/models/models.pro
@@ -1,7 +1,7 @@
CXX_MODULE = qml
TARGET = modelsplugin
TARGETPATH = QtQml/Models.2
-IMPORT_VERSION = 2.2
+IMPORT_VERSION = 2.3
SOURCES += \
plugin.cpp
diff --git a/src/imports/models/plugins.qmltypes b/src/imports/models/plugins.qmltypes
index e81a971e79..0bd52a13fd 100644
--- a/src/imports/models/plugins.qmltypes
+++ b/src/imports/models/plugins.qmltypes
@@ -1,12 +1,13 @@
-import QtQuick.tooling 1.1
+import QtQuick.tooling 1.2
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable QtQml.Models 2.2'
+// 'qmlplugindump -nonrelocatable QtQml.Models 2.3'
Module {
+ dependencies: []
Component {
name: "QAbstractItemModel"
prototype: "QObject"
@@ -527,10 +528,55 @@ Module {
name: "QQmlObjectModel"
defaultProperty: "children"
prototype: "QQmlInstanceModel"
- exports: ["QtQml.Models/ObjectModel 2.1"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQml.Models/ObjectModel 2.1",
+ "QtQml.Models/ObjectModel 2.3"
+ ]
+ exportMetaObjectRevisions: [0, 3]
attachedType: "QQmlObjectModelAttached"
Property { name: "children"; type: "QObject"; isList: true; isReadonly: true }
+ Method { name: "clear"; revision: 3 }
+ Method {
+ name: "get"
+ revision: 3
+ type: "QObject*"
+ Parameter { name: "index"; type: "int" }
+ }
+ Method {
+ name: "append"
+ revision: 3
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ Method {
+ name: "insert"
+ revision: 3
+ Parameter { name: "index"; type: "int" }
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ Method {
+ name: "move"
+ revision: 3
+ Parameter { name: "from"; type: "int" }
+ Parameter { name: "to"; type: "int" }
+ Parameter { name: "n"; type: "int" }
+ }
+ Method {
+ name: "move"
+ revision: 3
+ Parameter { name: "from"; type: "int" }
+ Parameter { name: "to"; type: "int" }
+ }
+ Method {
+ name: "remove"
+ revision: 3
+ Parameter { name: "index"; type: "int" }
+ Parameter { name: "n"; type: "int" }
+ }
+ Method {
+ name: "remove"
+ revision: 3
+ Parameter { name: "index"; type: "int" }
+ }
}
Component {
name: "QQmlObjectModelAttached"
diff --git a/src/imports/particles/plugins.qmltypes b/src/imports/particles/plugins.qmltypes
index b1b825dea6..ce78392610 100644
--- a/src/imports/particles/plugins.qmltypes
+++ b/src/imports/particles/plugins.qmltypes
@@ -1,4 +1,4 @@
-import QtQuick.tooling 1.1
+import QtQuick.tooling 1.2
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
@@ -7,6 +7,7 @@ import QtQuick.tooling 1.1
// 'qmlplugindump -nonrelocatable QtQuick.Particles 2.0'
Module {
+ dependencies: []
Component {
name: "QQuickAgeAffector"
defaultProperty: "data"
@@ -491,6 +492,160 @@ Module {
}
}
Component {
+ name: "QQuickItem"
+ defaultProperty: "data"
+ prototype: "QObject"
+ Enum {
+ name: "TransformOrigin"
+ values: {
+ "TopLeft": 0,
+ "Top": 1,
+ "TopRight": 2,
+ "Left": 3,
+ "Center": 4,
+ "Right": 5,
+ "BottomLeft": 6,
+ "Bottom": 7,
+ "BottomRight": 8
+ }
+ }
+ Property { name: "parent"; type: "QQuickItem"; isPointer: true }
+ Property { name: "data"; type: "QObject"; isList: true; isReadonly: true }
+ Property { name: "resources"; type: "QObject"; isList: true; isReadonly: true }
+ Property { name: "children"; type: "QQuickItem"; isList: true; isReadonly: true }
+ Property { name: "x"; type: "double" }
+ Property { name: "y"; type: "double" }
+ Property { name: "z"; type: "double" }
+ Property { name: "width"; type: "double" }
+ Property { name: "height"; type: "double" }
+ Property { name: "opacity"; type: "double" }
+ Property { name: "enabled"; type: "bool" }
+ Property { name: "visible"; type: "bool" }
+ Property { name: "visibleChildren"; type: "QQuickItem"; isList: true; isReadonly: true }
+ Property { name: "states"; type: "QQuickState"; isList: true; isReadonly: true }
+ Property { name: "transitions"; type: "QQuickTransition"; isList: true; isReadonly: true }
+ Property { name: "state"; type: "string" }
+ Property { name: "childrenRect"; type: "QRectF"; isReadonly: true }
+ Property { name: "anchors"; type: "QQuickAnchors"; isReadonly: true; isPointer: true }
+ Property { name: "left"; type: "QQuickAnchorLine"; isReadonly: true }
+ Property { name: "right"; type: "QQuickAnchorLine"; isReadonly: true }
+ Property { name: "horizontalCenter"; type: "QQuickAnchorLine"; isReadonly: true }
+ Property { name: "top"; type: "QQuickAnchorLine"; isReadonly: true }
+ Property { name: "bottom"; type: "QQuickAnchorLine"; isReadonly: true }
+ Property { name: "verticalCenter"; type: "QQuickAnchorLine"; isReadonly: true }
+ Property { name: "baseline"; type: "QQuickAnchorLine"; isReadonly: true }
+ Property { name: "baselineOffset"; type: "double" }
+ Property { name: "clip"; type: "bool" }
+ Property { name: "focus"; type: "bool" }
+ Property { name: "activeFocus"; type: "bool"; isReadonly: true }
+ Property { name: "activeFocusOnTab"; revision: 1; type: "bool" }
+ Property { name: "rotation"; type: "double" }
+ Property { name: "scale"; type: "double" }
+ Property { name: "transformOrigin"; type: "TransformOrigin" }
+ Property { name: "transformOriginPoint"; type: "QPointF"; isReadonly: true }
+ Property { name: "transform"; type: "QQuickTransform"; isList: true; isReadonly: true }
+ Property { name: "smooth"; type: "bool" }
+ Property { name: "antialiasing"; type: "bool" }
+ Property { name: "implicitWidth"; type: "double" }
+ Property { name: "implicitHeight"; type: "double" }
+ Property { name: "layer"; type: "QQuickItemLayer"; isReadonly: true; isPointer: true }
+ Signal {
+ name: "childrenRectChanged"
+ Parameter { type: "QRectF" }
+ }
+ Signal {
+ name: "baselineOffsetChanged"
+ Parameter { type: "double" }
+ }
+ Signal {
+ name: "stateChanged"
+ Parameter { type: "string" }
+ }
+ Signal {
+ name: "focusChanged"
+ Parameter { type: "bool" }
+ }
+ Signal {
+ name: "activeFocusChanged"
+ Parameter { type: "bool" }
+ }
+ Signal {
+ name: "activeFocusOnTabChanged"
+ revision: 1
+ Parameter { type: "bool" }
+ }
+ Signal {
+ name: "parentChanged"
+ Parameter { type: "QQuickItem"; isPointer: true }
+ }
+ Signal {
+ name: "transformOriginChanged"
+ Parameter { type: "TransformOrigin" }
+ }
+ Signal {
+ name: "smoothChanged"
+ Parameter { type: "bool" }
+ }
+ Signal {
+ name: "antialiasingChanged"
+ Parameter { type: "bool" }
+ }
+ Signal {
+ name: "clipChanged"
+ Parameter { type: "bool" }
+ }
+ Signal {
+ name: "windowChanged"
+ revision: 1
+ Parameter { name: "window"; type: "QQuickWindow"; isPointer: true }
+ }
+ Method { name: "update" }
+ Method {
+ name: "grabToImage"
+ revision: 2
+ type: "bool"
+ Parameter { name: "callback"; type: "QJSValue" }
+ Parameter { name: "targetSize"; type: "QSize" }
+ }
+ Method {
+ name: "grabToImage"
+ revision: 2
+ type: "bool"
+ Parameter { name: "callback"; type: "QJSValue" }
+ }
+ Method {
+ name: "contains"
+ type: "bool"
+ Parameter { name: "point"; type: "QPointF" }
+ }
+ Method {
+ name: "mapFromItem"
+ Parameter { type: "QQmlV4Function"; isPointer: true }
+ }
+ Method {
+ name: "mapToItem"
+ Parameter { type: "QQmlV4Function"; isPointer: true }
+ }
+ Method { name: "forceActiveFocus" }
+ Method {
+ name: "forceActiveFocus"
+ Parameter { name: "reason"; type: "Qt::FocusReason" }
+ }
+ Method {
+ name: "nextItemInFocusChain"
+ revision: 1
+ type: "QQuickItem*"
+ Parameter { name: "forward"; type: "bool" }
+ }
+ Method { name: "nextItemInFocusChain"; revision: 1; type: "QQuickItem*" }
+ Method {
+ name: "childAt"
+ type: "QQuickItem*"
+ Parameter { name: "x"; type: "double" }
+ Parameter { name: "y"; type: "double" }
+ }
+ }
+ Component {
name: "QQuickItemParticle"
defaultProperty: "data"
prototype: "QQuickParticlePainter"
@@ -996,6 +1151,56 @@ Module {
}
}
Component {
+ name: "QQuickStochasticState"
+ prototype: "QObject"
+ Property { name: "duration"; type: "int" }
+ Property { name: "durationVariation"; type: "int" }
+ Property { name: "randomStart"; type: "bool" }
+ Property { name: "to"; type: "QVariantMap" }
+ Property { name: "name"; type: "string" }
+ Signal {
+ name: "durationChanged"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Signal {
+ name: "nameChanged"
+ Parameter { name: "arg"; type: "string" }
+ }
+ Signal {
+ name: "toChanged"
+ Parameter { name: "arg"; type: "QVariantMap" }
+ }
+ Signal {
+ name: "durationVariationChanged"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Signal { name: "entered" }
+ Signal {
+ name: "randomStartChanged"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ Method {
+ name: "setDuration"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setName"
+ Parameter { name: "arg"; type: "string" }
+ }
+ Method {
+ name: "setTo"
+ Parameter { name: "arg"; type: "QVariantMap" }
+ }
+ Method {
+ name: "setDurationVariation"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setRandomStart"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ }
+ Component {
name: "QQuickTargetDirection"
prototype: "QQuickDirection"
exports: ["QtQuick.Particles/TargetDirection 2.0"]
diff --git a/src/imports/qtqml/plugins.qmltypes b/src/imports/qtqml/plugins.qmltypes
new file mode 100644
index 0000000000..864aca1f32
--- /dev/null
+++ b/src/imports/qtqml/plugins.qmltypes
@@ -0,0 +1,222 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable QtQml 2.2'
+
+Module {
+ dependencies: []
+ Component {
+ name: "QObject"
+ exports: ["QtQml/QtObject 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "objectName"; type: "string" }
+ Signal {
+ name: "objectNameChanged"
+ Parameter { name: "objectName"; type: "string" }
+ }
+ Method { name: "toString" }
+ Method { name: "destroy" }
+ Method {
+ name: "destroy"
+ Parameter { name: "delay"; type: "int" }
+ }
+ }
+ Component {
+ name: "QQmlBind"
+ prototype: "QObject"
+ exports: ["QtQml/Binding 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "target"; type: "QObject"; isPointer: true }
+ Property { name: "property"; type: "string" }
+ Property { name: "value"; type: "QVariant" }
+ Property { name: "when"; type: "bool" }
+ }
+ Component {
+ name: "QQmlComponent"
+ prototype: "QObject"
+ exports: ["QML/Component 1.0", "QtQml/Component 2.0"]
+ exportMetaObjectRevisions: [0, 0]
+ attachedType: "QQmlComponentAttached"
+ Enum {
+ name: "CompilationMode"
+ values: {
+ "PreferSynchronous": 0,
+ "Asynchronous": 1
+ }
+ }
+ Enum {
+ name: "Status"
+ values: {
+ "Null": 0,
+ "Ready": 1,
+ "Loading": 2,
+ "Error": 3
+ }
+ }
+ Property { name: "progress"; type: "double"; isReadonly: true }
+ Property { name: "status"; type: "Status"; isReadonly: true }
+ Property { name: "url"; type: "QUrl"; isReadonly: true }
+ Signal {
+ name: "statusChanged"
+ Parameter { type: "QQmlComponent::Status" }
+ }
+ Signal {
+ name: "progressChanged"
+ Parameter { type: "double" }
+ }
+ Method {
+ name: "loadUrl"
+ Parameter { name: "url"; type: "QUrl" }
+ }
+ Method {
+ name: "loadUrl"
+ Parameter { name: "url"; type: "QUrl" }
+ Parameter { name: "mode"; type: "CompilationMode" }
+ }
+ Method {
+ name: "setData"
+ Parameter { type: "QByteArray" }
+ Parameter { name: "baseUrl"; type: "QUrl" }
+ }
+ Method { name: "errorString"; type: "string" }
+ }
+ Component {
+ name: "QQmlComponentAttached"
+ prototype: "QObject"
+ Signal { name: "completed" }
+ Signal { name: "destruction" }
+ }
+ Component {
+ name: "QQmlConnections"
+ prototype: "QObject"
+ exports: ["QtQml/Connections 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "target"; type: "QObject"; isPointer: true }
+ Property { name: "ignoreUnknownSignals"; type: "bool" }
+ }
+ Component {
+ name: "QQmlInstanceModel"
+ prototype: "QObject"
+ Property { name: "count"; type: "int"; isReadonly: true }
+ Signal {
+ name: "modelUpdated"
+ Parameter { name: "changeSet"; type: "QQmlChangeSet" }
+ Parameter { name: "reset"; type: "bool" }
+ }
+ Signal {
+ name: "createdItem"
+ Parameter { name: "index"; type: "int" }
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ Signal {
+ name: "initItem"
+ Parameter { name: "index"; type: "int" }
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ Signal {
+ name: "destroyingItem"
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ }
+ Component {
+ name: "QQmlInstantiator"
+ defaultProperty: "delegate"
+ prototype: "QObject"
+ exports: ["QtQml/Instantiator 2.1"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "active"; type: "bool" }
+ Property { name: "asynchronous"; type: "bool" }
+ Property { name: "model"; type: "QVariant" }
+ Property { name: "count"; type: "int"; isReadonly: true }
+ Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
+ Property { name: "object"; type: "QObject"; isReadonly: true; isPointer: true }
+ Signal {
+ name: "objectAdded"
+ Parameter { name: "index"; type: "int" }
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ Signal {
+ name: "objectRemoved"
+ Parameter { name: "index"; type: "int" }
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ Method {
+ name: "objectAt"
+ type: "QObject*"
+ Parameter { name: "index"; type: "int" }
+ }
+ }
+ Component {
+ name: "QQmlLocale"
+ exports: ["QtQml/Locale 2.2"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "MeasurementSystem"
+ values: {
+ "MetricSystem": 0,
+ "ImperialSystem": 1,
+ "ImperialUSSystem": 1,
+ "ImperialUKSystem": 2
+ }
+ }
+ Enum {
+ name: "FormatType"
+ values: {
+ "LongFormat": 0,
+ "ShortFormat": 1,
+ "NarrowFormat": 2
+ }
+ }
+ Enum {
+ name: "CurrencySymbolFormat"
+ values: {
+ "CurrencyIsoCode": 0,
+ "CurrencySymbol": 1,
+ "CurrencyDisplayName": 2
+ }
+ }
+ Enum {
+ name: "DayOfWeek"
+ values: {
+ "Sunday": 0,
+ "Monday": 1,
+ "Tuesday": 2,
+ "Wednesday": 3,
+ "Thursday": 4,
+ "Friday": 5,
+ "Saturday": 6
+ }
+ }
+ }
+ Component {
+ name: "QQmlTimer"
+ prototype: "QObject"
+ exports: ["QtQml/Timer 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "interval"; type: "int" }
+ Property { name: "running"; type: "bool" }
+ Property { name: "repeat"; type: "bool" }
+ Property { name: "triggeredOnStart"; type: "bool" }
+ Property { name: "parent"; type: "QObject"; isReadonly: true; isPointer: true }
+ Signal { name: "triggered" }
+ Method { name: "start" }
+ Method { name: "stop" }
+ Method { name: "restart" }
+ }
+ Component {
+ name: "QQuickMouseEvent"
+ prototype: "QObject"
+ Property { name: "x"; type: "double"; isReadonly: true }
+ Property { name: "y"; type: "double"; isReadonly: true }
+ Property { name: "button"; type: "int"; isReadonly: true }
+ Property { name: "buttons"; type: "int"; isReadonly: true }
+ Property { name: "modifiers"; type: "int"; isReadonly: true }
+ Property { name: "wasHeld"; type: "bool"; isReadonly: true }
+ Property { name: "isClick"; type: "bool"; isReadonly: true }
+ Property { name: "accepted"; type: "bool" }
+ }
+}
diff --git a/src/imports/qtqml/qmldir b/src/imports/qtqml/qmldir
new file mode 100644
index 0000000000..8175ebb1a1
--- /dev/null
+++ b/src/imports/qtqml/qmldir
@@ -0,0 +1,2 @@
+module QtQml
+typeinfo plugins.qmltypes
diff --git a/src/imports/qtqml/qtqml.pro b/src/imports/qtqml/qtqml.pro
new file mode 100644
index 0000000000..05ef15a542
--- /dev/null
+++ b/src/imports/qtqml/qtqml.pro
@@ -0,0 +1,14 @@
+TARGETPATH = QtQml
+QML_FILES += plugins.qmltypes
+
+load(qml_module)
+
+# qmltypes target
+!cross_compile:if(build_pass|!debug_and_release) {
+ qtPrepareTool(QMLPLUGINDUMP, qmlplugindump)
+
+ # Use QtQml version defined in qmlplugindump source
+ # TODO: retrieve the correct version from QtQml
+ qmltypes.commands = $$QMLPLUGINDUMP -nonrelocatable QtQml 2.2 > $$PWD/plugins.qmltypes
+ QMAKE_EXTRA_TARGETS += qmltypes
+}
diff --git a/src/imports/qtquick2/plugins.qmltypes b/src/imports/qtquick2/plugins.qmltypes
index d98e9e6981..b11906ee09 100644
--- a/src/imports/qtquick2/plugins.qmltypes
+++ b/src/imports/qtquick2/plugins.qmltypes
@@ -1,12 +1,13 @@
-import QtQuick.tooling 1.1
+import QtQuick.tooling 1.2
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -builtins'
+// 'qmlplugindump -nonrelocatable QtQuick 2.6'
Module {
+ dependencies: []
Component {
name: "QAbstractItemModel"
prototype: "QObject"
@@ -139,6 +140,137 @@ Module {
}
Method { name: "submit"; type: "bool" }
Method { name: "revert" }
+ Method {
+ name: "hasIndex"
+ type: "bool"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "hasIndex"
+ type: "bool"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method {
+ name: "index"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "index"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method {
+ name: "parent"
+ type: "QModelIndex"
+ Parameter { name: "child"; type: "QModelIndex" }
+ }
+ Method {
+ name: "sibling"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "idx"; type: "QModelIndex" }
+ }
+ Method {
+ name: "rowCount"
+ type: "int"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "rowCount"; type: "int" }
+ Method {
+ name: "columnCount"
+ type: "int"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "columnCount"; type: "int" }
+ Method {
+ name: "hasChildren"
+ type: "bool"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "hasChildren"; type: "bool" }
+ Method {
+ name: "data"
+ type: "QVariant"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "data"
+ type: "QVariant"
+ Parameter { name: "index"; type: "QModelIndex" }
+ }
+ Method {
+ name: "setData"
+ type: "bool"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "setData"
+ type: "bool"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "value"; type: "QVariant" }
+ }
+ Method {
+ name: "headerData"
+ type: "QVariant"
+ Parameter { name: "section"; type: "int" }
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "headerData"
+ type: "QVariant"
+ Parameter { name: "section"; type: "int" }
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ }
+ Method {
+ name: "fetchMore"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "canFetchMore"
+ type: "bool"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "flags"
+ type: "Qt::ItemFlags"
+ Parameter { name: "index"; type: "QModelIndex" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "hits"; type: "int" }
+ Parameter { name: "flags"; type: "Qt::MatchFlags" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "hits"; type: "int" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ }
}
Component { name: "QAbstractListModel"; prototype: "QAbstractItemModel" }
Component {
@@ -299,27 +431,13 @@ Module {
"Quit": 65,
"FullScreen": 66,
"Deselect": 67,
- "DeleteCompleteLine": 68
+ "DeleteCompleteLine": 68,
+ "Backspace": 69,
+ "Cancel": 70
}
}
}
Component {
- name: "QObject"
- exports: ["QtQml/QtObject 2.0", "QtQuick/QtObject 2.0"]
- exportMetaObjectRevisions: [0, 0]
- Property { name: "objectName"; type: "string" }
- Signal {
- name: "objectNameChanged"
- Parameter { name: "objectName"; type: "string" }
- }
- Method { name: "toString" }
- Method { name: "destroy" }
- Method {
- name: "destroy"
- Parameter { name: "delay"; type: "int" }
- }
- }
- Component {
name: "QQmlApplication"
prototype: "QObject"
Property { name: "arguments"; type: "QStringList"; isReadonly: true }
@@ -346,83 +464,6 @@ Module {
}
}
Component {
- name: "QQmlBind"
- prototype: "QObject"
- exports: ["QtQml/Binding 2.0", "QtQuick/Binding 2.0"]
- exportMetaObjectRevisions: [0, 0]
- Property { name: "target"; type: "QObject"; isPointer: true }
- Property { name: "property"; type: "string" }
- Property { name: "value"; type: "QVariant" }
- Property { name: "when"; type: "bool" }
- }
- Component {
- name: "QQmlComponent"
- prototype: "QObject"
- exports: [
- "QML/Component 1.0",
- "QtQml/Component 2.0",
- "QtQuick/Component 2.0"
- ]
- exportMetaObjectRevisions: [0, 0, 0]
- attachedType: "QQmlComponentAttached"
- Enum {
- name: "CompilationMode"
- values: {
- "PreferSynchronous": 0,
- "Asynchronous": 1
- }
- }
- Enum {
- name: "Status"
- values: {
- "Null": 0,
- "Ready": 1,
- "Loading": 2,
- "Error": 3
- }
- }
- Property { name: "progress"; type: "double"; isReadonly: true }
- Property { name: "status"; type: "Status"; isReadonly: true }
- Property { name: "url"; type: "QUrl"; isReadonly: true }
- Signal {
- name: "statusChanged"
- Parameter { type: "QQmlComponent::Status" }
- }
- Signal {
- name: "progressChanged"
- Parameter { type: "double" }
- }
- Method {
- name: "loadUrl"
- Parameter { name: "url"; type: "QUrl" }
- }
- Method {
- name: "loadUrl"
- Parameter { name: "url"; type: "QUrl" }
- Parameter { name: "mode"; type: "CompilationMode" }
- }
- Method {
- name: "setData"
- Parameter { type: "QByteArray" }
- Parameter { name: "baseUrl"; type: "QUrl" }
- }
- Method { name: "errorString"; type: "string" }
- }
- Component {
- name: "QQmlComponentAttached"
- prototype: "QObject"
- Signal { name: "completed" }
- Signal { name: "destruction" }
- }
- Component {
- name: "QQmlConnections"
- prototype: "QObject"
- exports: ["QtQml/Connections 2.0", "QtQuick/Connections 2.0"]
- exportMetaObjectRevisions: [0, 0]
- Property { name: "target"; type: "QObject"; isPointer: true }
- Property { name: "ignoreUnknownSignals"; type: "bool" }
- }
- Component {
name: "QQmlDelegateModel"
defaultProperty: "delegate"
prototype: "QQmlInstanceModel"
@@ -514,7 +555,6 @@ Module {
Component { name: "QQmlDelegateModelParts"; prototype: "QObject" }
Component {
name: "QQmlEasingValueType"
- prototype: "QQmlValueType"
exports: ["QtQuick/Easing 2.0"]
isCreatable: false
exportMetaObjectRevisions: [0]
@@ -576,58 +616,6 @@ Module {
Property { name: "bezierCurve"; type: "QVariantList" }
}
Component {
- name: "QQmlInstanceModel"
- prototype: "QObject"
- Property { name: "count"; type: "int"; isReadonly: true }
- Signal {
- name: "modelUpdated"
- Parameter { name: "changeSet"; type: "QQmlChangeSet" }
- Parameter { name: "reset"; type: "bool" }
- }
- Signal {
- name: "createdItem"
- Parameter { name: "index"; type: "int" }
- Parameter { name: "object"; type: "QObject"; isPointer: true }
- }
- Signal {
- name: "initItem"
- Parameter { name: "index"; type: "int" }
- Parameter { name: "object"; type: "QObject"; isPointer: true }
- }
- Signal {
- name: "destroyingItem"
- Parameter { name: "object"; type: "QObject"; isPointer: true }
- }
- }
- Component {
- name: "QQmlInstantiator"
- defaultProperty: "delegate"
- prototype: "QObject"
- exports: ["QtQml/Instantiator 2.1", "QtQuick/Instantiator 2.1"]
- exportMetaObjectRevisions: [0, 0]
- Property { name: "active"; type: "bool" }
- Property { name: "asynchronous"; type: "bool" }
- Property { name: "model"; type: "QVariant" }
- Property { name: "count"; type: "int"; isReadonly: true }
- Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
- Property { name: "object"; type: "QObject"; isReadonly: true; isPointer: true }
- Signal {
- name: "objectAdded"
- Parameter { name: "index"; type: "int" }
- Parameter { name: "object"; type: "QObject"; isPointer: true }
- }
- Signal {
- name: "objectRemoved"
- Parameter { name: "index"; type: "int" }
- Parameter { name: "object"; type: "QObject"; isPointer: true }
- }
- Method {
- name: "objectAt"
- type: "QObject*"
- Parameter { name: "index"; type: "int" }
- }
- }
- Component {
name: "QQmlListElement"
prototype: "QObject"
exports: ["QtQuick/ListElement 2.0"]
@@ -678,49 +666,6 @@ Module {
Method { name: "sync" }
}
Component {
- name: "QQmlLocale"
- exports: ["QtQml/Locale 2.2", "QtQuick/Locale 2.0"]
- isCreatable: false
- exportMetaObjectRevisions: [0, 0]
- Enum {
- name: "MeasurementSystem"
- values: {
- "MetricSystem": 0,
- "ImperialSystem": 1,
- "ImperialUSSystem": 1,
- "ImperialUKSystem": 2
- }
- }
- Enum {
- name: "FormatType"
- values: {
- "LongFormat": 0,
- "ShortFormat": 1,
- "NarrowFormat": 2
- }
- }
- Enum {
- name: "CurrencySymbolFormat"
- values: {
- "CurrencyIsoCode": 0,
- "CurrencySymbol": 1,
- "CurrencyDisplayName": 2
- }
- }
- Enum {
- name: "DayOfWeek"
- values: {
- "Sunday": 0,
- "Monday": 1,
- "Tuesday": 2,
- "Wednesday": 3,
- "Thursday": 4,
- "Friday": 5,
- "Saturday": 6
- }
- }
- }
- Component {
name: "QQmlObjectModel"
defaultProperty: "children"
prototype: "QQmlInstanceModel"
@@ -728,6 +673,48 @@ Module {
exportMetaObjectRevisions: [0]
attachedType: "QQmlObjectModelAttached"
Property { name: "children"; type: "QObject"; isList: true; isReadonly: true }
+ Method { name: "clear"; revision: 3 }
+ Method {
+ name: "get"
+ revision: 3
+ type: "QObject*"
+ Parameter { name: "index"; type: "int" }
+ }
+ Method {
+ name: "append"
+ revision: 3
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ Method {
+ name: "insert"
+ revision: 3
+ Parameter { name: "index"; type: "int" }
+ Parameter { name: "object"; type: "QObject"; isPointer: true }
+ }
+ Method {
+ name: "move"
+ revision: 3
+ Parameter { name: "from"; type: "int" }
+ Parameter { name: "to"; type: "int" }
+ Parameter { name: "n"; type: "int" }
+ }
+ Method {
+ name: "move"
+ revision: 3
+ Parameter { name: "from"; type: "int" }
+ Parameter { name: "to"; type: "int" }
+ }
+ Method {
+ name: "remove"
+ revision: 3
+ Parameter { name: "index"; type: "int" }
+ Parameter { name: "n"; type: "int" }
+ }
+ Method {
+ name: "remove"
+ revision: 3
+ Parameter { name: "index"; type: "int" }
+ }
}
Component {
name: "QQmlObjectModelAttached"
@@ -735,22 +722,6 @@ Module {
Property { name: "index"; type: "int"; isReadonly: true }
}
Component {
- name: "QQmlTimer"
- prototype: "QObject"
- exports: ["QtQml/Timer 2.0", "QtQuick/Timer 2.0"]
- exportMetaObjectRevisions: [0, 0]
- Property { name: "interval"; type: "int" }
- Property { name: "running"; type: "bool" }
- Property { name: "repeat"; type: "bool" }
- Property { name: "triggeredOnStart"; type: "bool" }
- Property { name: "parent"; type: "QObject"; isReadonly: true; isPointer: true }
- Signal { name: "triggered" }
- Method { name: "start" }
- Method { name: "stop" }
- Method { name: "restart" }
- }
- Component { name: "QQmlValueType"; prototype: "QObject" }
- Component {
name: "QQuickAbstractAnimation"
prototype: "QObject"
exports: ["QtQuick/Animation 2.0"]
@@ -880,6 +851,12 @@ Module {
Signal { name: "toggleAction" }
Signal { name: "increaseAction" }
Signal { name: "decreaseAction" }
+ Signal { name: "scrollUpAction" }
+ Signal { name: "scrollDownAction" }
+ Signal { name: "scrollLeftAction" }
+ Signal { name: "scrollRightAction" }
+ Signal { name: "previousPageAction" }
+ Signal { name: "nextPageAction" }
Method { name: "valueChanged" }
Method { name: "cursorPositionChanged" }
Method {
@@ -1188,14 +1165,24 @@ Module {
name: "QQuickBasePositioner"
defaultProperty: "data"
prototype: "QQuickImplicitSizeItem"
- exports: ["QtQuick/Positioner 2.0"]
+ exports: ["QtQuick/Positioner 2.0", "QtQuick/Positioner 2.6"]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [0, 6]
attachedType: "QQuickPositionerAttached"
Property { name: "spacing"; type: "double" }
Property { name: "populate"; type: "QQuickTransition"; isPointer: true }
Property { name: "move"; type: "QQuickTransition"; isPointer: true }
Property { name: "add"; type: "QQuickTransition"; isPointer: true }
+ Property { name: "padding"; revision: 6; type: "double" }
+ Property { name: "topPadding"; revision: 6; type: "double" }
+ Property { name: "leftPadding"; revision: 6; type: "double" }
+ Property { name: "rightPadding"; revision: 6; type: "double" }
+ Property { name: "bottomPadding"; revision: 6; type: "double" }
+ Signal { name: "paddingChanged"; revision: 6 }
+ Signal { name: "topPaddingChanged"; revision: 6 }
+ Signal { name: "leftPaddingChanged"; revision: 6 }
+ Signal { name: "rightPaddingChanged"; revision: 6 }
+ Signal { name: "bottomPaddingChanged"; revision: 6 }
}
Component {
name: "QQuickBehavior"
@@ -1330,8 +1317,8 @@ Module {
name: "QQuickColumn"
defaultProperty: "data"
prototype: "QQuickBasePositioner"
- exports: ["QtQuick/Column 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQuick/Column 2.0", "QtQuick/Column 2.6"]
+ exportMetaObjectRevisions: [0, 6]
}
Component {
name: "QQuickCurve"
@@ -1469,6 +1456,10 @@ Module {
Parameter { type: "QQmlV4Function"; isPointer: true }
}
Method {
+ name: "getDataAsArrayBuffer"
+ Parameter { type: "QQmlV4Function"; isPointer: true }
+ }
+ Method {
name: "acceptProposedAction"
Parameter { type: "QQmlV4Function"; isPointer: true }
}
@@ -1478,6 +1469,14 @@ Module {
}
}
Component {
+ name: "QQuickEnterKeyAttached"
+ prototype: "QObject"
+ exports: ["QtQuick/EnterKey 2.6"]
+ isCreatable: false
+ exportMetaObjectRevisions: [6]
+ Property { name: "type"; type: "Qt::EnterKeyType" }
+ }
+ Component {
name: "QQuickFlickable"
defaultProperty: "flickableData"
prototype: "QQuickItem"
@@ -1488,7 +1487,8 @@ Module {
values: {
"StopAtBounds": 0,
"DragOverBounds": 1,
- "DragAndOvershootBounds": 2
+ "OvershootBounds": 2,
+ "DragAndOvershootBounds": 3
}
}
Enum {
@@ -1608,8 +1608,8 @@ Module {
name: "QQuickFlow"
defaultProperty: "data"
prototype: "QQuickBasePositioner"
- exports: ["QtQuick/Flow 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQuick/Flow 2.0", "QtQuick/Flow 2.6"]
+ exportMetaObjectRevisions: [0, 6]
Enum {
name: "Flow"
values: {
@@ -1703,17 +1703,20 @@ Module {
}
Component {
name: "QQuickFontValueType"
- prototype: "QQmlValueType"
exports: ["QtQuick/Font 2.0"]
isCreatable: false
exportMetaObjectRevisions: [0]
Enum {
name: "FontWeight"
values: {
+ "Thin": 0,
+ "ExtraLight": 12,
"Light": 25,
"Normal": 50,
+ "Medium": 57,
"DemiBold": 63,
"Bold": 75,
+ "ExtraBold": 81,
"Black": 87
}
}
@@ -1728,6 +1731,7 @@ Module {
}
}
Property { name: "family"; type: "string" }
+ Property { name: "styleName"; type: "string" }
Property { name: "bold"; type: "bool" }
Property { name: "weight"; type: "FontWeight" }
Property { name: "italic"; type: "bool" }
@@ -1739,6 +1743,7 @@ Module {
Property { name: "capitalization"; type: "Capitalization" }
Property { name: "letterSpacing"; type: "double" }
Property { name: "wordSpacing"; type: "double" }
+ Method { name: "toString"; type: "string" }
}
Component {
name: "QQuickGrabGestureEvent"
@@ -1768,8 +1773,8 @@ Module {
name: "QQuickGrid"
defaultProperty: "data"
prototype: "QQuickBasePositioner"
- exports: ["QtQuick/Grid 2.0", "QtQuick/Grid 2.1"]
- exportMetaObjectRevisions: [0, 1]
+ exports: ["QtQuick/Grid 2.0", "QtQuick/Grid 2.1", "QtQuick/Grid 2.6"]
+ exportMetaObjectRevisions: [0, 1, 6]
Enum {
name: "Flow"
values: {
@@ -1868,8 +1873,12 @@ Module {
name: "QQuickImage"
defaultProperty: "data"
prototype: "QQuickImageBase"
- exports: ["QtQuick/Image 2.0", "QtQuick/Image 2.3"]
- exportMetaObjectRevisions: [0, 1]
+ exports: [
+ "QtQuick/Image 2.0",
+ "QtQuick/Image 2.3",
+ "QtQuick/Image 2.5"
+ ]
+ exportMetaObjectRevisions: [0, 1, 2]
Enum {
name: "HAlignment"
values: {
@@ -1904,6 +1913,7 @@ Module {
Property { name: "horizontalAlignment"; type: "HAlignment" }
Property { name: "verticalAlignment"; type: "VAlignment" }
Property { name: "mipmap"; revision: 1; type: "bool" }
+ Property { name: "autoTransform"; revision: 2; type: "bool" }
Signal { name: "paintedGeometryChanged" }
Signal {
name: "horizontalAlignmentChanged"
@@ -1918,6 +1928,7 @@ Module {
revision: 1
Parameter { type: "bool" }
}
+ Signal { name: "autoTransformChanged"; revision: 2 }
}
Component {
name: "QQuickImageBase"
@@ -2149,6 +2160,7 @@ Module {
Property { name: "format"; type: "QQuickShaderEffectSource::Format" }
Property { name: "samplerName"; type: "QByteArray" }
Property { name: "effect"; type: "QQmlComponent"; isPointer: true }
+ Property { name: "textureMirroring"; type: "QQuickShaderEffectSource::TextureMirroring" }
Signal {
name: "enabledChanged"
Parameter { name: "enabled"; type: "bool" }
@@ -2185,6 +2197,10 @@ Module {
name: "sourceRectChanged"
Parameter { name: "sourceRect"; type: "QRectF" }
}
+ Signal {
+ name: "textureMirroringChanged"
+ Parameter { name: "mirroring"; type: "QQuickShaderEffectSource::TextureMirroring" }
+ }
}
Component {
name: "QQuickItemView"
@@ -2623,13 +2639,18 @@ Module {
name: "QQuickMouseArea"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick/MouseArea 2.0", "QtQuick/MouseArea 2.4"]
- exportMetaObjectRevisions: [0, 1]
+ exports: [
+ "QtQuick/MouseArea 2.0",
+ "QtQuick/MouseArea 2.4",
+ "QtQuick/MouseArea 2.5"
+ ]
+ exportMetaObjectRevisions: [0, 1, 2]
Property { name: "mouseX"; type: "double"; isReadonly: true }
Property { name: "mouseY"; type: "double"; isReadonly: true }
Property { name: "containsMouse"; type: "bool"; isReadonly: true }
Property { name: "pressed"; type: "bool"; isReadonly: true }
Property { name: "enabled"; type: "bool" }
+ Property { name: "scrollGestureEnabled"; revision: 2; type: "bool" }
Property { name: "pressedButtons"; type: "Qt::MouseButtons"; isReadonly: true }
Property { name: "acceptedButtons"; type: "Qt::MouseButtons" }
Property { name: "hoverEnabled"; type: "bool" }
@@ -2639,6 +2660,7 @@ Module {
Property { name: "cursorShape"; type: "Qt::CursorShape" }
Property { name: "containsPress"; revision: 1; type: "bool"; isReadonly: true }
Signal { name: "hoveredChanged" }
+ Signal { name: "scrollGestureEnabledChanged"; revision: 2 }
Signal {
name: "positionChanged"
Parameter { name: "mouse"; type: "QQuickMouseEvent"; isPointer: true }
@@ -2681,18 +2703,6 @@ Module {
Signal { name: "containsPressChanged"; revision: 1 }
}
Component {
- name: "QQuickMouseEvent"
- prototype: "QObject"
- Property { name: "x"; type: "double"; isReadonly: true }
- Property { name: "y"; type: "double"; isReadonly: true }
- Property { name: "button"; type: "int"; isReadonly: true }
- Property { name: "buttons"; type: "int"; isReadonly: true }
- Property { name: "modifiers"; type: "int"; isReadonly: true }
- Property { name: "wasHeld"; type: "bool"; isReadonly: true }
- Property { name: "isClick"; type: "bool"; isReadonly: true }
- Property { name: "accepted"; type: "bool" }
- }
- Component {
name: "QQuickMultiPointTouchArea"
defaultProperty: "data"
prototype: "QQuickItem"
@@ -2801,6 +2811,7 @@ Module {
Property { name: "fillColor"; type: "QColor" }
Property { name: "contentsScale"; type: "double" }
Property { name: "renderTarget"; type: "RenderTarget" }
+ Property { name: "textureSize"; type: "QSize" }
}
Component {
name: "QQuickParallelAnimation"
@@ -3131,8 +3142,8 @@ Module {
name: "QQuickPinchArea"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick/PinchArea 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQuick/PinchArea 2.0", "QtQuick/PinchArea 2.5"]
+ exportMetaObjectRevisions: [0, 1]
Property { name: "enabled"; type: "bool" }
Property { name: "pinch"; type: "QQuickPinch"; isReadonly: true; isPointer: true }
Signal {
@@ -3147,6 +3158,11 @@ Module {
name: "pinchFinished"
Parameter { name: "pinch"; type: "QQuickPinchEvent"; isPointer: true }
}
+ Signal {
+ name: "smartZoom"
+ revision: 1
+ Parameter { name: "pinch"; type: "QQuickPinchEvent"; isPointer: true }
+ }
}
Component {
name: "QQuickPinchEvent"
@@ -3324,8 +3340,8 @@ Module {
name: "QQuickRow"
defaultProperty: "data"
prototype: "QQuickBasePositioner"
- exports: ["QtQuick/Row 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQuick/Row 2.0", "QtQuick/Row 2.6"]
+ exportMetaObjectRevisions: [0, 6]
Property { name: "layoutDirection"; type: "Qt::LayoutDirection" }
Property { name: "effectiveLayoutDirection"; type: "Qt::LayoutDirection"; isReadonly: true }
}
@@ -3413,8 +3429,11 @@ Module {
name: "QQuickShaderEffectSource"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick/ShaderEffectSource 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick/ShaderEffectSource 2.0",
+ "QtQuick/ShaderEffectSource 2.6"
+ ]
+ exportMetaObjectRevisions: [0, 1]
Enum {
name: "WrapMode"
values: {
@@ -3432,6 +3451,14 @@ Module {
"RGBA": 6408
}
}
+ Enum {
+ name: "TextureMirroring"
+ values: {
+ "NoMirroring": 0,
+ "MirrorHorizontally": 1,
+ "MirrorVertically": 2
+ }
+ }
Property { name: "wrapMode"; type: "WrapMode" }
Property { name: "sourceItem"; type: "QQuickItem"; isPointer: true }
Property { name: "sourceRect"; type: "QRectF" }
@@ -3441,10 +3468,25 @@ Module {
Property { name: "hideSource"; type: "bool" }
Property { name: "mipmap"; type: "bool" }
Property { name: "recursive"; type: "bool" }
+ Property { name: "textureMirroring"; revision: 1; type: "TextureMirroring" }
Signal { name: "scheduledUpdateCompleted" }
Method { name: "scheduleUpdate" }
}
Component {
+ name: "QQuickShortcut"
+ prototype: "QObject"
+ exports: ["QtQuick/Shortcut 2.5", "QtQuick/Shortcut 2.6"]
+ exportMetaObjectRevisions: [0, 1]
+ Property { name: "sequence"; type: "QVariant" }
+ Property { name: "nativeText"; revision: 1; type: "string"; isReadonly: true }
+ Property { name: "portableText"; revision: 1; type: "string"; isReadonly: true }
+ Property { name: "enabled"; type: "bool" }
+ Property { name: "autoRepeat"; type: "bool" }
+ Property { name: "context"; type: "Qt::ShortcutContext" }
+ Signal { name: "activated" }
+ Signal { name: "activatedAmbiguously" }
+ }
+ Component {
name: "QQuickSmoothedAnimation"
prototype: "QQuickNumberAnimation"
exports: ["QtQuick/SmoothedAnimation 2.0"]
@@ -3755,8 +3797,13 @@ Module {
name: "QQuickText"
defaultProperty: "data"
prototype: "QQuickImplicitSizeItem"
- exports: ["QtQuick/Text 2.0", "QtQuick/Text 2.2", "QtQuick/Text 2.3"]
- exportMetaObjectRevisions: [0, 2, 3]
+ exports: [
+ "QtQuick/Text 2.0",
+ "QtQuick/Text 2.2",
+ "QtQuick/Text 2.3",
+ "QtQuick/Text 2.6"
+ ]
+ exportMetaObjectRevisions: [0, 2, 3, 6]
Enum {
name: "HAlignment"
values: {
@@ -3861,6 +3908,11 @@ Module {
Property { name: "fontSizeMode"; type: "FontSizeMode" }
Property { name: "renderType"; type: "RenderType" }
Property { name: "hoveredLink"; revision: 2; type: "string"; isReadonly: true }
+ Property { name: "padding"; revision: 6; type: "double" }
+ Property { name: "topPadding"; revision: 6; type: "double" }
+ Property { name: "leftPadding"; revision: 6; type: "double" }
+ Property { name: "rightPadding"; revision: 6; type: "double" }
+ Property { name: "bottomPadding"; revision: 6; type: "double" }
Signal {
name: "textChanged"
Parameter { name: "text"; type: "string" }
@@ -3911,6 +3963,11 @@ Module {
name: "lineLaidOut"
Parameter { name: "line"; type: "QQuickTextLine"; isPointer: true }
}
+ Signal { name: "paddingChanged"; revision: 6 }
+ Signal { name: "topPaddingChanged"; revision: 6 }
+ Signal { name: "leftPaddingChanged"; revision: 6 }
+ Signal { name: "rightPaddingChanged"; revision: 6 }
+ Signal { name: "bottomPaddingChanged"; revision: 6 }
Method { name: "doLayout" }
Method {
name: "linkAt"
@@ -3929,9 +3986,10 @@ Module {
"QtQuick/TextEdit 2.0",
"QtQuick/TextEdit 2.1",
"QtQuick/TextEdit 2.2",
- "QtQuick/TextEdit 2.3"
+ "QtQuick/TextEdit 2.3",
+ "QtQuick/TextEdit 2.6"
]
- exportMetaObjectRevisions: [0, 1, 2, 3]
+ exportMetaObjectRevisions: [0, 1, 2, 3, 6]
Enum {
name: "HAlignment"
values: {
@@ -4026,6 +4084,11 @@ Module {
isPointer: true
}
Property { name: "hoveredLink"; revision: 2; type: "string"; isReadonly: true }
+ Property { name: "padding"; revision: 6; type: "double" }
+ Property { name: "topPadding"; revision: 6; type: "double" }
+ Property { name: "leftPadding"; revision: 6; type: "double" }
+ Property { name: "rightPadding"; revision: 6; type: "double" }
+ Property { name: "bottomPadding"; revision: 6; type: "double" }
Signal { name: "contentSizeChanged" }
Signal {
name: "colorChanged"
@@ -4097,6 +4160,12 @@ Module {
revision: 2
Parameter { name: "link"; type: "string" }
}
+ Signal { name: "editingFinished"; revision: 6 }
+ Signal { name: "paddingChanged"; revision: 6 }
+ Signal { name: "topPaddingChanged"; revision: 6 }
+ Signal { name: "leftPaddingChanged"; revision: 6 }
+ Signal { name: "rightPaddingChanged"; revision: 6 }
+ Signal { name: "bottomPaddingChanged"; revision: 6 }
Method { name: "selectAll" }
Method { name: "selectWord" }
Method {
@@ -4185,9 +4254,10 @@ Module {
exports: [
"QtQuick/TextInput 2.0",
"QtQuick/TextInput 2.2",
- "QtQuick/TextInput 2.4"
+ "QtQuick/TextInput 2.4",
+ "QtQuick/TextInput 2.6"
]
- exportMetaObjectRevisions: [0, 2, 3]
+ exportMetaObjectRevisions: [0, 2, 3, 6]
Enum {
name: "EchoMode"
values: {
@@ -4283,6 +4353,11 @@ Module {
Property { name: "contentWidth"; type: "double"; isReadonly: true }
Property { name: "contentHeight"; type: "double"; isReadonly: true }
Property { name: "renderType"; type: "RenderType" }
+ Property { name: "padding"; revision: 6; type: "double" }
+ Property { name: "topPadding"; revision: 6; type: "double" }
+ Property { name: "leftPadding"; revision: 6; type: "double" }
+ Property { name: "rightPadding"; revision: 6; type: "double" }
+ Property { name: "bottomPadding"; revision: 6; type: "double" }
Signal { name: "accepted" }
Signal { name: "editingFinished"; revision: 2 }
Signal {
@@ -4339,6 +4414,11 @@ Module {
Parameter { name: "mode"; type: "SelectionMode" }
}
Signal { name: "contentSizeChanged" }
+ Signal { name: "paddingChanged"; revision: 6 }
+ Signal { name: "topPaddingChanged"; revision: 6 }
+ Signal { name: "leftPaddingChanged"; revision: 6 }
+ Signal { name: "rightPaddingChanged"; revision: 6 }
+ Signal { name: "bottomPaddingChanged"; revision: 6 }
Method { name: "selectAll" }
Method { name: "selectWord" }
Method {
@@ -4583,1515 +4663,4 @@ Module {
prototype: "QObject"
Signal { name: "changed" }
}
- Component {
- name: "Qt"
- Enum {
- name: "GlobalColor"
- values: {
- "color0": 0,
- "color1": 1,
- "black": 2,
- "white": 3,
- "darkGray": 4,
- "gray": 5,
- "lightGray": 6,
- "red": 7,
- "green": 8,
- "blue": 9,
- "cyan": 10,
- "magenta": 11,
- "yellow": 12,
- "darkRed": 13,
- "darkGreen": 14,
- "darkBlue": 15,
- "darkCyan": 16,
- "darkMagenta": 17,
- "darkYellow": 18,
- "transparent": 19
- }
- }
- Enum {
- name: "KeyboardModifiers"
- values: {
- "NoModifier": 0,
- "ShiftModifier": 33554432,
- "ControlModifier": 67108864,
- "AltModifier": 134217728,
- "MetaModifier": 268435456,
- "KeypadModifier": 536870912,
- "GroupSwitchModifier": 1073741824,
- "KeyboardModifierMask": -33554432
- }
- }
- Enum {
- name: "MouseButtons"
- values: {
- "NoButton": 0,
- "LeftButton": 1,
- "RightButton": 2,
- "MidButton": 4,
- "MiddleButton": 4,
- "BackButton": 8,
- "XButton1": 8,
- "ExtraButton1": 8,
- "ForwardButton": 16,
- "XButton2": 16,
- "ExtraButton2": 16,
- "TaskButton": 32,
- "ExtraButton3": 32,
- "ExtraButton4": 64,
- "ExtraButton5": 128,
- "ExtraButton6": 256,
- "ExtraButton7": 512,
- "ExtraButton8": 1024,
- "ExtraButton9": 2048,
- "ExtraButton10": 4096,
- "ExtraButton11": 8192,
- "ExtraButton12": 16384,
- "ExtraButton13": 32768,
- "ExtraButton14": 65536,
- "ExtraButton15": 131072,
- "ExtraButton16": 262144,
- "ExtraButton17": 524288,
- "ExtraButton18": 1048576,
- "ExtraButton19": 2097152,
- "ExtraButton20": 4194304,
- "ExtraButton21": 8388608,
- "ExtraButton22": 16777216,
- "ExtraButton23": 33554432,
- "ExtraButton24": 67108864,
- "AllButtons": 134217727,
- "MaxMouseButton": 67108864,
- "MouseButtonMask": -1
- }
- }
- Enum {
- name: "Orientation"
- values: {
- "Horizontal": 1,
- "Vertical": 2
- }
- }
- Enum {
- name: "Orientations"
- values: {
- "Horizontal": 1,
- "Vertical": 2
- }
- }
- Enum {
- name: "FocusPolicy"
- values: {
- "NoFocus": 0,
- "TabFocus": 1,
- "ClickFocus": 2,
- "StrongFocus": 11,
- "WheelFocus": 15
- }
- }
- Enum {
- name: "SortOrder"
- values: {
- "AscendingOrder": 0,
- "DescendingOrder": 1
- }
- }
- Enum {
- name: "Alignment"
- values: {
- "AlignLeft": 1,
- "AlignLeading": 1,
- "AlignRight": 2,
- "AlignTrailing": 2,
- "AlignHCenter": 4,
- "AlignJustify": 8,
- "AlignAbsolute": 16,
- "AlignHorizontal_Mask": 31,
- "AlignTop": 32,
- "AlignBottom": 64,
- "AlignVCenter": 128,
- "AlignBaseline": 256,
- "AlignVertical_Mask": 480,
- "AlignCenter": 132
- }
- }
- Enum {
- name: "TextElideMode"
- values: {
- "ElideLeft": 0,
- "ElideRight": 1,
- "ElideMiddle": 2,
- "ElideNone": 3
- }
- }
- Enum {
- name: "WindowType"
- values: {
- "Widget": 0,
- "Window": 1,
- "Dialog": 3,
- "Sheet": 5,
- "Drawer": 7,
- "Popup": 9,
- "Tool": 11,
- "ToolTip": 13,
- "SplashScreen": 15,
- "Desktop": 17,
- "SubWindow": 18,
- "ForeignWindow": 33,
- "CoverWindow": 65,
- "WindowType_Mask": 255,
- "MSWindowsFixedSizeDialogHint": 256,
- "MSWindowsOwnDC": 512,
- "BypassWindowManagerHint": 1024,
- "X11BypassWindowManagerHint": 1024,
- "FramelessWindowHint": 2048,
- "WindowTitleHint": 4096,
- "WindowSystemMenuHint": 8192,
- "WindowMinimizeButtonHint": 16384,
- "WindowMaximizeButtonHint": 32768,
- "WindowMinMaxButtonsHint": 49152,
- "WindowContextHelpButtonHint": 65536,
- "WindowShadeButtonHint": 131072,
- "WindowStaysOnTopHint": 262144,
- "WindowTransparentForInput": 524288,
- "WindowOverridesSystemGestures": 1048576,
- "WindowDoesNotAcceptFocus": 2097152,
- "CustomizeWindowHint": 33554432,
- "WindowStaysOnBottomHint": 67108864,
- "WindowCloseButtonHint": 134217728,
- "MacWindowToolBarButtonHint": 268435456,
- "BypassGraphicsProxyWidget": 536870912,
- "WindowOkButtonHint": 524288,
- "WindowCancelButtonHint": 1048576,
- "NoDropShadowWindowHint": 1073741824,
- "WindowFullscreenButtonHint": -2147483648
- }
- }
- Enum {
- name: "WindowFlags"
- values: {
- "Widget": 0,
- "Window": 1,
- "Dialog": 3,
- "Sheet": 5,
- "Drawer": 7,
- "Popup": 9,
- "Tool": 11,
- "ToolTip": 13,
- "SplashScreen": 15,
- "Desktop": 17,
- "SubWindow": 18,
- "ForeignWindow": 33,
- "CoverWindow": 65,
- "WindowType_Mask": 255,
- "MSWindowsFixedSizeDialogHint": 256,
- "MSWindowsOwnDC": 512,
- "BypassWindowManagerHint": 1024,
- "X11BypassWindowManagerHint": 1024,
- "FramelessWindowHint": 2048,
- "WindowTitleHint": 4096,
- "WindowSystemMenuHint": 8192,
- "WindowMinimizeButtonHint": 16384,
- "WindowMaximizeButtonHint": 32768,
- "WindowMinMaxButtonsHint": 49152,
- "WindowContextHelpButtonHint": 65536,
- "WindowShadeButtonHint": 131072,
- "WindowStaysOnTopHint": 262144,
- "WindowTransparentForInput": 524288,
- "WindowOverridesSystemGestures": 1048576,
- "WindowDoesNotAcceptFocus": 2097152,
- "CustomizeWindowHint": 33554432,
- "WindowStaysOnBottomHint": 67108864,
- "WindowCloseButtonHint": 134217728,
- "MacWindowToolBarButtonHint": 268435456,
- "BypassGraphicsProxyWidget": 536870912,
- "WindowOkButtonHint": 524288,
- "WindowCancelButtonHint": 1048576,
- "NoDropShadowWindowHint": 1073741824,
- "WindowFullscreenButtonHint": -2147483648
- }
- }
- Enum {
- name: "WindowState"
- values: {
- "WindowNoState": 0,
- "WindowMinimized": 1,
- "WindowMaximized": 2,
- "WindowFullScreen": 4,
- "WindowActive": 8
- }
- }
- Enum {
- name: "WindowStates"
- values: {
- "WindowNoState": 0,
- "WindowMinimized": 1,
- "WindowMaximized": 2,
- "WindowFullScreen": 4,
- "WindowActive": 8
- }
- }
- Enum {
- name: "ApplicationState"
- values: {
- "ApplicationSuspended": 0,
- "ApplicationHidden": 1,
- "ApplicationInactive": 2,
- "ApplicationActive": 4
- }
- }
- Enum {
- name: "ScreenOrientation"
- values: {
- "PrimaryOrientation": 0,
- "PortraitOrientation": 1,
- "LandscapeOrientation": 2,
- "InvertedPortraitOrientation": 4,
- "InvertedLandscapeOrientation": 8
- }
- }
- Enum {
- name: "ScreenOrientations"
- values: {
- "PrimaryOrientation": 0,
- "PortraitOrientation": 1,
- "LandscapeOrientation": 2,
- "InvertedPortraitOrientation": 4,
- "InvertedLandscapeOrientation": 8
- }
- }
- Enum {
- name: "WidgetAttribute"
- values: {
- "WA_Disabled": 0,
- "WA_UnderMouse": 1,
- "WA_MouseTracking": 2,
- "WA_ContentsPropagated": 3,
- "WA_OpaquePaintEvent": 4,
- "WA_NoBackground": 4,
- "WA_StaticContents": 5,
- "WA_LaidOut": 7,
- "WA_PaintOnScreen": 8,
- "WA_NoSystemBackground": 9,
- "WA_UpdatesDisabled": 10,
- "WA_Mapped": 11,
- "WA_MacNoClickThrough": 12,
- "WA_InputMethodEnabled": 14,
- "WA_WState_Visible": 15,
- "WA_WState_Hidden": 16,
- "WA_ForceDisabled": 32,
- "WA_KeyCompression": 33,
- "WA_PendingMoveEvent": 34,
- "WA_PendingResizeEvent": 35,
- "WA_SetPalette": 36,
- "WA_SetFont": 37,
- "WA_SetCursor": 38,
- "WA_NoChildEventsFromChildren": 39,
- "WA_WindowModified": 41,
- "WA_Resized": 42,
- "WA_Moved": 43,
- "WA_PendingUpdate": 44,
- "WA_InvalidSize": 45,
- "WA_MacBrushedMetal": 46,
- "WA_MacMetalStyle": 46,
- "WA_CustomWhatsThis": 47,
- "WA_LayoutOnEntireRect": 48,
- "WA_OutsideWSRange": 49,
- "WA_GrabbedShortcut": 50,
- "WA_TransparentForMouseEvents": 51,
- "WA_PaintUnclipped": 52,
- "WA_SetWindowIcon": 53,
- "WA_NoMouseReplay": 54,
- "WA_DeleteOnClose": 55,
- "WA_RightToLeft": 56,
- "WA_SetLayoutDirection": 57,
- "WA_NoChildEventsForParent": 58,
- "WA_ForceUpdatesDisabled": 59,
- "WA_WState_Created": 60,
- "WA_WState_CompressKeys": 61,
- "WA_WState_InPaintEvent": 62,
- "WA_WState_Reparented": 63,
- "WA_WState_ConfigPending": 64,
- "WA_WState_Polished": 66,
- "WA_WState_DND": 67,
- "WA_WState_OwnSizePolicy": 68,
- "WA_WState_ExplicitShowHide": 69,
- "WA_ShowModal": 70,
- "WA_MouseNoMask": 71,
- "WA_GroupLeader": 72,
- "WA_NoMousePropagation": 73,
- "WA_Hover": 74,
- "WA_InputMethodTransparent": 75,
- "WA_QuitOnClose": 76,
- "WA_KeyboardFocusChange": 77,
- "WA_AcceptDrops": 78,
- "WA_DropSiteRegistered": 79,
- "WA_ForceAcceptDrops": 79,
- "WA_WindowPropagation": 80,
- "WA_NoX11EventCompression": 81,
- "WA_TintedBackground": 82,
- "WA_X11OpenGLOverlay": 83,
- "WA_AlwaysShowToolTips": 84,
- "WA_MacOpaqueSizeGrip": 85,
- "WA_SetStyle": 86,
- "WA_SetLocale": 87,
- "WA_MacShowFocusRect": 88,
- "WA_MacNormalSize": 89,
- "WA_MacSmallSize": 90,
- "WA_MacMiniSize": 91,
- "WA_LayoutUsesWidgetRect": 92,
- "WA_StyledBackground": 93,
- "WA_MSWindowsUseDirect3D": 94,
- "WA_CanHostQMdiSubWindowTitleBar": 95,
- "WA_MacAlwaysShowToolWindow": 96,
- "WA_StyleSheet": 97,
- "WA_ShowWithoutActivating": 98,
- "WA_X11BypassTransientForHint": 99,
- "WA_NativeWindow": 100,
- "WA_DontCreateNativeAncestors": 101,
- "WA_MacVariableSize": 102,
- "WA_DontShowOnScreen": 103,
- "WA_X11NetWmWindowTypeDesktop": 104,
- "WA_X11NetWmWindowTypeDock": 105,
- "WA_X11NetWmWindowTypeToolBar": 106,
- "WA_X11NetWmWindowTypeMenu": 107,
- "WA_X11NetWmWindowTypeUtility": 108,
- "WA_X11NetWmWindowTypeSplash": 109,
- "WA_X11NetWmWindowTypeDialog": 110,
- "WA_X11NetWmWindowTypeDropDownMenu": 111,
- "WA_X11NetWmWindowTypePopupMenu": 112,
- "WA_X11NetWmWindowTypeToolTip": 113,
- "WA_X11NetWmWindowTypeNotification": 114,
- "WA_X11NetWmWindowTypeCombo": 115,
- "WA_X11NetWmWindowTypeDND": 116,
- "WA_MacFrameworkScaled": 117,
- "WA_SetWindowModality": 118,
- "WA_WState_WindowOpacitySet": 119,
- "WA_TranslucentBackground": 120,
- "WA_AcceptTouchEvents": 121,
- "WA_WState_AcceptedTouchBeginEvent": 122,
- "WA_TouchPadAcceptSingleTouchEvents": 123,
- "WA_X11DoNotAcceptFocus": 126,
- "WA_MacNoShadow": 127,
- "WA_AlwaysStackOnTop": 128,
- "WA_AttributeCount": 129
- }
- }
- Enum {
- name: "ApplicationAttribute"
- values: {
- "AA_ImmediateWidgetCreation": 0,
- "AA_MSWindowsUseDirect3DByDefault": 1,
- "AA_DontShowIconsInMenus": 2,
- "AA_NativeWindows": 3,
- "AA_DontCreateNativeWidgetSiblings": 4,
- "AA_MacPluginApplication": 5,
- "AA_DontUseNativeMenuBar": 6,
- "AA_MacDontSwapCtrlAndMeta": 7,
- "AA_Use96Dpi": 8,
- "AA_X11InitThreads": 10,
- "AA_SynthesizeTouchForUnhandledMouseEvents": 11,
- "AA_SynthesizeMouseForUnhandledTouchEvents": 12,
- "AA_UseHighDpiPixmaps": 13,
- "AA_ForceRasterWidgets": 14,
- "AA_UseDesktopOpenGL": 15,
- "AA_UseOpenGLES": 16,
- "AA_UseSoftwareOpenGL": 17,
- "AA_ShareOpenGLContexts": 18,
- "AA_AttributeCount": 19
- }
- }
- Enum {
- name: "ImageConversionFlags"
- values: {
- "ColorMode_Mask": 3,
- "AutoColor": 0,
- "ColorOnly": 3,
- "MonoOnly": 2,
- "AlphaDither_Mask": 12,
- "ThresholdAlphaDither": 0,
- "OrderedAlphaDither": 4,
- "DiffuseAlphaDither": 8,
- "NoAlpha": 12,
- "Dither_Mask": 48,
- "DiffuseDither": 0,
- "OrderedDither": 16,
- "ThresholdDither": 32,
- "DitherMode_Mask": 192,
- "AutoDither": 0,
- "PreferDither": 64,
- "AvoidDither": 128,
- "NoOpaqueDetection": 256,
- "NoFormatConversion": 512
- }
- }
- Enum {
- name: "BGMode"
- values: {
- "TransparentMode": 0,
- "OpaqueMode": 1
- }
- }
- Enum {
- name: "Key"
- values: {
- "Key_Escape": 16777216,
- "Key_Tab": 16777217,
- "Key_Backtab": 16777218,
- "Key_Backspace": 16777219,
- "Key_Return": 16777220,
- "Key_Enter": 16777221,
- "Key_Insert": 16777222,
- "Key_Delete": 16777223,
- "Key_Pause": 16777224,
- "Key_Print": 16777225,
- "Key_SysReq": 16777226,
- "Key_Clear": 16777227,
- "Key_Home": 16777232,
- "Key_End": 16777233,
- "Key_Left": 16777234,
- "Key_Up": 16777235,
- "Key_Right": 16777236,
- "Key_Down": 16777237,
- "Key_PageUp": 16777238,
- "Key_PageDown": 16777239,
- "Key_Shift": 16777248,
- "Key_Control": 16777249,
- "Key_Meta": 16777250,
- "Key_Alt": 16777251,
- "Key_CapsLock": 16777252,
- "Key_NumLock": 16777253,
- "Key_ScrollLock": 16777254,
- "Key_F1": 16777264,
- "Key_F2": 16777265,
- "Key_F3": 16777266,
- "Key_F4": 16777267,
- "Key_F5": 16777268,
- "Key_F6": 16777269,
- "Key_F7": 16777270,
- "Key_F8": 16777271,
- "Key_F9": 16777272,
- "Key_F10": 16777273,
- "Key_F11": 16777274,
- "Key_F12": 16777275,
- "Key_F13": 16777276,
- "Key_F14": 16777277,
- "Key_F15": 16777278,
- "Key_F16": 16777279,
- "Key_F17": 16777280,
- "Key_F18": 16777281,
- "Key_F19": 16777282,
- "Key_F20": 16777283,
- "Key_F21": 16777284,
- "Key_F22": 16777285,
- "Key_F23": 16777286,
- "Key_F24": 16777287,
- "Key_F25": 16777288,
- "Key_F26": 16777289,
- "Key_F27": 16777290,
- "Key_F28": 16777291,
- "Key_F29": 16777292,
- "Key_F30": 16777293,
- "Key_F31": 16777294,
- "Key_F32": 16777295,
- "Key_F33": 16777296,
- "Key_F34": 16777297,
- "Key_F35": 16777298,
- "Key_Super_L": 16777299,
- "Key_Super_R": 16777300,
- "Key_Menu": 16777301,
- "Key_Hyper_L": 16777302,
- "Key_Hyper_R": 16777303,
- "Key_Help": 16777304,
- "Key_Direction_L": 16777305,
- "Key_Direction_R": 16777312,
- "Key_Space": 32,
- "Key_Any": 32,
- "Key_Exclam": 33,
- "Key_QuoteDbl": 34,
- "Key_NumberSign": 35,
- "Key_Dollar": 36,
- "Key_Percent": 37,
- "Key_Ampersand": 38,
- "Key_Apostrophe": 39,
- "Key_ParenLeft": 40,
- "Key_ParenRight": 41,
- "Key_Asterisk": 42,
- "Key_Plus": 43,
- "Key_Comma": 44,
- "Key_Minus": 45,
- "Key_Period": 46,
- "Key_Slash": 47,
- "Key_0": 48,
- "Key_1": 49,
- "Key_2": 50,
- "Key_3": 51,
- "Key_4": 52,
- "Key_5": 53,
- "Key_6": 54,
- "Key_7": 55,
- "Key_8": 56,
- "Key_9": 57,
- "Key_Colon": 58,
- "Key_Semicolon": 59,
- "Key_Less": 60,
- "Key_Equal": 61,
- "Key_Greater": 62,
- "Key_Question": 63,
- "Key_At": 64,
- "Key_A": 65,
- "Key_B": 66,
- "Key_C": 67,
- "Key_D": 68,
- "Key_E": 69,
- "Key_F": 70,
- "Key_G": 71,
- "Key_H": 72,
- "Key_I": 73,
- "Key_J": 74,
- "Key_K": 75,
- "Key_L": 76,
- "Key_M": 77,
- "Key_N": 78,
- "Key_O": 79,
- "Key_P": 80,
- "Key_Q": 81,
- "Key_R": 82,
- "Key_S": 83,
- "Key_T": 84,
- "Key_U": 85,
- "Key_V": 86,
- "Key_W": 87,
- "Key_X": 88,
- "Key_Y": 89,
- "Key_Z": 90,
- "Key_BracketLeft": 91,
- "Key_Backslash": 92,
- "Key_BracketRight": 93,
- "Key_AsciiCircum": 94,
- "Key_Underscore": 95,
- "Key_QuoteLeft": 96,
- "Key_BraceLeft": 123,
- "Key_Bar": 124,
- "Key_BraceRight": 125,
- "Key_AsciiTilde": 126,
- "Key_nobreakspace": 160,
- "Key_exclamdown": 161,
- "Key_cent": 162,
- "Key_sterling": 163,
- "Key_currency": 164,
- "Key_yen": 165,
- "Key_brokenbar": 166,
- "Key_section": 167,
- "Key_diaeresis": 168,
- "Key_copyright": 169,
- "Key_ordfeminine": 170,
- "Key_guillemotleft": 171,
- "Key_notsign": 172,
- "Key_hyphen": 173,
- "Key_registered": 174,
- "Key_macron": 175,
- "Key_degree": 176,
- "Key_plusminus": 177,
- "Key_twosuperior": 178,
- "Key_threesuperior": 179,
- "Key_acute": 180,
- "Key_mu": 181,
- "Key_paragraph": 182,
- "Key_periodcentered": 183,
- "Key_cedilla": 184,
- "Key_onesuperior": 185,
- "Key_masculine": 186,
- "Key_guillemotright": 187,
- "Key_onequarter": 188,
- "Key_onehalf": 189,
- "Key_threequarters": 190,
- "Key_questiondown": 191,
- "Key_Agrave": 192,
- "Key_Aacute": 193,
- "Key_Acircumflex": 194,
- "Key_Atilde": 195,
- "Key_Adiaeresis": 196,
- "Key_Aring": 197,
- "Key_AE": 198,
- "Key_Ccedilla": 199,
- "Key_Egrave": 200,
- "Key_Eacute": 201,
- "Key_Ecircumflex": 202,
- "Key_Ediaeresis": 203,
- "Key_Igrave": 204,
- "Key_Iacute": 205,
- "Key_Icircumflex": 206,
- "Key_Idiaeresis": 207,
- "Key_ETH": 208,
- "Key_Ntilde": 209,
- "Key_Ograve": 210,
- "Key_Oacute": 211,
- "Key_Ocircumflex": 212,
- "Key_Otilde": 213,
- "Key_Odiaeresis": 214,
- "Key_multiply": 215,
- "Key_Ooblique": 216,
- "Key_Ugrave": 217,
- "Key_Uacute": 218,
- "Key_Ucircumflex": 219,
- "Key_Udiaeresis": 220,
- "Key_Yacute": 221,
- "Key_THORN": 222,
- "Key_ssharp": 223,
- "Key_division": 247,
- "Key_ydiaeresis": 255,
- "Key_AltGr": 16781571,
- "Key_Multi_key": 16781600,
- "Key_Codeinput": 16781623,
- "Key_SingleCandidate": 16781628,
- "Key_MultipleCandidate": 16781629,
- "Key_PreviousCandidate": 16781630,
- "Key_Mode_switch": 16781694,
- "Key_Kanji": 16781601,
- "Key_Muhenkan": 16781602,
- "Key_Henkan": 16781603,
- "Key_Romaji": 16781604,
- "Key_Hiragana": 16781605,
- "Key_Katakana": 16781606,
- "Key_Hiragana_Katakana": 16781607,
- "Key_Zenkaku": 16781608,
- "Key_Hankaku": 16781609,
- "Key_Zenkaku_Hankaku": 16781610,
- "Key_Touroku": 16781611,
- "Key_Massyo": 16781612,
- "Key_Kana_Lock": 16781613,
- "Key_Kana_Shift": 16781614,
- "Key_Eisu_Shift": 16781615,
- "Key_Eisu_toggle": 16781616,
- "Key_Hangul": 16781617,
- "Key_Hangul_Start": 16781618,
- "Key_Hangul_End": 16781619,
- "Key_Hangul_Hanja": 16781620,
- "Key_Hangul_Jamo": 16781621,
- "Key_Hangul_Romaja": 16781622,
- "Key_Hangul_Jeonja": 16781624,
- "Key_Hangul_Banja": 16781625,
- "Key_Hangul_PreHanja": 16781626,
- "Key_Hangul_PostHanja": 16781627,
- "Key_Hangul_Special": 16781631,
- "Key_Dead_Grave": 16781904,
- "Key_Dead_Acute": 16781905,
- "Key_Dead_Circumflex": 16781906,
- "Key_Dead_Tilde": 16781907,
- "Key_Dead_Macron": 16781908,
- "Key_Dead_Breve": 16781909,
- "Key_Dead_Abovedot": 16781910,
- "Key_Dead_Diaeresis": 16781911,
- "Key_Dead_Abovering": 16781912,
- "Key_Dead_Doubleacute": 16781913,
- "Key_Dead_Caron": 16781914,
- "Key_Dead_Cedilla": 16781915,
- "Key_Dead_Ogonek": 16781916,
- "Key_Dead_Iota": 16781917,
- "Key_Dead_Voiced_Sound": 16781918,
- "Key_Dead_Semivoiced_Sound": 16781919,
- "Key_Dead_Belowdot": 16781920,
- "Key_Dead_Hook": 16781921,
- "Key_Dead_Horn": 16781922,
- "Key_Back": 16777313,
- "Key_Forward": 16777314,
- "Key_Stop": 16777315,
- "Key_Refresh": 16777316,
- "Key_VolumeDown": 16777328,
- "Key_VolumeMute": 16777329,
- "Key_VolumeUp": 16777330,
- "Key_BassBoost": 16777331,
- "Key_BassUp": 16777332,
- "Key_BassDown": 16777333,
- "Key_TrebleUp": 16777334,
- "Key_TrebleDown": 16777335,
- "Key_MediaPlay": 16777344,
- "Key_MediaStop": 16777345,
- "Key_MediaPrevious": 16777346,
- "Key_MediaNext": 16777347,
- "Key_MediaRecord": 16777348,
- "Key_MediaPause": 16777349,
- "Key_MediaTogglePlayPause": 16777350,
- "Key_HomePage": 16777360,
- "Key_Favorites": 16777361,
- "Key_Search": 16777362,
- "Key_Standby": 16777363,
- "Key_OpenUrl": 16777364,
- "Key_LaunchMail": 16777376,
- "Key_LaunchMedia": 16777377,
- "Key_Launch0": 16777378,
- "Key_Launch1": 16777379,
- "Key_Launch2": 16777380,
- "Key_Launch3": 16777381,
- "Key_Launch4": 16777382,
- "Key_Launch5": 16777383,
- "Key_Launch6": 16777384,
- "Key_Launch7": 16777385,
- "Key_Launch8": 16777386,
- "Key_Launch9": 16777387,
- "Key_LaunchA": 16777388,
- "Key_LaunchB": 16777389,
- "Key_LaunchC": 16777390,
- "Key_LaunchD": 16777391,
- "Key_LaunchE": 16777392,
- "Key_LaunchF": 16777393,
- "Key_MonBrightnessUp": 16777394,
- "Key_MonBrightnessDown": 16777395,
- "Key_KeyboardLightOnOff": 16777396,
- "Key_KeyboardBrightnessUp": 16777397,
- "Key_KeyboardBrightnessDown": 16777398,
- "Key_PowerOff": 16777399,
- "Key_WakeUp": 16777400,
- "Key_Eject": 16777401,
- "Key_ScreenSaver": 16777402,
- "Key_WWW": 16777403,
- "Key_Memo": 16777404,
- "Key_LightBulb": 16777405,
- "Key_Shop": 16777406,
- "Key_History": 16777407,
- "Key_AddFavorite": 16777408,
- "Key_HotLinks": 16777409,
- "Key_BrightnessAdjust": 16777410,
- "Key_Finance": 16777411,
- "Key_Community": 16777412,
- "Key_AudioRewind": 16777413,
- "Key_BackForward": 16777414,
- "Key_ApplicationLeft": 16777415,
- "Key_ApplicationRight": 16777416,
- "Key_Book": 16777417,
- "Key_CD": 16777418,
- "Key_Calculator": 16777419,
- "Key_ToDoList": 16777420,
- "Key_ClearGrab": 16777421,
- "Key_Close": 16777422,
- "Key_Copy": 16777423,
- "Key_Cut": 16777424,
- "Key_Display": 16777425,
- "Key_DOS": 16777426,
- "Key_Documents": 16777427,
- "Key_Excel": 16777428,
- "Key_Explorer": 16777429,
- "Key_Game": 16777430,
- "Key_Go": 16777431,
- "Key_iTouch": 16777432,
- "Key_LogOff": 16777433,
- "Key_Market": 16777434,
- "Key_Meeting": 16777435,
- "Key_MenuKB": 16777436,
- "Key_MenuPB": 16777437,
- "Key_MySites": 16777438,
- "Key_News": 16777439,
- "Key_OfficeHome": 16777440,
- "Key_Option": 16777441,
- "Key_Paste": 16777442,
- "Key_Phone": 16777443,
- "Key_Calendar": 16777444,
- "Key_Reply": 16777445,
- "Key_Reload": 16777446,
- "Key_RotateWindows": 16777447,
- "Key_RotationPB": 16777448,
- "Key_RotationKB": 16777449,
- "Key_Save": 16777450,
- "Key_Send": 16777451,
- "Key_Spell": 16777452,
- "Key_SplitScreen": 16777453,
- "Key_Support": 16777454,
- "Key_TaskPane": 16777455,
- "Key_Terminal": 16777456,
- "Key_Tools": 16777457,
- "Key_Travel": 16777458,
- "Key_Video": 16777459,
- "Key_Word": 16777460,
- "Key_Xfer": 16777461,
- "Key_ZoomIn": 16777462,
- "Key_ZoomOut": 16777463,
- "Key_Away": 16777464,
- "Key_Messenger": 16777465,
- "Key_WebCam": 16777466,
- "Key_MailForward": 16777467,
- "Key_Pictures": 16777468,
- "Key_Music": 16777469,
- "Key_Battery": 16777470,
- "Key_Bluetooth": 16777471,
- "Key_WLAN": 16777472,
- "Key_UWB": 16777473,
- "Key_AudioForward": 16777474,
- "Key_AudioRepeat": 16777475,
- "Key_AudioRandomPlay": 16777476,
- "Key_Subtitle": 16777477,
- "Key_AudioCycleTrack": 16777478,
- "Key_Time": 16777479,
- "Key_Hibernate": 16777480,
- "Key_View": 16777481,
- "Key_TopMenu": 16777482,
- "Key_PowerDown": 16777483,
- "Key_Suspend": 16777484,
- "Key_ContrastAdjust": 16777485,
- "Key_LaunchG": 16777486,
- "Key_LaunchH": 16777487,
- "Key_TouchpadToggle": 16777488,
- "Key_TouchpadOn": 16777489,
- "Key_TouchpadOff": 16777490,
- "Key_MicMute": 16777491,
- "Key_Red": 16777492,
- "Key_Green": 16777493,
- "Key_Yellow": 16777494,
- "Key_Blue": 16777495,
- "Key_ChannelUp": 16777496,
- "Key_ChannelDown": 16777497,
- "Key_Guide": 16777498,
- "Key_Info": 16777499,
- "Key_Settings": 16777500,
- "Key_MicVolumeUp": 16777501,
- "Key_MicVolumeDown": 16777502,
- "Key_New": 16777504,
- "Key_Open": 16777505,
- "Key_Find": 16777506,
- "Key_Undo": 16777507,
- "Key_Redo": 16777508,
- "Key_MediaLast": 16842751,
- "Key_Select": 16842752,
- "Key_Yes": 16842753,
- "Key_No": 16842754,
- "Key_Cancel": 16908289,
- "Key_Printer": 16908290,
- "Key_Execute": 16908291,
- "Key_Sleep": 16908292,
- "Key_Play": 16908293,
- "Key_Zoom": 16908294,
- "Key_Exit": 16908298,
- "Key_Context1": 17825792,
- "Key_Context2": 17825793,
- "Key_Context3": 17825794,
- "Key_Context4": 17825795,
- "Key_Call": 17825796,
- "Key_Hangup": 17825797,
- "Key_Flip": 17825798,
- "Key_ToggleCallHangup": 17825799,
- "Key_VoiceDial": 17825800,
- "Key_LastNumberRedial": 17825801,
- "Key_Camera": 17825824,
- "Key_CameraFocus": 17825825,
- "Key_unknown": 33554431
- }
- }
- Enum {
- name: "ArrowType"
- values: {
- "NoArrow": 0,
- "UpArrow": 1,
- "DownArrow": 2,
- "LeftArrow": 3,
- "RightArrow": 4
- }
- }
- Enum {
- name: "PenStyle"
- values: {
- "NoPen": 0,
- "SolidLine": 1,
- "DashLine": 2,
- "DotLine": 3,
- "DashDotLine": 4,
- "DashDotDotLine": 5,
- "CustomDashLine": 6
- }
- }
- Enum {
- name: "PenCapStyle"
- values: {
- "FlatCap": 0,
- "SquareCap": 16,
- "RoundCap": 32,
- "MPenCapStyle": 48
- }
- }
- Enum {
- name: "PenJoinStyle"
- values: {
- "MiterJoin": 0,
- "BevelJoin": 64,
- "RoundJoin": 128,
- "SvgMiterJoin": 256,
- "MPenJoinStyle": 448
- }
- }
- Enum {
- name: "BrushStyle"
- values: {
- "NoBrush": 0,
- "SolidPattern": 1,
- "Dense1Pattern": 2,
- "Dense2Pattern": 3,
- "Dense3Pattern": 4,
- "Dense4Pattern": 5,
- "Dense5Pattern": 6,
- "Dense6Pattern": 7,
- "Dense7Pattern": 8,
- "HorPattern": 9,
- "VerPattern": 10,
- "CrossPattern": 11,
- "BDiagPattern": 12,
- "FDiagPattern": 13,
- "DiagCrossPattern": 14,
- "LinearGradientPattern": 15,
- "RadialGradientPattern": 16,
- "ConicalGradientPattern": 17,
- "TexturePattern": 24
- }
- }
- Enum {
- name: "SizeMode"
- values: {
- "AbsoluteSize": 0,
- "RelativeSize": 1
- }
- }
- Enum {
- name: "CursorShape"
- values: {
- "ArrowCursor": 0,
- "UpArrowCursor": 1,
- "CrossCursor": 2,
- "WaitCursor": 3,
- "IBeamCursor": 4,
- "SizeVerCursor": 5,
- "SizeHorCursor": 6,
- "SizeBDiagCursor": 7,
- "SizeFDiagCursor": 8,
- "SizeAllCursor": 9,
- "BlankCursor": 10,
- "SplitVCursor": 11,
- "SplitHCursor": 12,
- "PointingHandCursor": 13,
- "ForbiddenCursor": 14,
- "WhatsThisCursor": 15,
- "BusyCursor": 16,
- "OpenHandCursor": 17,
- "ClosedHandCursor": 18,
- "DragCopyCursor": 19,
- "DragMoveCursor": 20,
- "DragLinkCursor": 21,
- "LastCursor": 21,
- "BitmapCursor": 24,
- "CustomCursor": 25
- }
- }
- Enum {
- name: "TextFormat"
- values: {
- "PlainText": 0,
- "RichText": 1,
- "AutoText": 2
- }
- }
- Enum {
- name: "AspectRatioMode"
- values: {
- "IgnoreAspectRatio": 0,
- "KeepAspectRatio": 1,
- "KeepAspectRatioByExpanding": 2
- }
- }
- Enum {
- name: "DockWidgetArea"
- values: {
- "LeftDockWidgetArea": 1,
- "RightDockWidgetArea": 2,
- "TopDockWidgetArea": 4,
- "BottomDockWidgetArea": 8,
- "DockWidgetArea_Mask": 15,
- "AllDockWidgetAreas": 15,
- "NoDockWidgetArea": 0
- }
- }
- Enum {
- name: "DockWidgetAreas"
- values: {
- "LeftDockWidgetArea": 1,
- "RightDockWidgetArea": 2,
- "TopDockWidgetArea": 4,
- "BottomDockWidgetArea": 8,
- "DockWidgetArea_Mask": 15,
- "AllDockWidgetAreas": 15,
- "NoDockWidgetArea": 0
- }
- }
- Enum {
- name: "ToolBarArea"
- values: {
- "LeftToolBarArea": 1,
- "RightToolBarArea": 2,
- "TopToolBarArea": 4,
- "BottomToolBarArea": 8,
- "ToolBarArea_Mask": 15,
- "AllToolBarAreas": 15,
- "NoToolBarArea": 0
- }
- }
- Enum {
- name: "ToolBarAreas"
- values: {
- "LeftToolBarArea": 1,
- "RightToolBarArea": 2,
- "TopToolBarArea": 4,
- "BottomToolBarArea": 8,
- "ToolBarArea_Mask": 15,
- "AllToolBarAreas": 15,
- "NoToolBarArea": 0
- }
- }
- Enum {
- name: "DateFormat"
- values: {
- "TextDate": 0,
- "ISODate": 1,
- "SystemLocaleDate": 2,
- "LocalDate": 2,
- "LocaleDate": 3,
- "SystemLocaleShortDate": 4,
- "SystemLocaleLongDate": 5,
- "DefaultLocaleShortDate": 6,
- "DefaultLocaleLongDate": 7,
- "RFC2822Date": 8
- }
- }
- Enum {
- name: "TimeSpec"
- values: {
- "LocalTime": 0,
- "UTC": 1,
- "OffsetFromUTC": 2,
- "TimeZone": 3
- }
- }
- Enum {
- name: "DayOfWeek"
- values: {
- "Monday": 1,
- "Tuesday": 2,
- "Wednesday": 3,
- "Thursday": 4,
- "Friday": 5,
- "Saturday": 6,
- "Sunday": 7
- }
- }
- Enum {
- name: "ScrollBarPolicy"
- values: {
- "ScrollBarAsNeeded": 0,
- "ScrollBarAlwaysOff": 1,
- "ScrollBarAlwaysOn": 2
- }
- }
- Enum {
- name: "CaseSensitivity"
- values: {
- "CaseInsensitive": 0,
- "CaseSensitive": 1
- }
- }
- Enum {
- name: "Corner"
- values: {
- "TopLeftCorner": 0,
- "TopRightCorner": 1,
- "BottomLeftCorner": 2,
- "BottomRightCorner": 3
- }
- }
- Enum {
- name: "Edge"
- values: {
- "TopEdge": 1,
- "LeftEdge": 2,
- "RightEdge": 4,
- "BottomEdge": 8
- }
- }
- Enum {
- name: "Edges"
- values: {
- "TopEdge": 1,
- "LeftEdge": 2,
- "RightEdge": 4,
- "BottomEdge": 8
- }
- }
- Enum {
- name: "ConnectionType"
- values: {
- "AutoConnection": 0,
- "DirectConnection": 1,
- "QueuedConnection": 2,
- "BlockingQueuedConnection": 3,
- "UniqueConnection": 128
- }
- }
- Enum {
- name: "ShortcutContext"
- values: {
- "WidgetShortcut": 0,
- "WindowShortcut": 1,
- "ApplicationShortcut": 2,
- "WidgetWithChildrenShortcut": 3
- }
- }
- Enum {
- name: "FillRule"
- values: {
- "OddEvenFill": 0,
- "WindingFill": 1
- }
- }
- Enum {
- name: "MaskMode"
- values: {
- "MaskInColor": 0,
- "MaskOutColor": 1
- }
- }
- Enum {
- name: "ClipOperation"
- values: {
- "NoClip": 0,
- "ReplaceClip": 1,
- "IntersectClip": 2
- }
- }
- Enum {
- name: "ItemSelectionMode"
- values: {
- "ContainsItemShape": 0,
- "IntersectsItemShape": 1,
- "ContainsItemBoundingRect": 2,
- "IntersectsItemBoundingRect": 3
- }
- }
- Enum {
- name: "TransformationMode"
- values: {
- "FastTransformation": 0,
- "SmoothTransformation": 1
- }
- }
- Enum {
- name: "Axis"
- values: {
- "XAxis": 0,
- "YAxis": 1,
- "ZAxis": 2
- }
- }
- Enum {
- name: "FocusReason"
- values: {
- "MouseFocusReason": 0,
- "TabFocusReason": 1,
- "BacktabFocusReason": 2,
- "ActiveWindowFocusReason": 3,
- "PopupFocusReason": 4,
- "ShortcutFocusReason": 5,
- "MenuBarFocusReason": 6,
- "OtherFocusReason": 7,
- "NoFocusReason": 8
- }
- }
- Enum {
- name: "ContextMenuPolicy"
- values: {
- "NoContextMenu": 0,
- "DefaultContextMenu": 1,
- "ActionsContextMenu": 2,
- "CustomContextMenu": 3,
- "PreventContextMenu": 4
- }
- }
- Enum {
- name: "InputMethodQuery"
- values: {
- "ImEnabled": 1,
- "ImCursorRectangle": 2,
- "ImMicroFocus": 2,
- "ImFont": 4,
- "ImCursorPosition": 8,
- "ImSurroundingText": 16,
- "ImCurrentSelection": 32,
- "ImMaximumTextLength": 64,
- "ImAnchorPosition": 128,
- "ImHints": 256,
- "ImPreferredLanguage": 512,
- "ImAbsolutePosition": 1024,
- "ImTextBeforeCursor": 2048,
- "ImTextAfterCursor": 4096,
- "ImPlatformData": -2147483648,
- "ImQueryInput": 186,
- "ImQueryAll": -1
- }
- }
- Enum {
- name: "InputMethodQueries"
- values: {
- "ImEnabled": 1,
- "ImCursorRectangle": 2,
- "ImMicroFocus": 2,
- "ImFont": 4,
- "ImCursorPosition": 8,
- "ImSurroundingText": 16,
- "ImCurrentSelection": 32,
- "ImMaximumTextLength": 64,
- "ImAnchorPosition": 128,
- "ImHints": 256,
- "ImPreferredLanguage": 512,
- "ImAbsolutePosition": 1024,
- "ImTextBeforeCursor": 2048,
- "ImTextAfterCursor": 4096,
- "ImPlatformData": -2147483648,
- "ImQueryInput": 186,
- "ImQueryAll": -1
- }
- }
- Enum {
- name: "InputMethodHint"
- values: {
- "ImhNone": 0,
- "ImhHiddenText": 1,
- "ImhSensitiveData": 2,
- "ImhNoAutoUppercase": 4,
- "ImhPreferNumbers": 8,
- "ImhPreferUppercase": 16,
- "ImhPreferLowercase": 32,
- "ImhNoPredictiveText": 64,
- "ImhDate": 128,
- "ImhTime": 256,
- "ImhPreferLatin": 512,
- "ImhMultiLine": 1024,
- "ImhDigitsOnly": 65536,
- "ImhFormattedNumbersOnly": 131072,
- "ImhUppercaseOnly": 262144,
- "ImhLowercaseOnly": 524288,
- "ImhDialableCharactersOnly": 1048576,
- "ImhEmailCharactersOnly": 2097152,
- "ImhUrlCharactersOnly": 4194304,
- "ImhLatinOnly": 8388608,
- "ImhExclusiveInputMask": -65536
- }
- }
- Enum {
- name: "InputMethodHints"
- values: {
- "ImhNone": 0,
- "ImhHiddenText": 1,
- "ImhSensitiveData": 2,
- "ImhNoAutoUppercase": 4,
- "ImhPreferNumbers": 8,
- "ImhPreferUppercase": 16,
- "ImhPreferLowercase": 32,
- "ImhNoPredictiveText": 64,
- "ImhDate": 128,
- "ImhTime": 256,
- "ImhPreferLatin": 512,
- "ImhMultiLine": 1024,
- "ImhDigitsOnly": 65536,
- "ImhFormattedNumbersOnly": 131072,
- "ImhUppercaseOnly": 262144,
- "ImhLowercaseOnly": 524288,
- "ImhDialableCharactersOnly": 1048576,
- "ImhEmailCharactersOnly": 2097152,
- "ImhUrlCharactersOnly": 4194304,
- "ImhLatinOnly": 8388608,
- "ImhExclusiveInputMask": -65536
- }
- }
- Enum {
- name: "ToolButtonStyle"
- values: {
- "ToolButtonIconOnly": 0,
- "ToolButtonTextOnly": 1,
- "ToolButtonTextBesideIcon": 2,
- "ToolButtonTextUnderIcon": 3,
- "ToolButtonFollowStyle": 4
- }
- }
- Enum {
- name: "LayoutDirection"
- values: {
- "LeftToRight": 0,
- "RightToLeft": 1,
- "LayoutDirectionAuto": 2
- }
- }
- Enum {
- name: "DropAction"
- values: {
- "CopyAction": 1,
- "MoveAction": 2,
- "LinkAction": 4,
- "ActionMask": 255,
- "TargetMoveAction": 32770,
- "IgnoreAction": 0
- }
- }
- Enum {
- name: "DropActions"
- values: {
- "CopyAction": 1,
- "MoveAction": 2,
- "LinkAction": 4,
- "ActionMask": 255,
- "TargetMoveAction": 32770,
- "IgnoreAction": 0
- }
- }
- Enum {
- name: "CheckState"
- values: {
- "Unchecked": 0,
- "PartiallyChecked": 1,
- "Checked": 2
- }
- }
- Enum {
- name: "ItemFlags"
- values: {
- "NoItemFlags": 0,
- "ItemIsSelectable": 1,
- "ItemIsEditable": 2,
- "ItemIsDragEnabled": 4,
- "ItemIsDropEnabled": 8,
- "ItemIsUserCheckable": 16,
- "ItemIsEnabled": 32,
- "ItemIsTristate": 64,
- "ItemNeverHasChildren": 128
- }
- }
- Enum {
- name: "MatchFlags"
- values: {
- "MatchExactly": 0,
- "MatchContains": 1,
- "MatchStartsWith": 2,
- "MatchEndsWith": 3,
- "MatchRegExp": 4,
- "MatchWildcard": 5,
- "MatchFixedString": 8,
- "MatchCaseSensitive": 16,
- "MatchWrap": 32,
- "MatchRecursive": 64
- }
- }
- Enum {
- name: "WindowModality"
- values: {
- "NonModal": 0,
- "WindowModal": 1,
- "ApplicationModal": 2
- }
- }
- Enum {
- name: "TextInteractionFlag"
- values: {
- "NoTextInteraction": 0,
- "TextSelectableByMouse": 1,
- "TextSelectableByKeyboard": 2,
- "LinksAccessibleByMouse": 4,
- "LinksAccessibleByKeyboard": 8,
- "TextEditable": 16,
- "TextEditorInteraction": 19,
- "TextBrowserInteraction": 13
- }
- }
- Enum {
- name: "TextInteractionFlags"
- values: {
- "NoTextInteraction": 0,
- "TextSelectableByMouse": 1,
- "TextSelectableByKeyboard": 2,
- "LinksAccessibleByMouse": 4,
- "LinksAccessibleByKeyboard": 8,
- "TextEditable": 16,
- "TextEditorInteraction": 19,
- "TextBrowserInteraction": 13
- }
- }
- Enum {
- name: "SizeHint"
- values: {
- "MinimumSize": 0,
- "PreferredSize": 1,
- "MaximumSize": 2,
- "MinimumDescent": 3,
- "NSizeHints": 4
- }
- }
- Enum {
- name: "GestureState"
- values: {
- "NoGesture": 0,
- "GestureStarted": 1,
- "GestureUpdated": 2,
- "GestureFinished": 3,
- "GestureCanceled": 4
- }
- }
- Enum {
- name: "GestureType"
- values: {
- "TapGesture": 1,
- "TapAndHoldGesture": 2,
- "PanGesture": 3,
- "PinchGesture": 4,
- "SwipeGesture": 5,
- "CustomGesture": 256,
- "LastGestureType": -1
- }
- }
- Enum {
- name: "NativeGestureType"
- values: {
- "BeginNativeGesture": 0,
- "EndNativeGesture": 1,
- "PanNativeGesture": 2,
- "ZoomNativeGesture": 3,
- "SmartZoomNativeGesture": 4,
- "RotateNativeGesture": 5,
- "SwipeNativeGesture": 6
- }
- }
- Enum {
- name: "CursorMoveStyle"
- values: {
- "LogicalMoveStyle": 0,
- "VisualMoveStyle": 1
- }
- }
- Enum {
- name: "TimerType"
- values: {
- "PreciseTimer": 0,
- "CoarseTimer": 1,
- "VeryCoarseTimer": 2
- }
- }
- Enum {
- name: "ScrollPhase"
- values: {
- "ScrollBegin": 1,
- "ScrollUpdate": 2,
- "ScrollEnd": 3
- }
- }
- Enum {
- name: "MouseEventSource"
- values: {
- "MouseEventNotSynthesized": 0,
- "MouseEventSynthesizedBySystem": 1,
- "MouseEventSynthesizedByQt": 2
- }
- }
- }
- Component { name: "QEasingCurve"; prototype: "QQmlEasingValueType" }
}
diff --git a/src/imports/qtquick2/qtquick2.pro b/src/imports/qtquick2/qtquick2.pro
index 2cd15c7340..118343588a 100644
--- a/src/imports/qtquick2/qtquick2.pro
+++ b/src/imports/qtquick2/qtquick2.pro
@@ -1,6 +1,7 @@
CXX_MODULE = qml
TARGET = qtquick2plugin
TARGETPATH = QtQuick.2
+IMPORT_VERSION = 2.6
SOURCES += \
plugin.cpp
diff --git a/src/imports/settings/plugins.qmltypes b/src/imports/settings/plugins.qmltypes
index 87503fbda5..eaa310edc9 100644
--- a/src/imports/settings/plugins.qmltypes
+++ b/src/imports/settings/plugins.qmltypes
@@ -1,4 +1,4 @@
-import QtQuick.tooling 1.1
+import QtQuick.tooling 1.2
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
@@ -7,6 +7,7 @@ import QtQuick.tooling 1.1
// 'qmlplugindump -nonrelocatable Qt.labs.settings 1.0'
Module {
+ dependencies: []
Component {
name: "QQmlSettings"
prototype: "QObject"
diff --git a/src/imports/settings/qqmlsettings_p.h b/src/imports/settings/qqmlsettings_p.h
index a1207eb81c..d3eeaafb62 100644
--- a/src/imports/settings/qqmlsettings_p.h
+++ b/src/imports/settings/qqmlsettings_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLSETTINGS_P_H
#define QQMLSETTINGS_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQml/qqml.h>
#include <QtCore/qobject.h>
#include <QtCore/qscopedpointer.h>
diff --git a/src/imports/statemachine/plugins.qmltypes b/src/imports/statemachine/plugins.qmltypes
index db5897bb0f..c4b453b9e4 100644
--- a/src/imports/statemachine/plugins.qmltypes
+++ b/src/imports/statemachine/plugins.qmltypes
@@ -1,4 +1,4 @@
-import QtQuick.tooling 1.1
+import QtQuick.tooling 1.2
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
@@ -7,6 +7,7 @@ import QtQuick.tooling 1.1
// 'qmlplugindump -nonrelocatable QtQml.StateMachine 1.0'
Module {
+ dependencies: []
Component {
name: "FinalState"
defaultProperty: "children"
@@ -32,9 +33,17 @@ Module {
Component {
name: "QAbstractTransition"
prototype: "QObject"
+ Enum {
+ name: "TransitionType"
+ values: {
+ "ExternalTransition": 0,
+ "InternalTransition": 1
+ }
+ }
Property { name: "sourceState"; type: "QState"; isReadonly: true; isPointer: true }
Property { name: "targetState"; type: "QAbstractState"; isPointer: true }
Property { name: "targetStates"; type: "QList<QAbstractState*>" }
+ Property { name: "transitionType"; revision: 1; type: "TransitionType" }
Signal { name: "triggered" }
}
Component { name: "QFinalState"; prototype: "QAbstractState" }
@@ -51,6 +60,7 @@ Module {
}
}
Property { name: "defaultState"; type: "QAbstractState"; isPointer: true }
+ Property { name: "defaultTransition"; type: "QAbstractTransition"; isPointer: true }
Property { name: "historyType"; type: "HistoryType" }
}
Component {
diff --git a/src/imports/testlib/TestCase.qml b/src/imports/testlib/TestCase.qml
index 039ee63f07..8bedad40e9 100644
--- a/src/imports/testlib/TestCase.qml
+++ b/src/imports/testlib/TestCase.qml
@@ -613,12 +613,19 @@ Item {
\li blue(x, y) Returns the blue channel value of the pixel at \a x, \a y position
\li alpha(x, y) Returns the alpha channel value of the pixel at \a x, \a y position
\li pixel(x, y) Returns the color value of the pixel at \a x, \a y position
+ \li equals(image) Returns \c true if this image is identical to \a image -
+ see \l QImage::operator== (since 5.6)
+
For example:
\code
var image = grabImage(rect);
compare(image.red(10, 10), 255);
compare(image.pixel(20, 20), Qt.rgba(255, 0, 0, 255));
+
+ rect.width += 10;
+ var newImage = grabImage(rect);
+ verify(!newImage.equals(image));
\endcode
\endlist
@@ -869,6 +876,9 @@ Item {
focused item. If \a delay is larger than 0, the test will wait for
\a delay milliseconds.
+ The event will be sent to the TestCase window or, in case of multiple windows,
+ to the current active window. See \l QGuiApplication::focusWindow() for more details.
+
\b{Note:} At some point you should release the key using keyRelease().
\sa keyRelease(), keyClick()
@@ -894,6 +904,9 @@ Item {
focused item. If \a delay is larger than 0, the test will wait for
\a delay milliseconds.
+ The event will be sent to the TestCase window or, in case of multiple windows,
+ to the current active window. See \l QGuiApplication::focusWindow() for more details.
+
\sa keyPress(), keyClick()
*/
function keyRelease(key, modifiers, delay) {
@@ -917,6 +930,9 @@ Item {
focused item. If \a delay is larger than 0, the test will wait for
\a delay milliseconds.
+ The event will be sent to the TestCase window or, in case of multiple windows,
+ to the current active window. See \l QGuiApplication::focusWindow() for more details.
+
\sa keyPress(), keyRelease()
*/
function keyClick(key, modifiers, delay) {
diff --git a/src/imports/testlib/plugins.qmltypes b/src/imports/testlib/plugins.qmltypes
index a892f73eb0..2beb38a940 100644
--- a/src/imports/testlib/plugins.qmltypes
+++ b/src/imports/testlib/plugins.qmltypes
@@ -1,16 +1,17 @@
-import QtQuick.tooling 1.1
+import QtQuick.tooling 1.2
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump QtTest 1.1'
+// 'qmlplugindump -nonrelocatable QtTest 1.0'
Module {
+ dependencies: []
Component {
name: "QuickTestEvent"
prototype: "QObject"
- exports: ["TestEvent 1.0"]
+ exports: ["QtTest/TestEvent 1.0"]
exportMetaObjectRevisions: [0]
Method {
name: "keyPress"
@@ -95,6 +96,16 @@ Module {
Parameter { name: "delay"; type: "int" }
}
Method {
+ name: "mouseDoubleClickSequence"
+ type: "bool"
+ Parameter { name: "item"; type: "QObject"; isPointer: true }
+ Parameter { name: "x"; type: "double" }
+ Parameter { name: "y"; type: "double" }
+ Parameter { name: "button"; type: "int" }
+ Parameter { name: "modifiers"; type: "int" }
+ Parameter { name: "delay"; type: "int" }
+ }
+ Method {
name: "mouseMove"
type: "bool"
Parameter { name: "item"; type: "QObject"; isPointer: true }
@@ -119,7 +130,7 @@ Module {
Component {
name: "QuickTestResult"
prototype: "QObject"
- exports: ["TestResult 1.0", "TestResult 1.1"]
+ exports: ["QtTest/TestResult 1.0", "QtTest/TestResult 1.1"]
exportMetaObjectRevisions: [0, 1]
Enum {
name: "RunMode"
@@ -261,7 +272,7 @@ Module {
Component {
name: "QuickTestUtil"
prototype: "QObject"
- exports: ["TestUtil 1.0"]
+ exports: ["QtTest/TestUtil 1.0"]
exportMetaObjectRevisions: [0]
Property { name: "printAvailableFunctions"; type: "bool"; isReadonly: true }
Property { name: "dragThreshold"; type: "int"; isReadonly: true }
diff --git a/src/imports/window/plugins.qmltypes b/src/imports/window/plugins.qmltypes
index fa320886db..8c21271614 100644
--- a/src/imports/window/plugins.qmltypes
+++ b/src/imports/window/plugins.qmltypes
@@ -1,4 +1,4 @@
-import QtQuick.tooling 1.1
+import QtQuick.tooling 1.2
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
@@ -7,19 +7,7 @@ import QtQuick.tooling 1.1
// 'qmlplugindump -nonrelocatable QtQuick.Window 2.2'
Module {
- Component {
- name: "QQuickRootItem"
- defaultProperty: "data"
- prototype: "QQuickItem"
- Method {
- name: "setWidth"
- Parameter { name: "w"; type: "int" }
- }
- Method {
- name: "setHeight"
- Parameter { name: "h"; type: "int" }
- }
- }
+ dependencies: []
Component {
name: "QQuickScreen"
prototype: "QObject"
@@ -112,6 +100,8 @@ Module {
Property { name: "active"; type: "bool"; isReadonly: true }
Property { name: "activeFocusItem"; type: "QQuickItem"; isReadonly: true; isPointer: true }
Property { name: "contentItem"; type: "QQuickItem"; isReadonly: true; isPointer: true }
+ Property { name: "width"; type: "int"; isReadonly: true }
+ Property { name: "height"; type: "int"; isReadonly: true }
}
Component {
name: "QQuickWindowQmlImpl"
@@ -288,5 +278,6 @@ Module {
revision: 1
Parameter { name: "msec"; type: "int" }
}
+ Method { name: "requestUpdate"; revision: 3 }
}
}
diff --git a/src/imports/xmllistmodel/plugins.qmltypes b/src/imports/xmllistmodel/plugins.qmltypes
index 0978237027..d098d11409 100644
--- a/src/imports/xmllistmodel/plugins.qmltypes
+++ b/src/imports/xmllistmodel/plugins.qmltypes
@@ -1,4 +1,4 @@
-import QtQuick.tooling 1.1
+import QtQuick.tooling 1.2
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
@@ -7,6 +7,272 @@ import QtQuick.tooling 1.1
// 'qmlplugindump -nonrelocatable QtQuick.XmlListModel 2.0'
Module {
+ dependencies: []
+ Component {
+ name: "QAbstractItemModel"
+ prototype: "QObject"
+ Enum {
+ name: "LayoutChangeHint"
+ values: {
+ "NoLayoutChangeHint": 0,
+ "VerticalSortHint": 1,
+ "HorizontalSortHint": 2
+ }
+ }
+ Signal {
+ name: "dataChanged"
+ Parameter { name: "topLeft"; type: "QModelIndex" }
+ Parameter { name: "bottomRight"; type: "QModelIndex" }
+ Parameter { name: "roles"; type: "QVector<int>" }
+ }
+ Signal {
+ name: "dataChanged"
+ Parameter { name: "topLeft"; type: "QModelIndex" }
+ Parameter { name: "bottomRight"; type: "QModelIndex" }
+ }
+ Signal {
+ name: "headerDataChanged"
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "layoutChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ Parameter { name: "hint"; type: "QAbstractItemModel::LayoutChangeHint" }
+ }
+ Signal {
+ name: "layoutChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ }
+ Signal { name: "layoutChanged" }
+ Signal {
+ name: "layoutAboutToBeChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ Parameter { name: "hint"; type: "QAbstractItemModel::LayoutChangeHint" }
+ }
+ Signal {
+ name: "layoutAboutToBeChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ }
+ Signal { name: "layoutAboutToBeChanged" }
+ Signal {
+ name: "rowsAboutToBeInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsAboutToBeRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal { name: "modelAboutToBeReset" }
+ Signal { name: "modelReset" }
+ Signal {
+ name: "rowsAboutToBeMoved"
+ Parameter { name: "sourceParent"; type: "QModelIndex" }
+ Parameter { name: "sourceStart"; type: "int" }
+ Parameter { name: "sourceEnd"; type: "int" }
+ Parameter { name: "destinationParent"; type: "QModelIndex" }
+ Parameter { name: "destinationRow"; type: "int" }
+ }
+ Signal {
+ name: "rowsMoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "start"; type: "int" }
+ Parameter { name: "end"; type: "int" }
+ Parameter { name: "destination"; type: "QModelIndex" }
+ Parameter { name: "row"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeMoved"
+ Parameter { name: "sourceParent"; type: "QModelIndex" }
+ Parameter { name: "sourceStart"; type: "int" }
+ Parameter { name: "sourceEnd"; type: "int" }
+ Parameter { name: "destinationParent"; type: "QModelIndex" }
+ Parameter { name: "destinationColumn"; type: "int" }
+ }
+ Signal {
+ name: "columnsMoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "start"; type: "int" }
+ Parameter { name: "end"; type: "int" }
+ Parameter { name: "destination"; type: "QModelIndex" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method { name: "submit"; type: "bool" }
+ Method { name: "revert" }
+ Method {
+ name: "hasIndex"
+ type: "bool"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "hasIndex"
+ type: "bool"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method {
+ name: "index"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "index"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method {
+ name: "parent"
+ type: "QModelIndex"
+ Parameter { name: "child"; type: "QModelIndex" }
+ }
+ Method {
+ name: "sibling"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "idx"; type: "QModelIndex" }
+ }
+ Method {
+ name: "rowCount"
+ type: "int"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "rowCount"; type: "int" }
+ Method {
+ name: "columnCount"
+ type: "int"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "columnCount"; type: "int" }
+ Method {
+ name: "hasChildren"
+ type: "bool"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "hasChildren"; type: "bool" }
+ Method {
+ name: "data"
+ type: "QVariant"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "data"
+ type: "QVariant"
+ Parameter { name: "index"; type: "QModelIndex" }
+ }
+ Method {
+ name: "setData"
+ type: "bool"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "setData"
+ type: "bool"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "value"; type: "QVariant" }
+ }
+ Method {
+ name: "headerData"
+ type: "QVariant"
+ Parameter { name: "section"; type: "int" }
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "headerData"
+ type: "QVariant"
+ Parameter { name: "section"; type: "int" }
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ }
+ Method {
+ name: "fetchMore"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "canFetchMore"
+ type: "bool"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "flags"
+ type: "Qt::ItemFlags"
+ Parameter { name: "index"; type: "QModelIndex" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "hits"; type: "int" }
+ Parameter { name: "flags"; type: "Qt::MatchFlags" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "hits"; type: "int" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ }
+ }
+ Component { name: "QAbstractListModel"; prototype: "QAbstractItemModel" }
Component {
name: "QQuickXmlListModel"
defaultProperty: "roles"
diff --git a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
index b078edcbc6..50aa061213 100644
--- a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
+++ b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
@@ -36,7 +36,7 @@
#include <qqmlcontext.h>
#include <private/qqmlengine_p.h>
#include <private/qv8engine_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4engine_p.h>
#include <private/qv4object_p.h>
@@ -416,7 +416,7 @@ void QQuickXmlQueryEngine::getValuesOfKeyRoles(const XmlQueryJob& currentJob, QS
if (keysQueries.count() == 1)
keysQuery = currentJob.prefix + keysQueries[0];
else if (keysQueries.count() > 1)
- keysQuery = currentJob.prefix + QLatin1String("concat(") + keysQueries.join(QLatin1String(",")) + QLatin1String(")");
+ keysQuery = currentJob.prefix + QLatin1String("concat(") + keysQueries.join(QLatin1Char(',')) + QLatin1Char(')');
if (!keysQuery.isEmpty()) {
query->setQuery(keysQuery);
diff --git a/src/imports/xmllistmodel/qqmlxmllistmodel_p.h b/src/imports/xmllistmodel/qqmlxmllistmodel_p.h
index 5b54d0aff6..ebb5f43975 100644
--- a/src/imports/xmllistmodel/qqmlxmllistmodel_p.h
+++ b/src/imports/xmllistmodel/qqmlxmllistmodel_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKXMLLISTMODEL_H
#define QQUICKXMLLISTMODEL_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include <qqmlinfo.h>
diff --git a/src/particles/qquickage_p.h b/src/particles/qquickage_p.h
index cf7d1d80cb..733385cb6f 100644
--- a/src/particles/qquickage_p.h
+++ b/src/particles/qquickage_p.h
@@ -33,6 +33,17 @@
#ifndef KILLAFFECTOR_H
#define KILLAFFECTOR_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickparticleaffector_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/particles/qquickangledirection_p.h b/src/particles/qquickangledirection_p.h
index eaae53ef0a..837afe83df 100644
--- a/src/particles/qquickangledirection_p.h
+++ b/src/particles/qquickangledirection_p.h
@@ -33,6 +33,17 @@
#ifndef QQuickANGLEDDIRECTION_H
#define QQuickANGLEDDIRECTION_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickdirection_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/particles/qquickcumulativedirection_p.h b/src/particles/qquickcumulativedirection_p.h
index d9e19542cf..9756c92d05 100644
--- a/src/particles/qquickcumulativedirection_p.h
+++ b/src/particles/qquickcumulativedirection_p.h
@@ -33,6 +33,17 @@
#ifndef QQuickCUMULATIVEDIRECTION_P_H
#define QQuickCUMULATIVEDIRECTION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickdirection_p.h"
#include <QQmlListProperty>
QT_BEGIN_NAMESPACE
diff --git a/src/particles/qquickcustomaffector_p.h b/src/particles/qquickcustomaffector_p.h
index 931db97edf..a3388cc3e9 100644
--- a/src/particles/qquickcustomaffector_p.h
+++ b/src/particles/qquickcustomaffector_p.h
@@ -34,6 +34,17 @@
#ifndef CUSTOMAFFECTOR_H
#define CUSTOMAFFECTOR_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QObject>
#include "qquickparticlesystem_p.h"
#include "qquickparticleextruder_p.h"
diff --git a/src/particles/qquickcustomparticle.cpp b/src/particles/qquickcustomparticle.cpp
index 32cde7c126..5e244ba02c 100644
--- a/src/particles/qquickcustomparticle.cpp
+++ b/src/particles/qquickcustomparticle.cpp
@@ -370,10 +370,10 @@ QQuickShaderEffectNode* QQuickCustomParticle::buildCustomNodes()
}
}
- NodeHashConstIt it = m_nodes.begin();
+ NodeHashConstIt it = m_nodes.cbegin();
rootNode = it.value();
rootNode->setFlag(QSGNode::OwnsMaterial, true);
- const NodeHashConstIt cend = m_nodes.end();
+ NodeHashConstIt cend = m_nodes.cend();
for (++it; it != cend; ++it)
rootNode->appendChildNode(it.value());
diff --git a/src/particles/qquickcustomparticle_p.h b/src/particles/qquickcustomparticle_p.h
index 85e609a499..0e650534fb 100644
--- a/src/particles/qquickcustomparticle_p.h
+++ b/src/particles/qquickcustomparticle_p.h
@@ -33,6 +33,17 @@
#ifndef CUSTOM_PARTICLE_H
#define CUSTOM_PARTICLE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickparticlepainter_p.h"
#include <private/qquickshadereffectnode_p.h>
#include <private/qquickshadereffect_p.h>
diff --git a/src/particles/qquickdirection_p.h b/src/particles/qquickdirection_p.h
index 9dacb6db0e..68b189fd1a 100644
--- a/src/particles/qquickdirection_p.h
+++ b/src/particles/qquickdirection_p.h
@@ -34,6 +34,17 @@
#ifndef VARYINGVECTOR_H
#define VARYINGVECTOR_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QObject>
#include <QPointF>
diff --git a/src/particles/qquickellipseextruder_p.h b/src/particles/qquickellipseextruder_p.h
index bb766ac8de..b6606daa86 100644
--- a/src/particles/qquickellipseextruder_p.h
+++ b/src/particles/qquickellipseextruder_p.h
@@ -33,6 +33,17 @@
#ifndef ELLIPSEEXTRUDER_H
#define ELLIPSEEXTRUDER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickparticleextruder_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/particles/qquickfriction_p.h b/src/particles/qquickfriction_p.h
index 9f09e8ff97..b9b34e965c 100644
--- a/src/particles/qquickfriction_p.h
+++ b/src/particles/qquickfriction_p.h
@@ -33,6 +33,17 @@
#ifndef FRICTIONAFFECTOR_H
#define FRICTIONAFFECTOR_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickparticleaffector_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/particles/qquickgravity_p.h b/src/particles/qquickgravity_p.h
index b20de84607..03fa6f23fb 100644
--- a/src/particles/qquickgravity_p.h
+++ b/src/particles/qquickgravity_p.h
@@ -33,6 +33,17 @@
#ifndef GRAVITYAFFECTOR_H
#define GRAVITYAFFECTOR_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickparticleaffector_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/particles/qquickgroupgoal_p.h b/src/particles/qquickgroupgoal_p.h
index fe5d653ecc..3a61875411 100644
--- a/src/particles/qquickgroupgoal_p.h
+++ b/src/particles/qquickgroupgoal_p.h
@@ -33,6 +33,17 @@
#ifndef GROUPGOALAFFECTOR_H
#define GROUPGOALAFFECTOR_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickparticleaffector_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp
index 7df3299325..d78a350306 100644
--- a/src/particles/qquickimageparticle.cpp
+++ b/src/particles/qquickimageparticle.cpp
@@ -1156,7 +1156,9 @@ QQuickParticleData* QQuickImageParticle::getShadowDatum(QQuickParticleData* datu
QQuickParticleGroupData* gd = m_system->groupData[datum->group];
if (!m_shadowData.contains(datum->group)) {
QVector<QQuickParticleData*> data;
- for (int i=0; i<gd->size(); i++){
+ const int gdSize = gd->size();
+ data.reserve(gdSize);
+ for (int i = 0; i < gdSize; i++) {
QQuickParticleData* datum = new QQuickParticleData(m_system);
*datum = *(gd->data[i]);
data << datum;
diff --git a/src/particles/qquickimageparticle_p.h b/src/particles/qquickimageparticle_p.h
index 7d7d98dab6..a39253b28c 100644
--- a/src/particles/qquickimageparticle_p.h
+++ b/src/particles/qquickimageparticle_p.h
@@ -33,6 +33,17 @@
#ifndef ULTRAPARTICLE_H
#define ULTRAPARTICLE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickparticlepainter_p.h"
#include "qquickdirection_p.h"
#include <private/qquickpixmapcache_p.h>
@@ -175,13 +186,12 @@ class QQuickImageParticle : public QQuickParticlePainter
Q_PROPERTY(bool spritesInterpolate READ spritesInterpolate WRITE setSpritesInterpolate NOTIFY spritesInterpolateChanged)
Q_PROPERTY(EntryEffect entryEffect READ entryEffect WRITE setEntryEffect NOTIFY entryEffectChanged)
- Q_ENUMS(EntryEffect)
- Q_ENUMS(Status)
public:
explicit QQuickImageParticle(QQuickItem *parent = 0);
virtual ~QQuickImageParticle();
enum Status { Null, Ready, Loading, Error };
+ Q_ENUM(Status)
QQmlListProperty<QQuickSprite> sprites();
QQuickStochasticEngine* spriteEngine() {return m_spriteEngine;}
@@ -191,6 +201,7 @@ public:
Fade = 1,
Scale = 2
};
+ Q_ENUM(EntryEffect)
enum PerformanceLevel{//TODO: Expose?
Unknown = 0,
diff --git a/src/particles/qquickitemparticle_p.h b/src/particles/qquickitemparticle_p.h
index 4f804a232a..92a9f23b79 100644
--- a/src/particles/qquickitemparticle_p.h
+++ b/src/particles/qquickitemparticle_p.h
@@ -33,6 +33,17 @@
#ifndef ITEMPARTICLE_H
#define ITEMPARTICLE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickparticlepainter_p.h"
#include <QPointer>
#include <QSet>
diff --git a/src/particles/qquicklineextruder_p.h b/src/particles/qquicklineextruder_p.h
index 77896e86e0..1e9db2ce52 100644
--- a/src/particles/qquicklineextruder_p.h
+++ b/src/particles/qquicklineextruder_p.h
@@ -33,6 +33,17 @@
#ifndef LINEEXTRUDER_H
#define LINEEXTRUDER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickparticleextruder_p.h"
class QQuickLineExtruder : public QQuickParticleExtruder
diff --git a/src/particles/qquickmaskextruder_p.h b/src/particles/qquickmaskextruder_p.h
index 9fc84dd5aa..5f7fb1ea86 100644
--- a/src/particles/qquickmaskextruder_p.h
+++ b/src/particles/qquickmaskextruder_p.h
@@ -33,6 +33,17 @@
#ifndef MASKEXTRUDER_H
#define MASKEXTRUDER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickparticleextruder_p.h"
#include <private/qquickpixmapcache_p.h>
#include <QUrl>
diff --git a/src/particles/qquickparticleaffector_p.h b/src/particles/qquickparticleaffector_p.h
index 8dfc98dde7..4646c839d9 100644
--- a/src/particles/qquickparticleaffector_p.h
+++ b/src/particles/qquickparticleaffector_p.h
@@ -34,6 +34,17 @@
#ifndef PARTICLEAFFECTOR_H
#define PARTICLEAFFECTOR_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QObject>
#include "qquickparticlesystem_p.h"
#include "qquickparticleextruder_p.h"
diff --git a/src/particles/qquickparticleemitter_p.h b/src/particles/qquickparticleemitter_p.h
index 65e2a34aa7..c938cedccc 100644
--- a/src/particles/qquickparticleemitter_p.h
+++ b/src/particles/qquickparticleemitter_p.h
@@ -34,6 +34,17 @@
#ifndef PARTICLEEMITTER_H
#define PARTICLEEMITTER_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuick/QQuickItem>
#include <QDebug>
#include "qquickparticlesystem_p.h"
@@ -67,7 +78,6 @@ class QQuickParticleEmitter : public QQuickItem
Q_PROPERTY(QQuickDirection *acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged)
Q_PROPERTY(qreal velocityFromMovement READ velocityFromMovement WRITE setVelocityFromMovement NOTIFY velocityFromMovementChanged)
- Q_ENUMS(Lifetime)
public:
explicit QQuickParticleEmitter(QQuickItem *parent = 0);
virtual ~QQuickParticleEmitter();
@@ -76,6 +86,7 @@ public:
enum Lifetime {
InfiniteLife = QQuickParticleSystem::maxLife
};
+ Q_ENUM(Lifetime)
bool enabled() const
{
diff --git a/src/particles/qquickparticleextruder_p.h b/src/particles/qquickparticleextruder_p.h
index 6367c44429..79e1114d4b 100644
--- a/src/particles/qquickparticleextruder_p.h
+++ b/src/particles/qquickparticleextruder_p.h
@@ -34,6 +34,17 @@
#ifndef PARTICLEEXTRUDER_H
#define PARTICLEEXTRUDER_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QObject>
#include <QRectF>
#include <QPointF>
diff --git a/src/particles/qquickparticlegroup_p.h b/src/particles/qquickparticlegroup_p.h
index cbc1932524..9929128915 100644
--- a/src/particles/qquickparticlegroup_p.h
+++ b/src/particles/qquickparticlegroup_p.h
@@ -32,6 +32,17 @@
****************************************************************************/
#ifndef QQuickPARTICLEGROUP
#define QQuickPARTICLEGROUP
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include <private/qquickspriteengine_p.h>
#include "qquickparticlesystem_p.h"
#include "qqmlparserstatus.h"
diff --git a/src/particles/qquickparticlepainter_p.h b/src/particles/qquickparticlepainter_p.h
index df6dc5c192..c15ebfc01c 100644
--- a/src/particles/qquickparticlepainter_p.h
+++ b/src/particles/qquickparticlepainter_p.h
@@ -34,6 +34,17 @@
#ifndef PARTICLE_H
#define PARTICLE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QObject>
#include <QDebug>
#include <QPair>
diff --git a/src/particles/qquickparticlesmodule_p.h b/src/particles/qquickparticlesmodule_p.h
index 02168af8cd..2f43d63793 100644
--- a/src/particles/qquickparticlesmodule_p.h
+++ b/src/particles/qquickparticlesmodule_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKPARTICLESMODULE_H
#define QQUICKPARTICLESMODULE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qtquickparticlesglobal_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/particles/qquickparticlesystem.cpp b/src/particles/qquickparticlesystem.cpp
index affd19d981..401d40e275 100644
--- a/src/particles/qquickparticlesystem.cpp
+++ b/src/particles/qquickparticlesystem.cpp
@@ -143,8 +143,8 @@ DEFINE_BOOL_CONFIG_OPTION(qmlParticlesDebug, QML_PARTICLES_DEBUG)
with stochastic state transitions.
Each QtQuick::Sprite in this list is interpreted as corresponding to the particle group
- with ths same name. Any transitions defined in these sprites will take effect on the particle
- groups as well. Additionally TrailEmitters, Affectors and ParticlePainters definined
+ with the same name. Any transitions defined in these sprites will take effect on the particle
+ groups as well. Additionally TrailEmitters, Affectors and ParticlePainters defined
inside one of these sprites are automatically associated with the corresponding particle group.
*/
@@ -1025,6 +1025,7 @@ void QQuickParticleSystem::createEngine()
}
m_groups = newList;
QList<QQuickStochasticState*> states;
+ states.reserve(m_groups.count());
foreach (QQuickParticleGroup* g, m_groups)
states << (QQuickStochasticState*)g;
diff --git a/src/particles/qquickparticlesystem_p.h b/src/particles/qquickparticlesystem_p.h
index c8061916b5..96bd655793 100644
--- a/src/particles/qquickparticlesystem_p.h
+++ b/src/particles/qquickparticlesystem_p.h
@@ -34,6 +34,17 @@
#ifndef PARTICLESYSTEM_H
#define PARTICLESYSTEM_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuick/QQuickItem>
#include <QElapsedTimer>
#include <QVector>
diff --git a/src/particles/qquickpointattractor_p.h b/src/particles/qquickpointattractor_p.h
index aa2c9f2083..a1f5750841 100644
--- a/src/particles/qquickpointattractor_p.h
+++ b/src/particles/qquickpointattractor_p.h
@@ -33,6 +33,17 @@
#ifndef ATTRACTORAFFECTOR_H
#define ATTRACTORAFFECTOR_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickparticleaffector_p.h"
QT_BEGIN_NAMESPACE
@@ -45,8 +56,6 @@ class QQuickAttractorAffector : public QQuickParticleAffector
Q_PROPERTY(qreal pointY READ pointY WRITE setPointY NOTIFY pointYChanged)
Q_PROPERTY(AffectableParameters affectedParameter READ affectedParameter WRITE setAffectedParameter NOTIFY affectedParameterChanged)
Q_PROPERTY(Proportion proportionalToDistance READ proportionalToDistance WRITE setProportionalToDistance NOTIFY proportionalToDistanceChanged)
- Q_ENUMS(AffectableParameters)
- Q_ENUMS(Proportion)
public:
enum Proportion{
@@ -56,12 +65,14 @@ public:
InverseLinear,
InverseQuadratic
};
+ Q_ENUM(Proportion)
enum AffectableParameters {
Position,
Velocity,
Acceleration
};
+ Q_ENUM(AffectableParameters)
explicit QQuickAttractorAffector(QQuickItem *parent = 0);
diff --git a/src/particles/qquickpointdirection_p.h b/src/particles/qquickpointdirection_p.h
index 3975389a6b..26a4d28126 100644
--- a/src/particles/qquickpointdirection_p.h
+++ b/src/particles/qquickpointdirection_p.h
@@ -33,6 +33,17 @@
#ifndef POINTVECTOR_H
#define POINTVECTOR_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickdirection_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/particles/qquickrectangleextruder_p.h b/src/particles/qquickrectangleextruder_p.h
index 8ed535eaea..c286b60b14 100644
--- a/src/particles/qquickrectangleextruder_p.h
+++ b/src/particles/qquickrectangleextruder_p.h
@@ -34,6 +34,17 @@
#ifndef RECTANGLEEXTRUDER_H
#define RECTANGLEEXTRUDER_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickparticleextruder_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/particles/qquickspritegoal_p.h b/src/particles/qquickspritegoal_p.h
index 1ddfe14ac3..18ab6af156 100644
--- a/src/particles/qquickspritegoal_p.h
+++ b/src/particles/qquickspritegoal_p.h
@@ -33,6 +33,17 @@
#ifndef SPRITEGOALAFFECTOR_H
#define SPRITEGOALAFFECTOR_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickparticleaffector_p.h"
#include <QtQml/qqmlinfo.h>
diff --git a/src/particles/qquicktargetdirection_p.h b/src/particles/qquicktargetdirection_p.h
index bde6144d7f..75a53eec90 100644
--- a/src/particles/qquicktargetdirection_p.h
+++ b/src/particles/qquicktargetdirection_p.h
@@ -33,6 +33,17 @@
#ifndef DIRECTEDVECTOR_H
#define DIRECTEDVECTOR_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickdirection_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/particles/qquicktrailemitter_p.h b/src/particles/qquicktrailemitter_p.h
index d1213158d8..9f03a1107e 100644
--- a/src/particles/qquicktrailemitter_p.h
+++ b/src/particles/qquicktrailemitter_p.h
@@ -33,6 +33,17 @@
#ifndef FOLLOWEMITTER_H
#define FOLLOWEMITTER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickparticleemitter_p.h"
#include "qquickparticleaffector_p.h"
@@ -48,11 +59,11 @@ class QQuickTrailEmitter : public QQuickParticleEmitter
Q_PROPERTY(qreal emitHeight READ emitterYVariation WRITE setEmitterYVariation NOTIFY emitterYVariationChanged)
Q_PROPERTY(qreal emitWidth READ emitterXVariation WRITE setEmitterXVariation NOTIFY emitterXVariationChanged)
- Q_ENUMS(EmitSize)
public:
enum EmitSize {
ParticleSize = -2//Anything less than 0 will do
};
+ Q_ENUM(EmitSize)
explicit QQuickTrailEmitter(QQuickItem *parent = 0);
virtual void emitWindow(int timeStamp);
virtual void reset();
diff --git a/src/particles/qquickturbulence.cpp b/src/particles/qquickturbulence.cpp
index 11bae1107b..8d5846710a 100644
--- a/src/particles/qquickturbulence.cpp
+++ b/src/particles/qquickturbulence.cpp
@@ -36,6 +36,7 @@
#include <cmath>
#include <cstdlib>
#include <QDebug>
+#include <QQmlFile>
QT_BEGIN_NAMESPACE
/*!
@@ -108,7 +109,6 @@ void QQuickTurbulenceAffector::initializeGrid()
for (int i=0; i<m_gridSize; i++)
free(m_field[i]);
free(m_field);
- m_system = 0;
}
if (m_vectorField) {
for (int i=0; i<m_gridSize; i++)
@@ -127,17 +127,17 @@ void QQuickTurbulenceAffector::initializeGrid()
QImage image;
if (!m_noiseSource.isEmpty())
- image = QImage(m_noiseSource.toLocalFile()).scaled(QSize(m_gridSize, m_gridSize));
+ image = QImage(QQmlFile::urlToLocalFileOrQrc(m_noiseSource)).scaled(QSize(m_gridSize, m_gridSize));
if (image.isNull())
image = QImage(QStringLiteral(":particleresources/noise.png")).scaled(QSize(m_gridSize, m_gridSize));
for (int i=0; i<m_gridSize; i++)
for (int j=0; j<m_gridSize; j++)
- m_field[i][j] = qRed(image.pixel(QPoint(i,j)));//Red as proxy for Value
+ m_field[i][j] = qGray(image.pixel(QPoint(i,j)));
for (int i=0; i<m_gridSize; i++){
for (int j=0; j<m_gridSize; j++){
- m_vectorField[i][j].setX(boundsRespectingField(i,j) - boundsRespectingField(i,j-1));
- m_vectorField[i][j].setY(boundsRespectingField(i-1,j) - boundsRespectingField(i,j));
+ m_vectorField[i][j].setX(boundsRespectingField(i-1,j) - boundsRespectingField(i,j));
+ m_vectorField[i][j].setY(boundsRespectingField(i,j) - boundsRespectingField(i,j-1));
}
}
}
diff --git a/src/particles/qquickturbulence_p.h b/src/particles/qquickturbulence_p.h
index 3c32bb6063..44122e154f 100644
--- a/src/particles/qquickturbulence_p.h
+++ b/src/particles/qquickturbulence_p.h
@@ -33,6 +33,17 @@
#ifndef TURBULENCEAFFECTOR_H
#define TURBULENCEAFFECTOR_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "qquickparticleaffector_p.h"
#include <QQmlListProperty>
diff --git a/src/particles/qquickv4particledata.cpp b/src/particles/qquickv4particledata.cpp
index fcab455cce..876c7214b0 100644
--- a/src/particles/qquickv4particledata.cpp
+++ b/src/particles/qquickv4particledata.cpp
@@ -266,9 +266,8 @@ QT_BEGIN_NAMESPACE
struct QV4ParticleData : public QV4::Object
{
struct Data : QV4::Object::Data {
- Data(QV4::ExecutionEngine *engine, QQuickParticleData *datum)
- : QV4::Heap::Object(engine)
- , datum(datum)
+ Data(QQuickParticleData *datum)
+ : datum(datum)
{
}
QQuickParticleData* datum;//TODO: Guard needed?
@@ -506,7 +505,7 @@ QQuickV4ParticleData::QQuickV4ParticleData(QV8Engine* engine, QQuickParticleData
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
QV4ParticleDataDeletable *d = particleV4Data(scope.engine);
- QV4::ScopedObject o(scope, v4->memoryManager->alloc<QV4ParticleData>(v4, datum));
+ QV4::ScopedObject o(scope, v4->memoryManager->allocObject<QV4ParticleData>(datum));
QV4::ScopedObject p(scope, d->proto.value());
o->setPrototype(p);
m_v4Value = o;
diff --git a/src/particles/qquickv4particledata_p.h b/src/particles/qquickv4particledata_p.h
index f211ec7e7d..5abeadf1fa 100644
--- a/src/particles/qquickv4particledata_p.h
+++ b/src/particles/qquickv4particledata_p.h
@@ -34,9 +34,20 @@
#ifndef QQuickV8PARTICLEDATA_H
#define QQuickV8PARTICLEDATA_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qv8engine_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/particles/qquickwander_p.h b/src/particles/qquickwander_p.h
index 49c49c560e..67ebbebd96 100644
--- a/src/particles/qquickwander_p.h
+++ b/src/particles/qquickwander_p.h
@@ -33,6 +33,17 @@
#ifndef WANDERAFFECTOR_H
#define WANDERAFFECTOR_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include <QHash>
#include "qquickparticleaffector_p.h"
@@ -54,7 +65,6 @@ class QQuickWanderAffector : public QQuickParticleAffector
Q_PROPERTY(qreal xVariance READ xVariance WRITE setXVariance NOTIFY xVarianceChanged)
Q_PROPERTY(qreal yVariance READ yVariance WRITE setYVariance NOTIFY yVarianceChanged)
Q_PROPERTY(AffectableParameters affectedParameter READ affectedParameter WRITE setAffectedParameter NOTIFY affectedParameterChanged)
- Q_ENUMS(AffectableParameters)
public:
enum AffectableParameters {
@@ -62,6 +72,7 @@ public:
Velocity,
Acceleration
};
+ Q_ENUM(AffectableParameters)
explicit QQuickWanderAffector(QQuickItem *parent = 0);
~QQuickWanderAffector();
diff --git a/src/particles/qtquickparticlesglobal_p.h b/src/particles/qtquickparticlesglobal_p.h
index 783dd1895c..4c97247edd 100644
--- a/src/particles/qtquickparticlesglobal_p.h
+++ b/src/particles/qtquickparticlesglobal_p.h
@@ -34,6 +34,17 @@
#ifndef QTQUICKPARTICLESGLOBAL_P_H
#define QTQUICKPARTICLESGLOBAL_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qglobal.h>
// We only have private exports from this library
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 664a457608..273407c19d 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -1,2 +1,2 @@
TEMPLATE = subdirs
-SUBDIRS += qmltooling
+!contains(QT_CONFIG, no-qml-debug):SUBDIRS += qmltooling
diff --git a/src/qml/debugger/qdebugmessageservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp
index deaa472ce0..6bccec08b1 100644
--- a/src/qml/debugger/qdebugmessageservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp
@@ -31,62 +31,37 @@
**
****************************************************************************/
-#include "qdebugmessageservice_p.h"
-#include "qqmldebugservice_p_p.h"
+#include "qdebugmessageservice.h"
+#include <private/qqmldebugconnector_p.h>
#include <QDataStream>
-#include <QMutex>
QT_BEGIN_NAMESPACE
-Q_GLOBAL_STATIC(QDebugMessageService, qmlDebugMessageService)
+const QString QDebugMessageService::s_key = QStringLiteral("DebugMessages");
void DebugMessageHandler(QtMsgType type, const QMessageLogContext &ctxt,
const QString &buf)
{
- QDebugMessageService::instance()->sendDebugMessage(type, ctxt, buf);
+ QQmlDebugConnector::service<QDebugMessageService>()->sendDebugMessage(type, ctxt, buf);
}
-class QDebugMessageServicePrivate : public QQmlDebugServicePrivate
-{
-public:
- QDebugMessageServicePrivate()
- : oldMsgHandler(0)
- , prevState(QQmlDebugService::NotConnected)
- {
- }
-
- QtMessageHandler oldMsgHandler;
- QQmlDebugService::State prevState;
- QMutex initMutex;
-};
-
QDebugMessageService::QDebugMessageService(QObject *parent) :
- QQmlDebugService(*(new QDebugMessageServicePrivate()),
- QStringLiteral("DebugMessages"), 2, parent)
+ QQmlDebugService(s_key, 2, parent), oldMsgHandler(0),
+ prevState(QQmlDebugService::NotConnected)
{
- Q_D(QDebugMessageService);
-
// don't execute stateChanged() in parallel
- QMutexLocker lock(&d->initMutex);
- registerService();
+ QMutexLocker lock(&initMutex);
if (state() == Enabled) {
- d->oldMsgHandler = qInstallMessageHandler(DebugMessageHandler);
- d->prevState = Enabled;
+ oldMsgHandler = qInstallMessageHandler(DebugMessageHandler);
+ prevState = Enabled;
}
}
-QDebugMessageService *QDebugMessageService::instance()
-{
- return qmlDebugMessageService();
-}
-
void QDebugMessageService::sendDebugMessage(QtMsgType type,
const QMessageLogContext &ctxt,
const QString &buf)
{
- Q_D(QDebugMessageService);
-
//We do not want to alter the message handling mechanism
//We just eavesdrop and forward the messages to a port
//only if a client is connected to it.
@@ -96,27 +71,26 @@ void QDebugMessageService::sendDebugMessage(QtMsgType type,
ws << QString::fromLatin1(ctxt.file).toUtf8();
ws << ctxt.line << QString::fromLatin1(ctxt.function).toUtf8();
- sendMessage(message);
- if (d->oldMsgHandler)
- (*d->oldMsgHandler)(type, ctxt, buf);
+ emit messageToClient(name(), message);
+ if (oldMsgHandler)
+ (*oldMsgHandler)(type, ctxt, buf);
}
void QDebugMessageService::stateChanged(State state)
{
- Q_D(QDebugMessageService);
- QMutexLocker lock(&d->initMutex);
+ QMutexLocker lock(&initMutex);
- if (state != Enabled && d->prevState == Enabled) {
- QtMessageHandler handler = qInstallMessageHandler(d->oldMsgHandler);
+ if (state != Enabled && prevState == Enabled) {
+ QtMessageHandler handler = qInstallMessageHandler(oldMsgHandler);
// has our handler been overwritten in between?
if (handler != DebugMessageHandler)
qInstallMessageHandler(handler);
- } else if (state == Enabled && d->prevState != Enabled) {
- d->oldMsgHandler = qInstallMessageHandler(DebugMessageHandler);
+ } else if (state == Enabled && prevState != Enabled) {
+ oldMsgHandler = qInstallMessageHandler(DebugMessageHandler);
}
- d->prevState = state;
+ prevState = state;
}
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qdebugmessageservice_p.h b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.h
index 694cd0e64c..c0dc41bcd0 100644
--- a/src/qml/debugger/qdebugmessageservice_p.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.h
@@ -31,8 +31,8 @@
**
****************************************************************************/
-#ifndef QDEBUGMESSAGESERVICE_P_H
-#define QDEBUGMESSAGESERVICE_P_H
+#ifndef QDEBUGMESSAGESERVICE_H
+#define QDEBUGMESSAGESERVICE_H
//
// W A R N I N G
@@ -45,9 +45,10 @@
// We mean it.
//
-#include "qqmldebugservice_p.h"
+#include <private/qqmldebugservice_p.h>
#include <QtCore/qlogging.h>
+#include <QtCore/qmutex.h>
QT_BEGIN_NAMESPACE
@@ -59,19 +60,23 @@ class QDebugMessageService : public QQmlDebugService
public:
QDebugMessageService(QObject *parent = 0);
- static QDebugMessageService *instance();
-
void sendDebugMessage(QtMsgType type, const QMessageLogContext &ctxt,
const QString &buf);
protected:
+ static const QString s_key;
+
void stateChanged(State);
private:
- Q_DISABLE_COPY(QDebugMessageService)
- Q_DECLARE_PRIVATE(QDebugMessageService)
+ friend class QQmlDebugConnector;
+ friend class QQmlDebuggerServiceFactory;
+
+ QtMessageHandler oldMsgHandler;
+ QQmlDebugService::State prevState;
+ QMutex initMutex;
};
QT_END_NAMESPACE
-#endif // QDEBUGMESSAGESERVICE_P_H
+#endif // QDEBUGMESSAGESERVICE_H
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro b/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro
new file mode 100644
index 0000000000..8d1a54e9e4
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qmldbg_debugger.pro
@@ -0,0 +1,34 @@
+TARGET = qmldbg_debugger
+QT = qml-private core-private
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QQmlDebuggerServiceFactory
+load(qt_plugin)
+
+SOURCES += \
+ $$PWD/qdebugmessageservice.cpp \
+ $$PWD/qqmldebuggerservicefactory.cpp \
+ $$PWD/qqmlenginedebugservice.cpp \
+ $$PWD/qqmlnativedebugservice.cpp \
+ $$PWD/qqmlwatcher.cpp \
+ $$PWD/qv4debugservice.cpp \
+ $$PWD/qv4debuggeragent.cpp \
+ $$PWD/qv4datacollector.cpp
+
+HEADERS += \
+ $$PWD/../shared/qqmlconfigurabledebugservice.h \
+ $$PWD/qdebugmessageservice.h \
+ $$PWD/qqmldebuggerservicefactory.h \
+ $$PWD/qqmlenginedebugservice.h \
+ $$PWD/qqmlnativedebugservice.h \
+ $$PWD/qqmlwatcher.h \
+ $$PWD/qv4debugservice.h \
+ $$PWD/qv4debuggeragent.h \
+ $$PWD/qv4datacollector.h
+
+INCLUDEPATH += $$PWD \
+ $$PWD/../shared
+
+OTHER_FILES += \
+ $$PWD/qqmldebuggerservice.json
+
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservice.json b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservice.json
new file mode 100644
index 0000000000..967a725903
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservice.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "DebugMessages", "QmlDebugger", "V8Debugger", "NativeQmlDebugger" ]
+}
diff --git a/src/plugins/qmltooling/shared/qmlinspectorconstants.h b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp
index d76e172844..f379352cfa 100644
--- a/src/plugins/qmltooling/shared/qmlinspectorconstants.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.cpp
@@ -31,36 +31,30 @@
**
****************************************************************************/
-#ifndef QMLINSPECTORCONSTANTS_H
-#define QMLINSPECTORCONSTANTS_H
+#include "qqmldebuggerservicefactory.h"
+#include "qqmlenginedebugservice.h"
+#include "qdebugmessageservice.h"
+#include "qv4debugservice.h"
+#include "qqmlnativedebugservice.h"
+#include <private/qqmldebugserviceinterfaces_p.h>
-#include <QtQml/private/qqmlglobal_p.h>
+QT_BEGIN_NAMESPACE
-namespace QmlJSDebugger {
-namespace Constants {
+QQmlDebugService *QQmlDebuggerServiceFactory::create(const QString &key)
+{
+ if (key == QDebugMessageService::s_key)
+ return new QDebugMessageService(this);
-enum DesignTool {
- NoTool = 0,
- SelectionToolMode = 1,
- MarqueeSelectionToolMode = 2,
- MoveToolMode = 3,
- ResizeToolMode = 4,
- ZoomMode = 6
-};
+ if (key == QQmlEngineDebugServiceImpl::s_key)
+ return new QQmlEngineDebugServiceImpl(this);
-static const int PressAndHoldTimeout = 800;
+ if (key == QV4DebugServiceImpl::s_key)
+ return new QV4DebugServiceImpl(this);
-static const double ZoomSnapDelta = 0.04;
+ if (key == QQmlNativeDebugServiceImpl::s_key)
+ return new QQmlNativeDebugServiceImpl(this);
-static const int EditorItemDataKey = 1000;
+ return 0;
+}
-enum GraphicsItemTypes {
- EditorItemType = 0xEAAA,
- ResizeHandleItemType = 0xEAEA
-};
-
-
-} // namespace Constants
-} // namespace QmlJSDebugger
-
-#endif // QMLINSPECTORCONSTANTS_H
+QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4qmlextensions_p.h b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.h
index e4b9f75298..2c7509ba12 100644
--- a/src/qml/jsruntime/qv4qmlextensions_p.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmldebuggerservicefactory.h
@@ -30,29 +30,22 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QV4QMLEXTENSIONS_P_H
-#define QV4QMLEXTENSIONS_P_H
-#include <qtqmlglobal.h>
-#include <qv4global_p.h>
+#ifndef QQMLDEBUGGERSERVICEFACTORY_H
+#define QQMLDEBUGGERSERVICEFACTORY_H
-QT_BEGIN_NAMESPACE
+#include <private/qqmldebugservicefactory_p.h>
-namespace QV4 {
+QT_BEGIN_NAMESPACE
-struct Q_QML_EXPORT QmlExtensions
+class QQmlDebuggerServiceFactory : public QQmlDebugServiceFactory
{
- QmlExtensions()
- : valueTypeWrapperPrototype(0)
- {}
-
- Heap::Object *valueTypeWrapperPrototype;
-
- void markObjects(ExecutionEngine *e);
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlDebugServiceFactory_iid FILE "qqmldebuggerservice.json")
+public:
+ QQmlDebugService *create(const QString &key);
};
-} // namespace QV4
-
QT_END_NAMESPACE
-#endif
+#endif // QQMLDEBUGGERSERVICEFACTORY_H
diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
index da01d00f17..8f53dc6d50 100644
--- a/src/qml/debugger/qqmlenginedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
@@ -31,9 +31,10 @@
**
****************************************************************************/
-#include "qqmlenginedebugservice_p.h"
+#include "qqmlenginedebugservice.h"
+#include "qqmlwatcher.h"
-#include "qqmldebugstatesdelegate_p.h"
+#include <private/qqmldebugstatesdelegate_p.h>
#include <private/qqmlboundsignal_p.h>
#include <qqmlengine.h>
#include <private/qqmlmetatype_p.h>
@@ -41,42 +42,31 @@
#include <private/qqmlproperty_p.h>
#include <private/qqmlbinding_p.h>
#include <private/qqmlcontext_p.h>
-#include <private/qqmlwatcher_p.h>
#include <private/qqmlvaluetype_p.h>
#include <private/qqmlvmemetaobject_p.h>
#include <private/qqmlexpression_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qmetaobject.h>
+#include <QtCore/qfileinfo.h>
#include <private/qmetaobject_p.h>
QT_BEGIN_NAMESPACE
-Q_GLOBAL_STATIC(QQmlEngineDebugService, qmlEngineDebugService)
-
-QQmlEngineDebugService *QQmlEngineDebugService::instance()
-{
- return qmlEngineDebugService();
-}
-
-QQmlEngineDebugService::QQmlEngineDebugService(QObject *parent)
- : QQmlDebugService(QStringLiteral("QmlDebugger"), 2, parent),
- m_watch(new QQmlWatcher(this)),
- m_statesDelegate(0)
+QQmlEngineDebugServiceImpl::QQmlEngineDebugServiceImpl(QObject *parent) :
+ QQmlEngineDebugService(2, parent), m_watch(new QQmlWatcher(this)), m_statesDelegate(0)
{
QObject::connect(m_watch, SIGNAL(propertyChanged(int,int,QMetaProperty,QVariant)),
this, SLOT(propertyChanged(int,int,QMetaProperty,QVariant)));
-
- registerService();
}
-QQmlEngineDebugService::~QQmlEngineDebugService()
+QQmlEngineDebugServiceImpl::~QQmlEngineDebugServiceImpl()
{
delete m_statesDelegate;
}
QDataStream &operator<<(QDataStream &ds,
- const QQmlEngineDebugService::QQmlObjectData &data)
+ const QQmlEngineDebugServiceImpl::QQmlObjectData &data)
{
ds << data.url << data.lineNumber << data.columnNumber << data.idString
<< data.objectName << data.objectType << data.objectId << data.contextId
@@ -85,7 +75,7 @@ QDataStream &operator<<(QDataStream &ds,
}
QDataStream &operator>>(QDataStream &ds,
- QQmlEngineDebugService::QQmlObjectData &data)
+ QQmlEngineDebugServiceImpl::QQmlObjectData &data)
{
ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
>> data.objectName >> data.objectType >> data.objectId >> data.contextId
@@ -94,7 +84,7 @@ QDataStream &operator>>(QDataStream &ds,
}
QDataStream &operator<<(QDataStream &ds,
- const QQmlEngineDebugService::QQmlObjectProperty &data)
+ const QQmlEngineDebugServiceImpl::QQmlObjectProperty &data)
{
ds << (int)data.type << data.name;
// check first whether the data can be saved
@@ -110,12 +100,12 @@ QDataStream &operator<<(QDataStream &ds,
}
QDataStream &operator>>(QDataStream &ds,
- QQmlEngineDebugService::QQmlObjectProperty &data)
+ QQmlEngineDebugServiceImpl::QQmlObjectProperty &data)
{
int type;
ds >> type >> data.name >> data.value >> data.valueTypeName
>> data.binding >> data.hasNotifySignal;
- data.type = (QQmlEngineDebugService::QQmlObjectProperty::Type)type;
+ data.type = (QQmlEngineDebugServiceImpl::QQmlObjectProperty::Type)type;
return ds;
}
@@ -142,8 +132,8 @@ static bool hasValidSignal(QObject *object, const QString &propertyName)
return true;
}
-QQmlEngineDebugService::QQmlObjectProperty
-QQmlEngineDebugService::propertyData(QObject *obj, int propIdx)
+QQmlEngineDebugServiceImpl::QQmlObjectProperty
+QQmlEngineDebugServiceImpl::propertyData(QObject *obj, int propIdx)
{
QQmlObjectProperty rv;
@@ -177,7 +167,7 @@ QQmlEngineDebugService::propertyData(QObject *obj, int propIdx)
return rv;
}
-QVariant QQmlEngineDebugService::valueContents(QVariant value) const
+QVariant QQmlEngineDebugServiceImpl::valueContents(QVariant value) const
{
// We can't send JS objects across the wire, so transform them to variant
// maps for serialization.
@@ -192,6 +182,7 @@ QVariant QQmlEngineDebugService::valueContents(QVariant value) const
QVariantList contents;
QVariantList list = value.toList();
int count = list.size();
+ contents.reserve(count);
for (int i = 0; i < count; i++)
contents << valueContents(list.at(i));
return contents;
@@ -237,7 +228,7 @@ QVariant QQmlEngineDebugService::valueContents(QVariant value) const
return QString(QStringLiteral("<unknown value>"));
}
-void QQmlEngineDebugService::buildObjectDump(QDataStream &message,
+void QQmlEngineDebugServiceImpl::buildObjectDump(QDataStream &message,
QObject *object, bool recur, bool dumpProperties)
{
message << objectData(object);
@@ -277,13 +268,9 @@ void QQmlEngineDebugService::buildObjectDump(QDataStream &message,
QQmlData *ddata = QQmlData::get(object);
if (ddata && ddata->signalHandlers) {
- QQmlAbstractBoundSignal *signalHandler = ddata->signalHandlers;
+ QQmlBoundSignal *signalHandler = ddata->signalHandlers;
while (signalHandler) {
- if (!dumpProperties) {
- signalHandler = signalHandler->m_nextSignal;
- continue;
- }
QQmlObjectProperty prop;
prop.type = QQmlObjectProperty::SignalProperty;
prop.hasNotifySignal = false;
@@ -292,7 +279,7 @@ void QQmlEngineDebugService::buildObjectDump(QDataStream &message,
prop.value = expr->expression();
QObject *scope = expr->scopeObject();
if (scope) {
- QString methodName = QString::fromLatin1(QMetaObjectPrivate::signal(scope->metaObject(), signalHandler->index()).name());
+ QString methodName = QString::fromLatin1(QMetaObjectPrivate::signal(scope->metaObject(), signalHandler->signalIndex()).name());
if (!methodName.isEmpty()) {
prop.name = QLatin1String("on") + methodName[0].toUpper()
+ methodName.mid(1);
@@ -301,7 +288,7 @@ void QQmlEngineDebugService::buildObjectDump(QDataStream &message,
}
fakeProperties << prop;
- signalHandler = signalHandler->m_nextSignal;
+ signalHandler = nextSignal(signalHandler);
}
}
@@ -314,7 +301,7 @@ void QQmlEngineDebugService::buildObjectDump(QDataStream &message,
message << fakeProperties[ii];
}
-void QQmlEngineDebugService::prepareDeferredObjects(QObject *obj)
+void QQmlEngineDebugServiceImpl::prepareDeferredObjects(QObject *obj)
{
qmlExecuteDeferred(obj);
@@ -326,7 +313,7 @@ void QQmlEngineDebugService::prepareDeferredObjects(QObject *obj)
}
-void QQmlEngineDebugService::storeObjectIds(QObject *co)
+void QQmlEngineDebugServiceImpl::storeObjectIds(QObject *co)
{
QQmlDebugService::idForObject(co);
QObjectList children = co->children();
@@ -334,7 +321,7 @@ void QQmlEngineDebugService::storeObjectIds(QObject *co)
storeObjectIds(children.at(ii));
}
-void QQmlEngineDebugService::buildObjectList(QDataStream &message,
+void QQmlEngineDebugServiceImpl::buildObjectList(QDataStream &message,
QQmlContext *ctxt,
const QList<QPointer<QObject> > &instances)
{
@@ -378,15 +365,15 @@ void QQmlEngineDebugService::buildObjectList(QDataStream &message,
}
}
-void QQmlEngineDebugService::buildStatesList(bool cleanList,
+void QQmlEngineDebugServiceImpl::buildStatesList(bool cleanList,
const QList<QPointer<QObject> > &instances)
{
if (m_statesDelegate)
m_statesDelegate->buildStatesList(cleanList, instances);
}
-QQmlEngineDebugService::QQmlObjectData
-QQmlEngineDebugService::objectData(QObject *object)
+QQmlEngineDebugServiceImpl::QQmlObjectData
+QQmlEngineDebugServiceImpl::objectData(QObject *object)
{
QQmlData *ddata = QQmlData::get(object);
QQmlObjectData rv;
@@ -425,12 +412,33 @@ QQmlEngineDebugService::objectData(QObject *object)
return rv;
}
-void QQmlEngineDebugService::messageReceived(const QByteArray &message)
+void QQmlEngineDebugServiceImpl::messageReceived(const QByteArray &message)
{
QMetaObject::invokeMethod(this, "processMessage", Qt::QueuedConnection, Q_ARG(QByteArray, message));
}
-void QQmlEngineDebugService::processMessage(const QByteArray &message)
+/*!
+ Returns a list of objects matching the given filename, line and column.
+*/
+QList<QObject*> QQmlEngineDebugServiceImpl::objectForLocationInfo(const QString &filename,
+ int lineNumber, int columnNumber)
+{
+ QList<QObject *> objects;
+ const QHash<int, QObject *> &hash = objectsForIds();
+ for (QHash<int, QObject *>::ConstIterator i = hash.constBegin(); i != hash.constEnd(); ++i) {
+ QQmlData *ddata = QQmlData::get(i.value());
+ if (ddata && ddata->outerContext) {
+ if (QFileInfo(ddata->outerContext->urlString()).fileName() == filename &&
+ ddata->lineNumber == lineNumber &&
+ ddata->columnNumber >= columnNumber) {
+ objects << i.value();
+ }
+ }
+ }
+ return objects;
+}
+
+void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
{
QQmlDebugStream ds(message);
@@ -503,8 +511,7 @@ void QQmlEngineDebugService::processMessage(const QByteArray &message)
ds >> file >> lineNumber >> columnNumber >> recurse >> dumpProperties;
- QList<QObject*> objects = QQmlDebugService::objectForLocationInfo(
- file, lineNumber, columnNumber);
+ QList<QObject*> objects = objectForLocationInfo(file, lineNumber, columnNumber);
rs << QByteArray("FETCH_OBJECTS_FOR_LOCATION_R") << queryId
<< objects.count();
@@ -610,10 +617,10 @@ void QQmlEngineDebugService::processMessage(const QByteArray &message)
rs << QByteArray("SET_METHOD_BODY_R") << queryId << ok;
}
- sendMessage(reply);
+ emit messageToClient(name(), reply);
}
-bool QQmlEngineDebugService::setBinding(int objectId,
+bool QQmlEngineDebugServiceImpl::setBinding(int objectId,
const QString &propertyName,
const QVariant &expression,
bool isLiteralValue,
@@ -644,11 +651,9 @@ bool QQmlEngineDebugService::setBinding(int objectId,
filename, line, column);
QQmlPropertyPrivate::takeSignalExpression(property, qmlExpression);
} else if (property.isProperty()) {
- QQmlBinding *binding = new QQmlBinding(expression.toString(), object, QQmlContextData::get(context), filename, line, column);;
+ QQmlBinding *binding = new QQmlBinding(expression.toString(), object, QQmlContextData::get(context), filename, line, column);
binding->setTarget(property);
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::setBinding(property, binding);
- if (oldBinding)
- oldBinding->destroy();
+ QQmlPropertyPrivate::setBinding(binding);
binding->update();
} else {
ok = false;
@@ -667,7 +672,7 @@ bool QQmlEngineDebugService::setBinding(int objectId,
return ok;
}
-bool QQmlEngineDebugService::resetBinding(int objectId, const QString &propertyName)
+bool QQmlEngineDebugServiceImpl::resetBinding(int objectId, const QString &propertyName)
{
QObject *object = objectForId(objectId);
QQmlContext *context = qmlContext(object);
@@ -679,12 +684,7 @@ bool QQmlEngineDebugService::resetBinding(int objectId, const QString &propertyN
if (object->property(parentProperty.toLatin1()).isValid()) {
QQmlProperty property(object, propertyName);
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(property);
- if (oldBinding) {
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::setBinding(property, 0);
- if (oldBinding)
- oldBinding->destroy();
- }
+ QQmlPropertyPrivate::removeBinding(property);
if (property.isResettable()) {
// Note: this will reset the property in any case, without regard to states
// Right now almost no QQuickItem has reset methods for its properties (with the
@@ -725,7 +725,7 @@ bool QQmlEngineDebugService::resetBinding(int objectId, const QString &propertyN
return false;
}
-bool QQmlEngineDebugService::setMethodBody(int objectId, const QString &method, const QString &body)
+bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &method, const QString &body)
{
QObject *object = objectForId(objectId);
QQmlContext *context = qmlContext(object);
@@ -762,22 +762,22 @@ bool QQmlEngineDebugService::setMethodBody(int objectId, const QString &method,
int lineNumber = vmeMetaObject->vmeMethodLineNumber(prop->coreIndex);
QV4::ExecutionEngine *v4 = QV8Engine::getV4(qmlEngine(object)->handle());
QV4::Scope scope(v4);
- QV4::ScopedValue v(scope, QQmlExpressionPrivate::evalFunction(contextData, object, jsfunction, contextData->urlString(), lineNumber));
+ QV4::ScopedValue v(scope, QQmlJavaScriptExpression::evalFunction(contextData, object, jsfunction, contextData->urlString(), lineNumber));
vmeMetaObject->setVmeMethod(prop->coreIndex, v);
return true;
}
-void QQmlEngineDebugService::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
+void QQmlEngineDebugServiceImpl::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
{
QByteArray reply;
QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("UPDATE_WATCH") << id << objectId << QByteArray(property.name()) << valueContents(value);
- sendMessage(reply);
+ emit messageToClient(name(), reply);
}
-void QQmlEngineDebugService::engineAboutToBeAdded(QQmlEngine *engine)
+void QQmlEngineDebugServiceImpl::engineAboutToBeAdded(QQmlEngine *engine)
{
Q_ASSERT(engine);
Q_ASSERT(!m_engines.contains(engine));
@@ -786,7 +786,7 @@ void QQmlEngineDebugService::engineAboutToBeAdded(QQmlEngine *engine)
emit attachedToEngine(engine);
}
-void QQmlEngineDebugService::engineAboutToBeRemoved(QQmlEngine *engine)
+void QQmlEngineDebugServiceImpl::engineAboutToBeRemoved(QQmlEngine *engine)
{
Q_ASSERT(engine);
Q_ASSERT(m_engines.contains(engine));
@@ -795,7 +795,7 @@ void QQmlEngineDebugService::engineAboutToBeRemoved(QQmlEngine *engine)
emit detachedFromEngine(engine);
}
-void QQmlEngineDebugService::objectCreated(QQmlEngine *engine, QObject *object)
+void QQmlEngineDebugServiceImpl::objectCreated(QQmlEngine *engine, QObject *object)
{
Q_ASSERT(engine);
Q_ASSERT(m_engines.contains(engine));
@@ -809,10 +809,10 @@ void QQmlEngineDebugService::objectCreated(QQmlEngine *engine, QObject *object)
//unique queryId -1
rs << QByteArray("OBJECT_CREATED") << -1 << engineId << objectId << parentId;
- sendMessage(reply);
+ emit messageToClient(name(), reply);
}
-void QQmlEngineDebugService::setStatesDelegate(QQmlDebugStatesDelegate *delegate)
+void QQmlEngineDebugServiceImpl::setStatesDelegate(QQmlDebugStatesDelegate *delegate)
{
m_statesDelegate = delegate;
}
diff --git a/src/qml/debugger/qqmlenginedebugservice_p.h b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h
index 0a824b132f..68cb420cc0 100644
--- a/src/qml/debugger/qqmlenginedebugservice_p.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h
@@ -31,8 +31,8 @@
**
****************************************************************************/
-#ifndef QQMLENGINEDEBUGSERVICE_P_H
-#define QQMLENGINEDEBUGSERVICE_P_H
+#ifndef QQMLENGINEDEBUGSERVICE_H
+#define QQMLENGINEDEBUGSERVICE_H
//
// W A R N I N G
@@ -46,6 +46,7 @@
//
#include <private/qqmldebugservice_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#include <QtCore/qurl.h>
#include <QtCore/qvariant.h>
@@ -59,12 +60,12 @@ class QQmlWatcher;
class QDataStream;
class QQmlDebugStatesDelegate;
-class Q_QML_PRIVATE_EXPORT QQmlEngineDebugService : public QQmlDebugService
+class QQmlEngineDebugServiceImpl : public QQmlEngineDebugService
{
Q_OBJECT
public:
- QQmlEngineDebugService(QObject * = 0);
- ~QQmlEngineDebugService();
+ QQmlEngineDebugServiceImpl(QObject * = 0);
+ ~QQmlEngineDebugServiceImpl();
struct QQmlObjectData {
QUrl url;
@@ -88,22 +89,22 @@ public:
bool hasNotifySignal;
};
- void engineAboutToBeAdded(QQmlEngine *);
- void engineAboutToBeRemoved(QQmlEngine *);
- void objectCreated(QQmlEngine *, QObject *);
+ void engineAboutToBeAdded(QQmlEngine *) Q_DECL_OVERRIDE;
+ void engineAboutToBeRemoved(QQmlEngine *) Q_DECL_OVERRIDE;
+ void objectCreated(QQmlEngine *, QObject *) Q_DECL_OVERRIDE;
- void setStatesDelegate(QQmlDebugStatesDelegate *);
-
- static QQmlEngineDebugService *instance();
+ void setStatesDelegate(QQmlDebugStatesDelegate *) Q_DECL_OVERRIDE;
protected:
- virtual void messageReceived(const QByteArray &);
+ virtual void messageReceived(const QByteArray &) Q_DECL_OVERRIDE;
private Q_SLOTS:
void processMessage(const QByteArray &msg);
void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value);
private:
+ friend class QQmlDebuggerServiceFactory;
+
void prepareDeferredObjects(QObject *);
void buildObjectList(QDataStream &, QQmlContext *,
const QList<QPointer<QObject> > &instances);
@@ -116,17 +117,19 @@ private:
bool resetBinding(int objectId, const QString &propertyName);
bool setMethodBody(int objectId, const QString &method, const QString &body);
void storeObjectIds(QObject *co);
+ QList<QObject *> objectForLocationInfo(const QString &filename, int lineNumber,
+ int columnNumber);
QList<QQmlEngine *> m_engines;
QQmlWatcher *m_watch;
QQmlDebugStatesDelegate *m_statesDelegate;
};
-Q_QML_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QQmlEngineDebugService::QQmlObjectData &);
-Q_QML_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QQmlEngineDebugService::QQmlObjectData &);
-Q_QML_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QQmlEngineDebugService::QQmlObjectProperty &);
-Q_QML_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QQmlEngineDebugService::QQmlObjectProperty &);
+QDataStream &operator<<(QDataStream &, const QQmlEngineDebugServiceImpl::QQmlObjectData &);
+QDataStream &operator>>(QDataStream &, QQmlEngineDebugServiceImpl::QQmlObjectData &);
+QDataStream &operator<<(QDataStream &, const QQmlEngineDebugServiceImpl::QQmlObjectProperty &);
+QDataStream &operator>>(QDataStream &, QQmlEngineDebugServiceImpl::QQmlObjectProperty &);
QT_END_NAMESPACE
-#endif // QQMLENGINEDEBUGSERVICE_P_H
+#endif // QQMLENGINEDEBUGSERVICE_H
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp
new file mode 100644
index 0000000000..f5cc78e77f
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp
@@ -0,0 +1,804 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlnativedebugservice.h"
+
+#include <private/qqmldebugconnector_p.h>
+#include <private/qv4debugging_p.h>
+#include <private/qv8engine_p.h>
+#include <private/qv4engine_p.h>
+#include <private/qv4debugging_p.h>
+#include <private/qv4script_p.h>
+#include <private/qv4string_p.h>
+#include <private/qv4objectiterator_p.h>
+#include <private/qv4identifier_p.h>
+#include <private/qv4runtime_p.h>
+#include <private/qv4isel_moth_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
+
+#include <qqmlengine.h>
+
+#include <QtCore/qjsonarray.h>
+#include <QtCore/qjsondocument.h>
+#include <QtCore/qjsonobject.h>
+#include <QtCore/qjsonvalue.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qpointer.h>
+
+//#define TRACE_PROTOCOL(s) qDebug() << s
+#define TRACE_PROTOCOL(s)
+
+QT_BEGIN_NAMESPACE
+
+class BreakPoint
+{
+public:
+ BreakPoint() : id(-1), lineNumber(-1), enabled(false), ignoreCount(0), hitCount(0) {}
+ bool isValid() const { return lineNumber >= 0 && !fileName.isEmpty(); }
+
+ int id;
+ int lineNumber;
+ QString fileName;
+ bool enabled;
+ QString condition;
+ int ignoreCount;
+
+ int hitCount;
+};
+
+inline uint qHash(const BreakPoint &b, uint seed = 0) Q_DECL_NOTHROW
+{
+ return qHash(b.fileName, seed) ^ b.lineNumber;
+}
+
+inline bool operator==(const BreakPoint &a, const BreakPoint &b)
+{
+ return a.lineNumber == b.lineNumber && a.fileName == b.fileName
+ && a.enabled == b.enabled && a.condition == b.condition
+ && a.ignoreCount == b.ignoreCount;
+}
+
+static void setError(QJsonObject *response, const QString &msg)
+{
+ response->insert(QStringLiteral("type"), QStringLiteral("error"));
+ response->insert(QStringLiteral("msg"), msg);
+}
+
+class NativeDebugger;
+
+class Collector
+{
+public:
+ Collector(QV4::ExecutionEngine *engine)
+ : m_engine(engine), m_anonCount(0)
+ {}
+
+ void collect(QJsonArray *output, const QString &parentIName, const QString &name,
+ const QV4::Value &value);
+
+ bool isExpanded(const QString &iname) const { return m_expanded.contains(iname); }
+
+public:
+ QV4::ExecutionEngine *m_engine;
+ int m_anonCount;
+ QStringList m_expanded;
+};
+
+// Encapsulate Breakpoint handling
+// Could be made per-NativeDebugger (i.e. per execution engine, if needed)
+class BreakPointHandler
+{
+public:
+ BreakPointHandler() : m_haveBreakPoints(false), m_breakOnThrow(true), m_lastBreakpoint(1) {}
+
+ void handleSetBreakpoint(QJsonObject *response, const QJsonObject &arguments);
+ void handleRemoveBreakpoint(QJsonObject *response, const QJsonObject &arguments);
+
+ void removeBreakPoint(int id);
+ void enableBreakPoint(int id, bool onoff);
+
+ void setBreakOnThrow(bool onoff);
+ bool m_haveBreakPoints;
+ bool m_breakOnThrow;
+ int m_lastBreakpoint;
+ QVector<BreakPoint> m_breakPoints;
+};
+
+void BreakPointHandler::handleSetBreakpoint(QJsonObject *response, const QJsonObject &arguments)
+{
+ TRACE_PROTOCOL("SET BREAKPOINT" << arguments);
+ QString type = arguments.value(QStringLiteral("type")).toString();
+
+ QString fileName = arguments.value(QStringLiteral("file")).toString();
+ if (fileName.isEmpty()) {
+ setError(response, QStringLiteral("breakpoint has no file name"));
+ return;
+ }
+
+ int line = arguments.value(QStringLiteral("line")).toInt(-1);
+ if (line < 0) {
+ setError(response, QStringLiteral("breakpoint has an invalid line number"));
+ return;
+ }
+
+ BreakPoint bp;
+ bp.id = m_lastBreakpoint++;
+ bp.fileName = fileName.mid(fileName.lastIndexOf('/') + 1);
+ bp.lineNumber = line;
+ bp.enabled = arguments.value(QStringLiteral("enabled")).toBool(true);
+ bp.condition = arguments.value(QStringLiteral("condition")).toString();
+ bp.ignoreCount = arguments.value(QStringLiteral("ignorecount")).toInt();
+ m_breakPoints.append(bp);
+
+ m_haveBreakPoints = true;
+
+ response->insert(QStringLiteral("type"), type);
+ response->insert(QStringLiteral("breakpoint"), bp.id);
+}
+
+void BreakPointHandler::handleRemoveBreakpoint(QJsonObject *response, const QJsonObject &arguments)
+{
+ int id = arguments.value(QStringLiteral("id")).toInt();
+ removeBreakPoint(id);
+ response->insert(QStringLiteral("id"), id);
+}
+
+class NativeDebugger : public QV4::Debugging::Debugger
+{
+public:
+ NativeDebugger(QQmlNativeDebugServiceImpl *service, QV4::ExecutionEngine *engine);
+
+ void signalEmitted(const QString &signal);
+
+ QV4::ExecutionEngine *engine() const { return m_engine; }
+
+ bool pauseAtNextOpportunity() const Q_DECL_OVERRIDE {
+ return m_pauseRequested
+ || m_service->m_breakHandler->m_haveBreakPoints
+ || m_stepping >= StepOver;
+ }
+
+ void maybeBreakAtInstruction() Q_DECL_OVERRIDE;
+ void enteringFunction() Q_DECL_OVERRIDE;
+ void leavingFunction(const QV4::ReturnedValue &retVal) Q_DECL_OVERRIDE;
+ void aboutToThrow() Q_DECL_OVERRIDE;
+
+ void handleCommand(QJsonObject *response, const QString &cmd, const QJsonObject &arguments);
+
+private:
+ void handleBacktrace(QJsonObject *response, const QJsonObject &arguments);
+ void handleVariables(QJsonObject *response, const QJsonObject &arguments);
+ void handleExpressions(QJsonObject *response, const QJsonObject &arguments);
+
+ void handleDebuggerDeleted(QObject *debugger);
+
+ QV4::ReturnedValue evaluateExpression(QV4::Scope &scope, const QString &expression);
+ bool checkCondition(const QString &expression);
+
+ QStringList breakOnSignals;
+
+ enum Speed {
+ NotStepping = 0,
+ StepOut,
+ StepOver,
+ StepIn,
+ };
+
+ void pauseAndWait();
+ void pause();
+ void handleContinue(QJsonObject *reponse, Speed speed);
+
+ QV4::Function *getFunction() const;
+
+ bool reallyHitTheBreakPoint(const QV4::Function *function, int lineNumber);
+
+ QV4::ExecutionEngine *m_engine;
+ QQmlNativeDebugServiceImpl *m_service;
+ QV4::PersistentValue m_currentContext;
+ Speed m_stepping;
+ bool m_pauseRequested;
+ bool m_runningJob;
+
+ QV4::PersistentValue m_returnedValue;
+};
+
+bool NativeDebugger::checkCondition(const QString &expression)
+{
+ QV4::Scope scope(m_engine);
+ QV4::ReturnedValue result = evaluateExpression(scope, expression);
+ QV4::ScopedValue val(scope, result);
+ return val->booleanValue();
+}
+
+QV4::ReturnedValue NativeDebugger::evaluateExpression(QV4::Scope &scope, const QString &expression)
+{
+ m_runningJob = true;
+
+ QV4::ExecutionContextSaver saver(scope);
+
+ QV4::ExecutionContext *ctx = m_engine->currentContext;
+ m_engine->pushContext(ctx);
+
+ QV4::Script script(ctx, expression);
+ script.strictMode = ctx->d()->strictMode;
+ // In order for property lookups in QML to work, we need to disable fast v4 lookups.
+ // That is a side-effect of inheritContext.
+ script.inheritContext = true;
+ script.parse();
+ QV4::ScopedValue result(scope);
+ if (!m_engine->hasException)
+ result = script.run();
+
+ m_runningJob = false;
+ return result->asReturnedValue();
+}
+
+NativeDebugger::NativeDebugger(QQmlNativeDebugServiceImpl *service, QV4::ExecutionEngine *engine)
+ : m_returnedValue(engine, QV4::Primitive::undefinedValue())
+{
+ m_stepping = NotStepping;
+ m_pauseRequested = false;
+ m_runningJob = false;
+ m_service = service;
+ m_engine = engine;
+ TRACE_PROTOCOL("Creating native debugger");
+}
+
+void NativeDebugger::signalEmitted(const QString &signal)
+{
+ //This function is only called by QQmlBoundSignal
+ //only if there is a slot connected to the signal. Hence, there
+ //is no need for additional check.
+
+ //Parse just the name and remove the class info
+ //Normalize to Lower case.
+ QString signalName = signal.left(signal.indexOf(QLatin1Char('('))).toLower();
+
+ foreach (const QString &signal, breakOnSignals) {
+ if (signal == signalName) {
+ // TODO: pause debugger
+ break;
+ }
+ }
+}
+
+void NativeDebugger::handleCommand(QJsonObject *response, const QString &cmd,
+ const QJsonObject &arguments)
+{
+ if (cmd == QStringLiteral("backtrace"))
+ handleBacktrace(response, arguments);
+ else if (cmd == QStringLiteral("variables"))
+ handleVariables(response, arguments);
+ else if (cmd == QStringLiteral("expressions"))
+ handleExpressions(response, arguments);
+ else if (cmd == QStringLiteral("stepin"))
+ handleContinue(response, StepIn);
+ else if (cmd == QStringLiteral("stepout"))
+ handleContinue(response, StepOut);
+ else if (cmd == QStringLiteral("stepover"))
+ handleContinue(response, StepOver);
+ else if (cmd == QStringLiteral("continue"))
+ handleContinue(response, NotStepping);
+}
+
+static QString encodeContext(QV4::ExecutionContext *executionContext)
+{
+ QByteArray ba;
+ QDataStream ds(&ba, QIODevice::WriteOnly);
+ ds << quintptr(executionContext);
+ return QString::fromLatin1(ba.toHex());
+}
+
+static void decodeContext(const QString &context, QV4::ExecutionContext **executionContext)
+{
+ quintptr rawContext;
+ QDataStream ds(QByteArray::fromHex(context.toLatin1()));
+ ds >> rawContext;
+ *executionContext = reinterpret_cast<QV4::ExecutionContext *>(rawContext);
+}
+
+void NativeDebugger::handleBacktrace(QJsonObject *response, const QJsonObject &arguments)
+{
+ int limit = arguments.value(QStringLiteral("limit")).toInt(0);
+
+ QJsonArray frameArray;
+ QV4::ExecutionContext *executionContext = m_engine->currentContext;
+ for (int i = 0; i < limit && executionContext; ++i) {
+ QV4::Heap::FunctionObject *heapFunctionObject = executionContext->getFunctionObject();
+ if (heapFunctionObject) {
+
+ QJsonObject frame;
+ frame[QStringLiteral("language")] = QStringLiteral("js");
+ frame[QStringLiteral("context")] = encodeContext(executionContext);
+
+ if (QV4::Function *function = heapFunctionObject->function) {
+ if (QV4::Heap::String *functionName = function->name())
+ frame[QStringLiteral("function")] = functionName->toQString();
+ frame[QStringLiteral("file")] = function->sourceFile();
+ }
+ int line = executionContext->d()->lineNumber;
+ frame[QStringLiteral("line")] = (line < 0 ? -line : line);
+
+ frameArray.push_back(frame);
+ }
+
+ executionContext = m_engine->parentContext(executionContext);
+ }
+
+ response->insert(QStringLiteral("frames"), frameArray);
+}
+
+void Collector::collect(QJsonArray *out, const QString &parentIName, const QString &name,
+ const QV4::Value &value)
+{
+ QJsonObject dict;
+ QV4::Scope scope(m_engine);
+
+ QString nonEmptyName = name.isEmpty() ? QString::fromLatin1("@%1").arg(m_anonCount++) : name;
+ QString iname = parentIName + QLatin1Char('.') + nonEmptyName;
+ dict.insert(QStringLiteral("iname"), iname);
+ dict.insert(QStringLiteral("name"), nonEmptyName);
+
+ QV4::ScopedValue typeString(scope, QV4::Runtime::typeofValue(m_engine, value));
+ dict.insert(QStringLiteral("type"), typeString->toQStringNoThrow());
+
+ switch (value.type()) {
+ case QV4::Value::Empty_Type:
+ dict.insert(QStringLiteral("valueencoded"), QStringLiteral("empty"));
+ dict.insert(QStringLiteral("haschild"), false);
+ break;
+ case QV4::Value::Undefined_Type:
+ dict.insert(QStringLiteral("valueencoded"), QStringLiteral("undefined"));
+ dict.insert(QStringLiteral("haschild"), false);
+ break;
+ case QV4::Value::Null_Type:
+ dict.insert(QStringLiteral("type"), QStringLiteral("object"));
+ dict.insert(QStringLiteral("valueencoded"), QStringLiteral("null"));
+ dict.insert(QStringLiteral("haschild"), false);
+ break;
+ case QV4::Value::Boolean_Type:
+ dict.insert(QStringLiteral("value"), value.booleanValue());
+ dict.insert(QStringLiteral("haschild"), false);
+ break;
+ case QV4::Value::Managed_Type:
+ if (const QV4::String *string = value.as<QV4::String>()) {
+ dict.insert(QStringLiteral("value"), string->toQStringNoThrow());
+ dict.insert(QStringLiteral("haschild"), false);
+ dict.insert(QStringLiteral("valueencoded"), QStringLiteral("utf16"));
+ dict.insert(QStringLiteral("quoted"), true);
+ } else if (const QV4::ArrayObject *array = value.as<QV4::ArrayObject>()) {
+ // The size of an array is number of its numerical properties.
+ // We don't consider free form object properties here.
+ const uint n = array->getLength();
+ dict.insert(QStringLiteral("value"), qint64(n));
+ dict.insert(QStringLiteral("valueencoded"), QStringLiteral("itemcount"));
+ dict.insert(QStringLiteral("haschild"), qint64(n));
+ if (isExpanded(iname)) {
+ QJsonArray children;
+ for (uint i = 0; i < n; ++i) {
+ QV4::ReturnedValue v = array->getIndexed(i);
+ QV4::ScopedValue sval(scope, v);
+ collect(&children, iname, QString::number(i), *sval);
+ }
+ dict.insert(QStringLiteral("children"), children);
+ }
+ } else if (const QV4::Object *object = value.as<QV4::Object>()) {
+ QJsonArray children;
+ bool expanded = isExpanded(iname);
+ qint64 numProperties = 0;
+ QV4::ObjectIterator it(scope, object, QV4::ObjectIterator::EnumerableOnly);
+ QV4::ScopedProperty p(scope);
+ QV4::ScopedString name(scope);
+ while (true) {
+ QV4::PropertyAttributes attrs;
+ uint index;
+ it.next(name.getRef(), &index, p, &attrs);
+ if (attrs.isEmpty())
+ break;
+ if (name.getPointer()) {
+ ++numProperties;
+ if (expanded) {
+ if (name.getPointer()) {
+ QV4::Value v = p.property->value;
+ collect(&children, iname, name->toQStringNoThrow(), v);
+ }
+ }
+ }
+ }
+ dict.insert(QStringLiteral("value"), numProperties);
+ dict.insert(QStringLiteral("valueencoded"), QStringLiteral("itemcount"));
+ dict.insert(QStringLiteral("haschild"), numProperties > 0);
+ if (expanded)
+ dict.insert(QStringLiteral("children"), children);
+ }
+ break;
+ case QV4::Value::Integer_Type:
+ dict.insert(QStringLiteral("value"), value.integerValue());
+ dict.insert(QStringLiteral("haschild"), false);
+ break;
+ default: // double
+ dict.insert(QStringLiteral("value"), value.doubleValue());
+ dict.insert(QStringLiteral("haschild"), false);
+ }
+
+ out->append(dict);
+}
+
+void NativeDebugger::handleVariables(QJsonObject *response, const QJsonObject &arguments)
+{
+ TRACE_PROTOCOL("Build variables");
+ QV4::ExecutionContext *executionContext = 0;
+ decodeContext(arguments.value(QStringLiteral("context")).toString(), &executionContext);
+ if (!executionContext) {
+ setError(response, QStringLiteral("No execution context passed"));
+ return;
+ }
+ TRACE_PROTOCOL("Context: " << executionContext);
+
+ QV4::ExecutionEngine *engine = executionContext->d()->engine;
+ if (!engine) {
+ setError(response, QStringLiteral("No execution engine passed"));
+ return;
+ }
+ TRACE_PROTOCOL("Engine: " << engine);
+
+ Collector collector(engine);
+ QJsonArray expanded = arguments.value(QStringLiteral("expanded")).toArray();
+ foreach (const QJsonValue &ex, expanded)
+ collector.m_expanded.append(ex.toString());
+ TRACE_PROTOCOL("Expanded: " << collector.m_expanded);
+
+ QJsonArray output;
+ QV4::Scope scope(engine);
+
+ if (QV4::CallContext *callContext = executionContext->asCallContext()) {
+ QV4::Value thisObject = callContext->thisObject();
+ collector.collect(&output, QString(), QStringLiteral("this"), thisObject);
+ QV4::Identifier *const *variables = callContext->variables();
+ QV4::Identifier *const *formals = callContext->formals();
+ for (unsigned i = 0, ei = callContext->variableCount(); i != ei; ++i) {
+ QString qName;
+ if (QV4::Identifier *name = variables[i])
+ qName = name->string;
+ QV4::Value val = callContext->d()->locals[i];
+ collector.collect(&output, QString(), qName, val);
+ }
+ for (unsigned i = 0, ei = callContext->formalCount(); i != ei; ++i) {
+ QString qName;
+ if (QV4::Identifier *name = formals[i])
+ qName = name->string;
+ QV4::ReturnedValue rval = callContext->argument(i);
+ QV4::ScopedValue sval(scope, rval);
+ collector.collect(&output, QString(), qName, *sval);
+ }
+ }
+
+ response->insert(QStringLiteral("variables"), output);
+}
+
+void NativeDebugger::handleExpressions(QJsonObject *response, const QJsonObject &arguments)
+{
+ TRACE_PROTOCOL("Evaluate expressions");
+ QV4::ExecutionContext *executionContext = 0;
+ decodeContext(arguments.value(QStringLiteral("context")).toString(), &executionContext);
+ if (!executionContext) {
+ setError(response, QStringLiteral("No execution context passed"));
+ return;
+ }
+ TRACE_PROTOCOL("Context: " << executionContext);
+
+ QV4::ExecutionEngine *engine = executionContext->d()->engine;
+ if (!engine) {
+ setError(response, QStringLiteral("No execution engine passed"));
+ return;
+ }
+ TRACE_PROTOCOL("Engines: " << engine << m_engine);
+
+ Collector collector(engine);
+ QJsonArray expanded = arguments.value(QStringLiteral("expanded")).toArray();
+ foreach (const QJsonValue &ex, expanded)
+ collector.m_expanded.append(ex.toString());
+ TRACE_PROTOCOL("Expanded: " << collector.m_expanded);
+
+ QJsonArray output;
+ QV4::Scope scope(engine);
+
+ QJsonArray expressions = arguments.value(QStringLiteral("expressions")).toArray();
+ foreach (const QJsonValue &expr, expressions) {
+ QString expression = expr.toObject().value(QStringLiteral("expression")).toString();
+ QString name = expr.toObject().value(QStringLiteral("name")).toString();
+ TRACE_PROTOCOL("Evaluate expression: " << expression);
+ m_runningJob = true;
+
+ QV4::ReturnedValue eval = evaluateExpression(scope, expression);
+ QV4::ScopedValue result(scope, eval);
+
+ m_runningJob = false;
+ if (result->isUndefined()) {
+ QJsonObject dict;
+ dict[QStringLiteral("name")] = name;
+ dict[QStringLiteral("valueencoded")] = QStringLiteral("undefined");
+ output.append(dict);
+ } else if (result.ptr && result.ptr->_val) {
+ collector.collect(&output, QString(), name, *result);
+ } else {
+ QJsonObject dict;
+ dict[QStringLiteral("name")] = name;
+ dict[QStringLiteral("valueencoded")] = QStringLiteral("notaccessible");
+ output.append(dict);
+ }
+ TRACE_PROTOCOL("EXCEPTION: " << engine->hasException);
+ engine->hasException = false;
+ }
+
+ response->insert(QStringLiteral("expressions"), output);
+}
+
+void BreakPointHandler::removeBreakPoint(int id)
+{
+ for (int i = 0; i != m_breakPoints.size(); ++i) {
+ if (m_breakPoints.at(i).id == id) {
+ m_breakPoints.remove(i);
+ m_haveBreakPoints = !m_breakPoints.isEmpty();
+ return;
+ }
+ }
+}
+
+void BreakPointHandler::enableBreakPoint(int id, bool enabled)
+{
+ m_breakPoints[id].enabled = enabled;
+}
+
+void NativeDebugger::pause()
+{
+ m_pauseRequested = true;
+}
+
+void NativeDebugger::handleContinue(QJsonObject *response, Speed speed)
+{
+ Q_UNUSED(response);
+
+ if (!m_returnedValue.isUndefined())
+ m_returnedValue.set(m_engine, QV4::Encode::undefined());
+
+ m_currentContext.set(m_engine, *m_engine->currentContext);
+ m_stepping = speed;
+}
+
+void NativeDebugger::maybeBreakAtInstruction()
+{
+ if (m_runningJob) // do not re-enter when we're doing a job for the debugger.
+ return;
+
+ if (m_stepping == StepOver) {
+ if (m_currentContext.asManaged()->d() == m_engine->current)
+ pauseAndWait();
+ return;
+ }
+
+ if (m_stepping == StepIn) {
+ pauseAndWait();
+ return;
+ }
+
+ if (m_pauseRequested) { // Serve debugging requests from the agent
+ m_pauseRequested = false;
+ pauseAndWait();
+ return;
+ }
+
+ if (m_service->m_breakHandler->m_haveBreakPoints) {
+ if (QV4::Function *function = getFunction()) {
+ const int lineNumber = m_engine->current->lineNumber;
+ if (reallyHitTheBreakPoint(function, lineNumber))
+ pauseAndWait();
+ }
+ }
+}
+
+void NativeDebugger::enteringFunction()
+{
+ if (m_runningJob)
+ return;
+
+ if (m_stepping == StepIn) {
+ m_currentContext.set(m_engine, *m_engine->currentContext);
+ }
+}
+
+void NativeDebugger::leavingFunction(const QV4::ReturnedValue &retVal)
+{
+ if (m_runningJob)
+ return;
+
+ if (m_stepping != NotStepping && m_currentContext.asManaged()->d() == m_engine->current) {
+ m_currentContext.set(m_engine, *m_engine->parentContext(m_engine->currentContext));
+ m_stepping = StepOver;
+ m_returnedValue.set(m_engine, retVal);
+ }
+}
+
+void NativeDebugger::aboutToThrow()
+{
+ if (!m_service->m_breakHandler->m_breakOnThrow)
+ return;
+
+ if (m_runningJob) // do not re-enter when we're doing a job for the debugger.
+ return;
+
+ QJsonObject event;
+ // TODO: complete this!
+ event.insert(QStringLiteral("event"), QStringLiteral("exception"));
+ m_service->emitAsynchronousMessageToClient(event);
+}
+
+QV4::Function *NativeDebugger::getFunction() const
+{
+ QV4::Scope scope(m_engine);
+ QV4::ExecutionContext *context = m_engine->currentContext;
+ QV4::ScopedFunctionObject function(scope, context->getFunctionObject());
+ if (function)
+ return function->function();
+ else
+ return context->d()->engine->globalCode;
+}
+
+void NativeDebugger::pauseAndWait()
+{
+ QJsonObject event;
+
+ event.insert(QStringLiteral("event"), QStringLiteral("break"));
+ event.insert(QStringLiteral("language"), QStringLiteral("js"));
+ if (QV4::ExecutionContext *executionContext = m_engine->currentContext) {
+ QV4::Heap::FunctionObject *heapFunctionObject = executionContext->getFunctionObject();
+ if (heapFunctionObject) {
+ if (QV4::Function *function = heapFunctionObject->function)
+ event.insert(QStringLiteral("file"), function->sourceFile());
+ int line = executionContext->d()->lineNumber;
+ event.insert(QStringLiteral("line"), (line < 0 ? -line : line));
+ }
+ }
+
+ m_service->emitAsynchronousMessageToClient(event);
+}
+
+bool NativeDebugger::reallyHitTheBreakPoint(const QV4::Function *function, int lineNumber)
+{
+ for (int i = 0, n = m_service->m_breakHandler->m_breakPoints.size(); i != n; ++i) {
+ const BreakPoint &bp = m_service->m_breakHandler->m_breakPoints.at(i);
+ if (bp.lineNumber == lineNumber) {
+ const QString fileName = function->sourceFile();
+ const QString base = fileName.mid(fileName.lastIndexOf('/') + 1);
+ if (bp.fileName.endsWith(base)) {
+ if (bp.condition.isEmpty() || checkCondition(bp.condition)) {
+ BreakPoint &mbp = m_service->m_breakHandler->m_breakPoints[i];
+ ++mbp.hitCount;
+ if (mbp.hitCount > mbp.ignoreCount)
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+QQmlNativeDebugServiceImpl::QQmlNativeDebugServiceImpl(QObject *parent)
+ : QQmlNativeDebugService(1.0, parent)
+{
+ m_breakHandler = new BreakPointHandler;
+}
+
+QQmlNativeDebugServiceImpl::~QQmlNativeDebugServiceImpl()
+{
+ delete m_breakHandler;
+}
+
+void QQmlNativeDebugServiceImpl::engineAboutToBeAdded(QQmlEngine *engine)
+{
+ TRACE_PROTOCOL("Adding engine" << engine);
+ if (engine) {
+ QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
+ TRACE_PROTOCOL("Adding execution engine" << ee);
+ if (ee) {
+ NativeDebugger *debugger = new NativeDebugger(this, ee);
+ ee->iselFactory.reset(new QV4::Moth::ISelFactory);
+ if (state() == Enabled)
+ ee->setDebugger(debugger);
+ m_debuggers.append(QPointer<NativeDebugger>(debugger));
+ }
+ }
+ QQmlDebugService::engineAboutToBeAdded(engine);
+}
+
+void QQmlNativeDebugServiceImpl::engineAboutToBeRemoved(QQmlEngine *engine)
+{
+ TRACE_PROTOCOL("Removing engine" << engine);
+ if (engine) {
+ QV4::ExecutionEngine *executionEngine = QV8Engine::getV4(engine->handle());
+ foreach (NativeDebugger *debugger, m_debuggers) {
+ if (debugger->engine() == executionEngine)
+ m_debuggers.removeAll(debugger);
+ }
+ }
+ QQmlDebugService::engineAboutToBeRemoved(engine);
+}
+
+void QQmlNativeDebugServiceImpl::stateAboutToBeChanged(QQmlDebugService::State state)
+{
+ if (state == Enabled) {
+ foreach (NativeDebugger *debugger, m_debuggers) {
+ QV4::ExecutionEngine *engine = debugger->engine();
+ if (!engine->debugger)
+ engine->setDebugger(debugger);
+ }
+ }
+ QQmlDebugService::stateAboutToBeChanged(state);
+}
+
+void QQmlNativeDebugServiceImpl::messageReceived(const QByteArray &message)
+{
+ TRACE_PROTOCOL("Native message received: " << message);
+ QJsonObject request = QJsonDocument::fromJson(message).object();
+ QJsonObject response;
+ QJsonObject arguments = request.value(QStringLiteral("arguments")).toObject();
+ QString cmd = request.value(QStringLiteral("command")).toString();
+
+ if (cmd == QStringLiteral("setbreakpoint")) {
+ m_breakHandler->handleSetBreakpoint(&response, arguments);
+ } else if (cmd == QStringLiteral("removebreakpoint")) {
+ m_breakHandler->handleRemoveBreakpoint(&response, arguments);
+ } else if (cmd == QStringLiteral("echo")) {
+ response.insert(QStringLiteral("result"), arguments);
+ } else {
+ foreach (NativeDebugger *debugger, m_debuggers)
+ if (debugger)
+ debugger->handleCommand(&response, cmd, arguments);
+ }
+ QJsonDocument doc;
+ doc.setObject(response);
+ QByteArray ba = doc.toJson(QJsonDocument::Compact);
+ TRACE_PROTOCOL("Sending synchronous response:" << ba.constData() << endl);
+ emit messageToClient(s_key, ba);
+}
+
+void QQmlNativeDebugServiceImpl::emitAsynchronousMessageToClient(const QJsonObject &message)
+{
+ QJsonDocument doc;
+ doc.setObject(message);
+ QByteArray ba = doc.toJson(QJsonDocument::Compact);
+ TRACE_PROTOCOL("Sending asynchronous message:" << ba.constData() << endl);
+ emit messageToClient(s_key, ba);
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/debugger/qv4debugservice_p.h b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.h
index f7b38b11b6..9d0780a203 100644
--- a/src/qml/debugger/qv4debugservice_p.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.h
@@ -31,53 +31,62 @@
**
****************************************************************************/
-#ifndef QV4DEBUGSERVICE_P_H
-#define QV4DEBUGSERVICE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qqmlconfigurabledebugservice_p.h"
+#ifndef QQML_NATIVE_DEBUG_SERVICE_H
+#define QQML_NATIVE_DEBUG_SERVICE_H
+
+#include <private/qqmldebugconnector_p.h>
+#include <private/qv4debugging_p.h>
+#include <private/qv8engine_p.h>
+#include <private/qv4engine_p.h>
+#include <private/qv4debugging_p.h>
+#include <private/qv4script_p.h>
+#include <private/qv4string_p.h>
+#include <private/qv4objectiterator_p.h>
+#include <private/qv4identifier_p.h>
+#include <private/qv4runtime_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
+
+#include <QtCore/qjsonarray.h>
+
+#include <qqmlengine.h>
+
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonValue>
+#include <QVector>
+#include <QPointer>
QT_BEGIN_NAMESPACE
-namespace QV4 { struct ExecutionEngine; }
-class QQmlEngine;
-class QV4DebugServicePrivate;
+class NativeDebugger;
+class BreakPointHandler;
+class QQmlDebuggerServiceFactory;
-class QV4DebugService : public QQmlConfigurableDebugService
+class QQmlNativeDebugServiceImpl : public QQmlNativeDebugService
{
- Q_OBJECT
public:
- explicit QV4DebugService(QObject *parent = 0);
- ~QV4DebugService();
+ QQmlNativeDebugServiceImpl(QObject *parent);
+
+ ~QQmlNativeDebugServiceImpl();
- static QV4DebugService *instance();
void engineAboutToBeAdded(QQmlEngine *engine);
void engineAboutToBeRemoved(QQmlEngine *engine);
- void signalEmitted(const QString &signal);
+ void stateAboutToBeChanged(State state);
-protected:
- void messageReceived(const QByteArray &);
- void sendSomethingToSomebody(const char *type, int magicNumber = 1);
+ void messageReceived(const QByteArray &message);
-private:
- void handleV8Request(const QByteArray &payload);
+ void emitAsynchronousMessageToClient(const QJsonObject &message);
private:
- Q_DISABLE_COPY(QV4DebugService)
- Q_DECLARE_PRIVATE(QV4DebugService)
+ friend class QQmlDebuggerServiceFactory;
+ friend class NativeDebugger;
+
+ QList<QPointer<NativeDebugger> > m_debuggers;
+ BreakPointHandler *m_breakHandler;
};
QT_END_NAMESPACE
-#endif // QV4DEBUGSERVICE_P_H
+#endif // QQML_NATIVE_DEBUG_SERVICE_H
diff --git a/src/qml/qml/qqmlwatcher.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp
index 9726b6f3b9..9f9a6eb33b 100644
--- a/src/qml/qml/qqmlwatcher.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp
@@ -31,15 +31,15 @@
**
****************************************************************************/
-#include "qqmlwatcher_p.h"
+#include "qqmlwatcher.h"
#include "qqmlexpression.h"
#include "qqmlcontext.h"
#include "qqml.h"
#include <private/qqmldebugservice_p.h>
-#include "qqmlproperty_p.h"
-#include "qqmlvaluetype_p.h"
+#include <private/qqmlproperty_p.h>
+#include <private/qqmlvaluetype_p.h>
#include <QtCore/qmetaobject.h>
#include <QtCore/qdebug.h>
diff --git a/src/qml/qml/qqmlwatcher_p.h b/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.h
index a7bb3c3418..329aee77d2 100644
--- a/src/qml/qml/qqmlwatcher_p.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.h
@@ -31,8 +31,8 @@
**
****************************************************************************/
-#ifndef QQMLWATCHER_P_H
-#define QQMLWATCHER_P_H
+#ifndef QQMLWATCHER_H
+#define QQMLWATCHER_H
//
// W A R N I N G
@@ -83,4 +83,4 @@ private:
QT_END_NAMESPACE
-#endif // QQMLWATCHER_P_H
+#endif // QQMLWATCHER_H
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
new file mode 100644
index 0000000000..4cca1900de
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
@@ -0,0 +1,474 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4datacollector.h"
+
+#include <private/qv4script_p.h>
+#include <private/qv4string_p.h>
+#include <private/qv4objectiterator_p.h>
+#include <private/qv4identifier_p.h>
+#include <private/qv4runtime_p.h>
+
+#include <QtCore/qjsonarray.h>
+
+QT_BEGIN_NAMESPACE
+
+QV4::CallContext *QV4DataCollector::findContext(QV4::ExecutionEngine *engine, int frame)
+{
+ QV4::ExecutionContext *ctx = engine->currentContext;
+ while (ctx) {
+ QV4::CallContext *cCtxt = ctx->asCallContext();
+ if (cCtxt && cCtxt->d()->function) {
+ if (frame < 1)
+ return cCtxt;
+ --frame;
+ }
+ ctx = engine->parentContext(ctx);
+ }
+
+ return 0;
+}
+
+QV4::Heap::CallContext *QV4DataCollector::findScope(QV4::ExecutionContext *ctxt, int scope)
+{
+ if (!ctxt)
+ return 0;
+
+ QV4::Scope s(ctxt->d()->engine);
+ QV4::ScopedContext ctx(s, ctxt);
+ for (; scope > 0 && ctx; --scope)
+ ctx = ctx->d()->outer;
+
+ return (ctx && ctx->d()) ? ctx->asCallContext()->d() : 0;
+}
+
+QVector<QV4::Heap::ExecutionContext::ContextType> QV4DataCollector::getScopeTypes(
+ QV4::ExecutionEngine *engine, int frame)
+{
+ QVector<QV4::Heap::ExecutionContext::ContextType> types;
+
+ QV4::Scope scope(engine);
+ QV4::CallContext *sctxt = findContext(engine, frame);
+ if (!sctxt || sctxt->d()->type < QV4::Heap::ExecutionContext::Type_QmlContext)
+ return types;
+
+ QV4::ScopedContext it(scope, sctxt);
+ for (; it; it = it->d()->outer)
+ types.append(it->d()->type);
+
+ return types;
+}
+
+
+QV4DataCollector::QV4DataCollector(QV4::ExecutionEngine *engine)
+ : m_engine(engine), m_collectedRefs(Q_NULLPTR)
+{
+ values.set(engine, engine->newArrayObject());
+}
+
+QV4DataCollector::~QV4DataCollector()
+{
+}
+
+void QV4DataCollector::collect(const QV4::ScopedValue &value)
+{
+ if (m_collectedRefs)
+ m_collectedRefs->append(addRef(value));
+}
+
+const QV4::Object *collectProperty(const QV4::ScopedValue &value, QV4::ExecutionEngine *engine,
+ QJsonObject &dict)
+{
+ QV4::Scope scope(engine);
+ QV4::ScopedValue typeString(scope, QV4::Runtime::typeofValue(engine, value));
+ dict.insert(QStringLiteral("type"), typeString->toQStringNoThrow());
+
+ const QLatin1String valueKey("value");
+ switch (value->type()) {
+ case QV4::Value::Empty_Type:
+ Q_ASSERT(!"empty Value encountered");
+ return 0;
+ case QV4::Value::Undefined_Type:
+ dict.insert(valueKey, QJsonValue::Undefined);
+ return 0;
+ case QV4::Value::Null_Type:
+ // "null" is not the correct type, but we leave this in until QtC can deal with "object"
+ dict.insert(QStringLiteral("type"), QStringLiteral("null"));
+ dict.insert(valueKey, QJsonValue::Null);
+ return 0;
+ case QV4::Value::Boolean_Type:
+ dict.insert(valueKey, value->booleanValue());
+ return 0;
+ case QV4::Value::Managed_Type:
+ if (const QV4::String *s = value->as<QV4::String>()) {
+ dict.insert(valueKey, s->toQString());
+ } else if (const QV4::ArrayObject *a = value->as<QV4::ArrayObject>()) {
+ // size of an array is number of its numerical properties; We don't consider free form
+ // object properties here.
+ dict.insert(valueKey, qint64(a->getLength()));
+ return a;
+ } else if (const QV4::Object *o = value->as<QV4::Object>()) {
+ int numProperties = 0;
+ QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
+ QV4::PropertyAttributes attrs;
+ uint index;
+ QV4::ScopedProperty p(scope);
+ QV4::ScopedString name(scope);
+ while (true) {
+ it.next(name.getRef(), &index, p, &attrs);
+ if (attrs.isEmpty())
+ break;
+ else
+ ++numProperties;
+ }
+ dict.insert(valueKey, numProperties);
+ return o;
+ } else {
+ Q_UNREACHABLE();
+ }
+ return 0;
+ case QV4::Value::Integer_Type:
+ dict.insert(valueKey, value->integerValue());
+ return 0;
+ default: // double
+ dict.insert(valueKey, value->doubleValue());
+ return 0;
+ }
+}
+
+QJsonObject QV4DataCollector::lookupRef(Ref ref)
+{
+ QJsonObject dict;
+ if (lookupSpecialRef(ref, &dict))
+ return dict;
+
+ dict.insert(QStringLiteral("handle"), qint64(ref));
+ QV4::Scope scope(engine());
+ QV4::ScopedValue value(scope, getValue(ref));
+
+ if (const QV4::Object *o = collectProperty(value, engine(), dict))
+ dict.insert(QStringLiteral("properties"), collectProperties(o));
+
+ return dict;
+}
+
+QV4DataCollector::Ref QV4DataCollector::addFunctionRef(const QString &functionName)
+{
+ Ref ref = addRef(QV4::Primitive::emptyValue(), false);
+
+ QJsonObject dict;
+ dict.insert(QStringLiteral("handle"), qint64(ref));
+ dict.insert(QStringLiteral("type"), QStringLiteral("function"));
+ dict.insert(QStringLiteral("name"), functionName);
+ specialRefs.insert(ref, dict);
+
+ return ref;
+}
+
+QV4DataCollector::Ref QV4DataCollector::addScriptRef(const QString &scriptName)
+{
+ Ref ref = addRef(QV4::Primitive::emptyValue(), false);
+
+ QJsonObject dict;
+ dict.insert(QStringLiteral("handle"), qint64(ref));
+ dict.insert(QStringLiteral("type"), QStringLiteral("script"));
+ dict.insert(QStringLiteral("name"), scriptName);
+ specialRefs.insert(ref, dict);
+
+ return ref;
+}
+
+void QV4DataCollector::collectScope(QJsonObject *dict, QV4::Debugging::V4Debugger *debugger,
+ int frameNr, int scopeNr)
+{
+ QStringList names;
+
+ Refs refs;
+ if (debugger->state() == QV4::Debugging::V4Debugger::Paused) {
+ RefHolder holder(this, &refs);
+ ArgumentCollectJob argumentsJob(m_engine, this, &names, frameNr, scopeNr);
+ debugger->runInEngine(&argumentsJob);
+ LocalCollectJob localsJob(m_engine, this, &names, frameNr, scopeNr);
+ debugger->runInEngine(&localsJob);
+ }
+
+ QV4::Scope scope(engine());
+ QV4::ScopedObject scopeObject(scope, engine()->newObject());
+
+ Q_ASSERT(names.size() == refs.size());
+ for (int i = 0, ei = refs.size(); i != ei; ++i)
+ scopeObject->put(engine(), names.at(i),
+ QV4::Value::fromReturnedValue(getValue(refs.at(i))));
+
+ Ref scopeObjectRef = addRef(scopeObject);
+ dict->insert(QStringLiteral("ref"), qint64(scopeObjectRef));
+ if (m_collectedRefs)
+ m_collectedRefs->append(scopeObjectRef);
+}
+
+QV4DataCollector::Ref QV4DataCollector::addRef(QV4::Value value, bool deduplicate)
+{
+ class ExceptionStateSaver
+ {
+ quint32 *hasExceptionLoc;
+ quint32 hadException;
+
+ public:
+ ExceptionStateSaver(QV4::ExecutionEngine *engine)
+ : hasExceptionLoc(&engine->hasException)
+ , hadException(false)
+ { std::swap(*hasExceptionLoc, hadException); }
+
+ ~ExceptionStateSaver()
+ { std::swap(*hasExceptionLoc, hadException); }
+ };
+
+ // if we wouldn't do this, the putIndexed won't work.
+ ExceptionStateSaver resetExceptionState(engine());
+ QV4::Scope scope(engine());
+ QV4::ScopedObject array(scope, values.value());
+ if (deduplicate) {
+ for (Ref i = 0; i < array->getLength(); ++i) {
+ if (array->getIndexed(i) == value.rawValue() && !specialRefs.contains(i))
+ return i;
+ }
+ }
+ Ref ref = array->getLength();
+ array->putIndexed(ref, value);
+ Q_ASSERT(array->getLength() - 1 == ref);
+ return ref;
+}
+
+QV4::ReturnedValue QV4DataCollector::getValue(Ref ref)
+{
+ QV4::Scope scope(engine());
+ QV4::ScopedObject array(scope, values.value());
+ Q_ASSERT(ref < array->getLength());
+ return array->getIndexed(ref, Q_NULLPTR);
+}
+
+bool QV4DataCollector::lookupSpecialRef(Ref ref, QJsonObject *dict)
+{
+ SpecialRefs::const_iterator it = specialRefs.find(ref);
+ if (it == specialRefs.end())
+ return false;
+
+ *dict = it.value();
+ return true;
+}
+
+QJsonArray QV4DataCollector::collectProperties(const QV4::Object *object)
+{
+ QJsonArray res;
+
+ QV4::Scope scope(engine());
+ QV4::ObjectIterator it(scope, object, QV4::ObjectIterator::EnumerableOnly);
+ QV4::ScopedValue name(scope);
+ QV4::ScopedValue value(scope);
+ while (true) {
+ QV4::Value v;
+ name = it.nextPropertyNameAsString(&v);
+ if (name->isNull())
+ break;
+ QString key = name->toQStringNoThrow();
+ value = v;
+ res.append(collectAsJson(key, value));
+ }
+
+ return res;
+}
+
+QJsonObject QV4DataCollector::collectAsJson(const QString &name, const QV4::ScopedValue &value)
+{
+ QJsonObject dict;
+ if (!name.isNull())
+ dict.insert(QStringLiteral("name"), name);
+ if (value->isManaged() && !value->isString()) {
+ Ref ref = addRef(value);
+ dict.insert(QStringLiteral("ref"), qint64(ref));
+ if (m_collectedRefs)
+ m_collectedRefs->append(ref);
+ }
+
+ collectProperty(value, engine(), dict);
+ return dict;
+}
+
+ExpressionEvalJob::ExpressionEvalJob(QV4::ExecutionEngine *engine, int frameNr,
+ const QString &expression,
+ QV4DataCollector *collector)
+ : JavaScriptJob(engine, frameNr, expression)
+ , collector(collector)
+{
+}
+
+void ExpressionEvalJob::handleResult(QV4::ScopedValue &result)
+{
+ if (hasExeption())
+ exception = result->toQStringNoThrow();
+ collector->collect(result);
+}
+
+const QString &ExpressionEvalJob::exceptionMessage() const
+{
+ return exception;
+}
+
+GatherSourcesJob::GatherSourcesJob(QV4::ExecutionEngine *engine, int seq)
+ : engine(engine)
+ , seq(seq)
+{}
+
+void GatherSourcesJob::run()
+{
+ QStringList sources;
+
+ foreach (QV4::CompiledData::CompilationUnit *unit, engine->compilationUnits) {
+ QString fileName = unit->fileName();
+ if (!fileName.isEmpty())
+ sources.append(fileName);
+ }
+
+ QV4::Debugging::V4Debugger *debugger
+ = static_cast<QV4::Debugging::V4Debugger *>(engine->debugger);
+ emit debugger->sourcesCollected(debugger, sources, seq);
+}
+
+ArgumentCollectJob::ArgumentCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector,
+ QStringList *names, int frameNr, int scopeNr)
+ : engine(engine)
+ , collector(collector)
+ , names(names)
+ , frameNr(frameNr)
+ , scopeNr(scopeNr)
+{}
+
+void ArgumentCollectJob::run()
+{
+ if (frameNr < 0)
+ return;
+
+ QV4::Scope scope(engine);
+ QV4::Scoped<QV4::CallContext> ctxt(
+ scope, QV4DataCollector::findScope(QV4DataCollector::findContext(engine, frameNr), scopeNr));
+ if (!ctxt)
+ return;
+
+ QV4::ScopedValue v(scope);
+ int nFormals = ctxt->formalCount();
+ for (unsigned i = 0, ei = nFormals; i != ei; ++i) {
+ QString qName;
+ if (QV4::Identifier *name = ctxt->formals()[nFormals - i - 1])
+ qName = name->string;
+ names->append(qName);
+ v = ctxt->argument(i);
+ collector->collect(v);
+ }
+}
+
+LocalCollectJob::LocalCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector,
+ QStringList *names, int frameNr, int scopeNr)
+ : engine(engine)
+ , collector(collector)
+ , names(names)
+ , frameNr(frameNr)
+ , scopeNr(scopeNr)
+{}
+
+void LocalCollectJob::run()
+{
+ if (frameNr < 0)
+ return;
+
+ QV4::Scope scope(engine);
+ QV4::Scoped<QV4::CallContext> ctxt(
+ scope, QV4DataCollector::findScope(QV4DataCollector::findContext(engine, frameNr), scopeNr));
+ if (!ctxt)
+ return;
+
+ QV4::ScopedValue v(scope);
+ for (unsigned i = 0, ei = ctxt->variableCount(); i != ei; ++i) {
+ QString qName;
+ if (QV4::Identifier *name = ctxt->variables()[i])
+ qName = name->string;
+ names->append(qName);
+ v = ctxt->d()->locals[i];
+ collector->collect(v);
+ }
+}
+
+ThisCollectJob::ThisCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector,
+ int frameNr, bool *foundThis)
+ : engine(engine)
+ , collector(collector)
+ , frameNr(frameNr)
+ , foundThis(foundThis)
+{}
+
+void ThisCollectJob::run()
+{
+ *foundThis = myRun();
+}
+
+bool ThisCollectJob::myRun()
+{
+ QV4::Scope scope(engine);
+ QV4::ScopedContext ctxt(scope, QV4DataCollector::findContext(engine, frameNr));
+ while (ctxt) {
+ if (QV4::CallContext *cCtxt = ctxt->asCallContext())
+ if (cCtxt->d()->activation)
+ break;
+ ctxt = ctxt->d()->outer;
+ }
+
+ if (!ctxt)
+ return false;
+
+ QV4::ScopedValue o(scope, ctxt->asCallContext()->d()->activation);
+ collector->collect(o);
+ return true;
+}
+
+ExceptionCollectJob::ExceptionCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector)
+ : engine(engine)
+ , collector(collector)
+{}
+
+void ExceptionCollectJob::run()
+{
+ QV4::Scope scope(engine);
+ QV4::ScopedValue v(scope, *engine->exceptionValue);
+ collector->collect(v);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
new file mode 100644
index 0000000000..d0e4a4ad18
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4DATACOLLECTOR_H
+#define QV4DATACOLLECTOR_H
+
+#include <private/qv4engine_p.h>
+#include <private/qv4debugging_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV4DataCollector
+{
+public:
+ typedef uint Ref;
+ typedef QVector<uint> Refs;
+
+ static QV4::CallContext *findContext(QV4::ExecutionEngine *engine, int frame);
+ static QV4::Heap::CallContext *findScope(QV4::ExecutionContext *ctxt, int scope);
+ static QVector<QV4::Heap::ExecutionContext::ContextType> getScopeTypes(
+ QV4::ExecutionEngine *engine, int frame);
+
+ QV4DataCollector(QV4::ExecutionEngine *engine);
+ ~QV4DataCollector();
+
+ void collect(const QV4::ScopedValue &value);
+
+ QJsonObject lookupRef(Ref ref);
+
+ Ref addFunctionRef(const QString &functionName);
+ Ref addScriptRef(const QString &scriptName);
+
+ void collectScope(QJsonObject *dict, QV4::Debugging::V4Debugger *debugger, int frameNr,
+ int scopeNr);
+
+ QV4::ExecutionEngine *engine() const { return m_engine; }
+
+private:
+ friend class RefHolder;
+
+ Ref addRef(QV4::Value value, bool deduplicate = true);
+ QV4::ReturnedValue getValue(Ref ref);
+ bool lookupSpecialRef(Ref ref, QJsonObject *dict);
+
+ QJsonArray collectProperties(const QV4::Object *object);
+ QJsonObject collectAsJson(const QString &name, const QV4::ScopedValue &value);
+ void collectArgumentsInContext();
+
+ QV4::ExecutionEngine *m_engine;
+ Refs *m_collectedRefs;
+ QV4::PersistentValue values;
+ typedef QHash<Ref, QJsonObject> SpecialRefs;
+ SpecialRefs specialRefs;
+};
+
+class RefHolder {
+public:
+ RefHolder(QV4DataCollector *collector, QV4DataCollector::Refs *target) :
+ m_collector(collector), m_previousRefs(collector->m_collectedRefs)
+ {
+ m_collector->m_collectedRefs = target;
+ }
+
+ ~RefHolder()
+ {
+ std::swap(m_collector->m_collectedRefs, m_previousRefs);
+ }
+
+private:
+ QV4DataCollector *m_collector;
+ QV4DataCollector::Refs *m_previousRefs;
+};
+
+class ExpressionEvalJob: public QV4::Debugging::V4Debugger::JavaScriptJob
+{
+ QV4DataCollector *collector;
+ QString exception;
+
+public:
+ ExpressionEvalJob(QV4::ExecutionEngine *engine, int frameNr, const QString &expression,
+ QV4DataCollector *collector);
+ virtual void handleResult(QV4::ScopedValue &result);
+ const QString &exceptionMessage() const;
+};
+
+class GatherSourcesJob: public QV4::Debugging::V4Debugger::Job
+{
+ QV4::ExecutionEngine *engine;
+ const int seq;
+
+public:
+ GatherSourcesJob(QV4::ExecutionEngine *engine, int seq);
+ void run();
+};
+
+class ArgumentCollectJob: public QV4::Debugging::V4Debugger::Job
+{
+ QV4::ExecutionEngine *engine;
+ QV4DataCollector *collector;
+ QStringList *names;
+ int frameNr;
+ int scopeNr;
+
+public:
+ ArgumentCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector,
+ QStringList *names, int frameNr, int scopeNr);
+ void run();
+};
+
+class LocalCollectJob: public QV4::Debugging::V4Debugger::Job
+{
+ QV4::ExecutionEngine *engine;
+ QV4DataCollector *collector;
+ QStringList *names;
+ int frameNr;
+ int scopeNr;
+
+public:
+ LocalCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector, QStringList *names,
+ int frameNr, int scopeNr);
+ void run();
+};
+
+class ThisCollectJob: public QV4::Debugging::V4Debugger::Job
+{
+ QV4::ExecutionEngine *engine;
+ QV4DataCollector *collector;
+ int frameNr;
+ bool *foundThis;
+
+public:
+ ThisCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector, int frameNr,
+ bool *foundThis);
+ void run();
+ bool myRun();
+};
+
+class ExceptionCollectJob: public QV4::Debugging::V4Debugger::Job
+{
+ QV4::ExecutionEngine *engine;
+ QV4DataCollector *collector;
+
+public:
+ ExceptionCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector);
+ void run();
+};
+
+QT_END_NAMESPACE
+
+#endif // QV4DATACOLLECTOR_H
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp
new file mode 100644
index 0000000000..e33595c629
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4debuggeragent.h"
+#include "qv4debugservice.h"
+#include "qv4datacollector.h"
+
+#include <QtCore/qjsonobject.h>
+#include <QtCore/qjsonarray.h>
+
+QT_BEGIN_NAMESPACE
+
+QV4DebuggerAgent::QV4DebuggerAgent(QV4DebugServiceImpl *debugService)
+ : m_breakOnThrow(false), m_debugService(debugService)
+{}
+
+QV4::Debugging::V4Debugger *QV4DebuggerAgent::firstDebugger() const
+{
+ // Currently only 1 single engine is supported, so:
+ if (m_debuggers.isEmpty())
+ return 0;
+ else
+ return m_debuggers.first();
+}
+
+bool QV4DebuggerAgent::isRunning() const
+{
+ // Currently only 1 single engine is supported, so:
+ if (QV4::Debugging::V4Debugger *debugger = firstDebugger())
+ return debugger->state() == QV4::Debugging::V4Debugger::Running;
+ else
+ return false;
+}
+
+void QV4DebuggerAgent::debuggerPaused(QV4::Debugging::V4Debugger *debugger,
+ QV4::Debugging::PauseReason reason)
+{
+ Q_UNUSED(reason);
+
+ m_debugService->clearHandles(debugger->engine());
+
+ QJsonObject event, body, script;
+ event.insert(QStringLiteral("type"), QStringLiteral("event"));
+
+ switch (reason) {
+ case QV4::Debugging::Step:
+ case QV4::Debugging::PauseRequest:
+ case QV4::Debugging::BreakPoint: {
+ event.insert(QStringLiteral("event"), QStringLiteral("break"));
+ QVector<QV4::StackFrame> frames = debugger->stackTrace(1);
+ if (frames.isEmpty())
+ break;
+
+ const QV4::StackFrame &topFrame = frames.first();
+ body.insert(QStringLiteral("invocationText"), topFrame.function);
+ body.insert(QStringLiteral("sourceLine"), topFrame.line - 1);
+ if (topFrame.column > 0)
+ body.insert(QStringLiteral("sourceColumn"), topFrame.column);
+ QJsonArray breakPoints;
+ foreach (int breakPointId, breakPointIds(topFrame.source, topFrame.line))
+ breakPoints.push_back(breakPointId);
+ body.insert(QStringLiteral("breakpoints"), breakPoints);
+ script.insert(QStringLiteral("name"), topFrame.source);
+ } break;
+ case QV4::Debugging::Throwing:
+ // TODO: complete this!
+ event.insert(QStringLiteral("event"), QStringLiteral("exception"));
+ break;
+ }
+
+ if (!script.isEmpty())
+ body.insert(QStringLiteral("script"), script);
+ if (!body.isEmpty())
+ event.insert(QStringLiteral("body"), body);
+ m_debugService->send(event);
+}
+
+void QV4DebuggerAgent::sourcesCollected(QV4::Debugging::V4Debugger *debugger,
+ const QStringList &sources, int requestSequenceNr)
+{
+ QJsonArray body;
+ foreach (const QString &source, sources) {
+ QJsonObject src;
+ src[QLatin1String("name")] = source;
+ src[QLatin1String("scriptType")] = 4;
+ body.append(src);
+ }
+
+ QJsonObject response;
+ response[QLatin1String("success")] = true;
+ response[QLatin1String("running")] = debugger->state() == QV4::Debugging::V4Debugger::Running;
+ response[QLatin1String("body")] = body;
+ response[QLatin1String("command")] = QStringLiteral("scripts");
+ response[QLatin1String("request_seq")] = requestSequenceNr;
+ response[QLatin1String("type")] = QStringLiteral("response");
+ m_debugService->send(response);
+}
+
+void QV4DebuggerAgent::addDebugger(QV4::Debugging::V4Debugger *debugger)
+{
+ Q_ASSERT(!m_debuggers.contains(debugger));
+ m_debuggers << debugger;
+
+ debugger->setBreakOnThrow(m_breakOnThrow);
+
+ foreach (const BreakPoint &breakPoint, m_breakPoints.values())
+ if (breakPoint.enabled)
+ debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
+
+ connect(debugger, SIGNAL(destroyed(QObject*)),
+ this, SLOT(handleDebuggerDeleted(QObject*)));
+ connect(debugger, SIGNAL(sourcesCollected(QV4::Debugging::V4Debugger*,QStringList,int)),
+ this, SLOT(sourcesCollected(QV4::Debugging::V4Debugger*,QStringList,int)),
+ Qt::QueuedConnection);
+ connect(debugger,
+ SIGNAL(debuggerPaused(QV4::Debugging::V4Debugger*,QV4::Debugging::PauseReason)),
+ this, SLOT(debuggerPaused(QV4::Debugging::V4Debugger*,QV4::Debugging::PauseReason)),
+ Qt::QueuedConnection);
+}
+
+void QV4DebuggerAgent::removeDebugger(QV4::Debugging::V4Debugger *debugger)
+{
+ m_debuggers.removeAll(debugger);
+ disconnect(debugger, SIGNAL(destroyed(QObject*)),
+ this, SLOT(handleDebuggerDeleted(QObject*)));
+ disconnect(debugger, SIGNAL(sourcesCollected(QV4::Debugging::V4Debugger*,QStringList,int)),
+ this, SLOT(sourcesCollected(QV4::Debugging::V4Debugger*,QStringList,int)));
+ disconnect(debugger,
+ SIGNAL(debuggerPaused(QV4::Debugging::V4Debugger*,QV4::Debugging::PauseReason)),
+ this,
+ SLOT(debuggerPaused(QV4::Debugging::V4Debugger*,QV4::Debugging::PauseReason)));
+}
+
+void QV4DebuggerAgent::handleDebuggerDeleted(QObject *debugger)
+{
+ m_debuggers.removeAll(static_cast<QV4::Debugging::V4Debugger *>(debugger));
+}
+
+void QV4DebuggerAgent::pause(QV4::Debugging::V4Debugger *debugger) const
+{
+ debugger->pause();
+}
+
+void QV4DebuggerAgent::pauseAll() const
+{
+ foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers)
+ pause(debugger);
+}
+
+void QV4DebuggerAgent::resumeAll() const
+{
+ foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers)
+ if (debugger->state() == QV4::Debugging::V4Debugger::Paused)
+ debugger->resume(QV4::Debugging::V4Debugger::FullThrottle);
+}
+
+int QV4DebuggerAgent::addBreakPoint(const QString &fileName, int lineNumber, bool enabled, const QString &condition)
+{
+ if (enabled)
+ foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers)
+ debugger->addBreakPoint(fileName, lineNumber, condition);
+
+ int id = m_breakPoints.size();
+ m_breakPoints.insert(id, BreakPoint(fileName, lineNumber, enabled, condition));
+ return id;
+}
+
+void QV4DebuggerAgent::removeBreakPoint(int id)
+{
+ BreakPoint breakPoint = m_breakPoints.value(id);
+ if (!breakPoint.isValid())
+ return;
+
+ m_breakPoints.remove(id);
+
+ if (breakPoint.enabled)
+ foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers)
+ debugger->removeBreakPoint(breakPoint.fileName, breakPoint.lineNr);
+}
+
+void QV4DebuggerAgent::removeAllBreakPoints()
+{
+ QList<int> ids = m_breakPoints.keys();
+ foreach (int id, ids)
+ removeBreakPoint(id);
+}
+
+void QV4DebuggerAgent::enableBreakPoint(int id, bool onoff)
+{
+ BreakPoint &breakPoint = m_breakPoints[id];
+ if (!breakPoint.isValid() || breakPoint.enabled == onoff)
+ return;
+ breakPoint.enabled = onoff;
+
+ foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers) {
+ if (onoff)
+ debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
+ else
+ debugger->removeBreakPoint(breakPoint.fileName, breakPoint.lineNr);
+ }
+}
+
+QList<int> QV4DebuggerAgent::breakPointIds(const QString &fileName, int lineNumber) const
+{
+ QList<int> ids;
+
+ for (QHash<int, BreakPoint>::const_iterator i = m_breakPoints.begin(), ei = m_breakPoints.end(); i != ei; ++i)
+ if (i->lineNr == lineNumber && fileName.endsWith(i->fileName))
+ ids.push_back(i.key());
+
+ return ids;
+}
+
+void QV4DebuggerAgent::setBreakOnThrow(bool onoff)
+{
+ if (onoff != m_breakOnThrow) {
+ m_breakOnThrow = onoff;
+ foreach (QV4::Debugging::V4Debugger *debugger, m_debuggers)
+ debugger->setBreakOnThrow(onoff);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h
new file mode 100644
index 0000000000..eafb408e7a
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4DEBUGGERAGENT_H
+#define QV4DEBUGGERAGENT_H
+
+#include <private/qv4debugging_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV4DebugServiceImpl;
+
+class QV4DebuggerAgent : public QObject
+{
+ Q_OBJECT
+public:
+ QV4DebuggerAgent(QV4DebugServiceImpl *m_debugService);
+
+ QV4::Debugging::V4Debugger *firstDebugger() const;
+ bool isRunning() const;
+
+ void addDebugger(QV4::Debugging::V4Debugger *debugger);
+ void removeDebugger(QV4::Debugging::V4Debugger *debugger);
+
+ void pause(QV4::Debugging::V4Debugger *debugger) const;
+ void pauseAll() const;
+ void resumeAll() const;
+ int addBreakPoint(const QString &fileName, int lineNumber, bool enabled = true, const QString &condition = QString());
+ void removeBreakPoint(int id);
+ void removeAllBreakPoints();
+ void enableBreakPoint(int id, bool onoff);
+ QList<int> breakPointIds(const QString &fileName, int lineNumber) const;
+
+ bool breakOnThrow() const { return m_breakOnThrow; }
+ void setBreakOnThrow(bool onoff);
+
+public slots:
+ void debuggerPaused(QV4::Debugging::V4Debugger *debugger, QV4::Debugging::PauseReason reason);
+ void sourcesCollected(QV4::Debugging::V4Debugger *debugger, const QStringList &sources,
+ int requestSequenceNr);
+ void handleDebuggerDeleted(QObject *debugger);
+
+private:
+ QList<QV4::Debugging::V4Debugger *> m_debuggers;
+
+ struct BreakPoint {
+ QString fileName;
+ int lineNr;
+ bool enabled;
+ QString condition;
+
+ BreakPoint(): lineNr(-1), enabled(false) {}
+ BreakPoint(const QString &fileName, int lineNr, bool enabled, const QString &condition)
+ : fileName(fileName), lineNr(lineNr), enabled(enabled), condition(condition)
+ {}
+
+ bool isValid() const { return lineNr >= 0 && !fileName.isEmpty(); }
+ };
+
+ QHash<int, BreakPoint> m_breakPoints;
+ bool m_breakOnThrow;
+ QV4DebugServiceImpl *m_debugService;
+};
+
+QT_END_NAMESPACE
+
+#endif // QV4DEBUGGERAGENT_H
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
new file mode 100644
index 0000000000..5233a09992
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
@@ -0,0 +1,931 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4debugservice.h"
+#include "qqmlengine.h"
+#include <private/qv4engine_p.h>
+#include <private/qv4isel_moth_p.h>
+#include <private/qv4function_p.h>
+#include <private/qqmldebugconnector_p.h>
+
+#include <private/qv8engine_p.h>
+
+#include <QtCore/QJsonArray>
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonObject>
+#include <QtCore/QJsonValue>
+
+const char *const V4_CONNECT = "connect";
+const char *const V4_DISCONNECT = "disconnect";
+const char *const V4_BREAK_ON_SIGNAL = "breakonsignal";
+const char *const V4_PAUSE = "interrupt";
+
+#define NO_PROTOCOL_TRACING
+#ifdef NO_PROTOCOL_TRACING
+# define TRACE_PROTOCOL(x)
+#else
+#include <QtCore/QDebug>
+# define TRACE_PROTOCOL(x) x
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class V8CommandHandler;
+class UnknownV8CommandHandler;
+
+int QV4DebugServiceImpl::debuggerIndex = 0;
+int QV4DebugServiceImpl::sequence = 0;
+
+class V8CommandHandler
+{
+public:
+ V8CommandHandler(const QString &command)
+ : cmd(command)
+ {}
+
+ virtual ~V8CommandHandler()
+ {}
+
+ QString command() const { return cmd; }
+
+ void handle(const QJsonObject &request, QV4DebugServiceImpl *s)
+ {
+ TRACE_PROTOCOL(qDebug() << "handling command" << command() << "...");
+
+ req = request;
+ seq = req.value(QStringLiteral("seq"));
+ debugService = s;
+
+ handleRequest();
+ if (!response.isEmpty()) {
+ response[QLatin1String("type")] = QStringLiteral("response");
+ debugService->send(response);
+ }
+
+ debugService = 0;
+ seq = QJsonValue();
+ req = QJsonObject();
+ response = QJsonObject();
+ }
+
+ virtual void handleRequest() = 0;
+
+protected:
+ void addCommand() { response.insert(QStringLiteral("command"), cmd); }
+ void addRequestSequence() { response.insert(QStringLiteral("request_seq"), seq); }
+ void addSuccess(bool success) { response.insert(QStringLiteral("success"), success); }
+ void addBody(const QJsonObject &body)
+ {
+ response.insert(QStringLiteral("body"), body);
+ }
+
+ void addRunning()
+ {
+ response.insert(QStringLiteral("running"), debugService->debuggerAgent.isRunning());
+ }
+
+ void addRefs()
+ {
+ response.insert(QStringLiteral("refs"), debugService->buildRefs());
+ }
+
+ void createErrorResponse(const QString &msg)
+ {
+ QJsonValue command = req.value(QStringLiteral("command"));
+ response.insert(QStringLiteral("command"), command);
+ addRequestSequence();
+ addSuccess(false);
+ addRunning();
+ response.insert(QStringLiteral("message"), msg);
+ }
+
+ int requestSequenceNr() const
+ { return seq.toInt(-1); }
+
+protected:
+ QString cmd;
+ QJsonObject req;
+ QJsonValue seq;
+ QV4DebugServiceImpl *debugService;
+ QJsonObject response;
+};
+
+class UnknownV8CommandHandler: public V8CommandHandler
+{
+public:
+ UnknownV8CommandHandler(): V8CommandHandler(QString()) {}
+
+ virtual void handleRequest()
+ {
+ QString msg = QStringLiteral("unimplemented command \"");
+ msg += req.value(QStringLiteral("command")).toString();
+ msg += QLatin1Char('"');
+ createErrorResponse(msg);
+ }
+};
+
+namespace {
+class V8VersionRequest: public V8CommandHandler
+{
+public:
+ V8VersionRequest(): V8CommandHandler(QStringLiteral("version")) {}
+
+ virtual void handleRequest()
+ {
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ QJsonObject body;
+ body.insert(QStringLiteral("V8Version"),
+ QLatin1String("this is not V8, this is V4 in Qt " QT_VERSION_STR));
+ addBody(body);
+ }
+};
+
+class V8SetBreakPointRequest: public V8CommandHandler
+{
+public:
+ V8SetBreakPointRequest(): V8CommandHandler(QStringLiteral("setbreakpoint")) {}
+
+ virtual void handleRequest()
+ {
+ // decypher the payload:
+ QJsonObject args = req.value(QStringLiteral("arguments")).toObject();
+ if (args.isEmpty())
+ return;
+
+ QString type = args.value(QStringLiteral("type")).toString();
+ if (type != QStringLiteral("scriptRegExp")) {
+ createErrorResponse(QStringLiteral("breakpoint type \"%1\" is not implemented").arg(type));
+ return;
+ }
+
+ QString fileName = args.value(QStringLiteral("target")).toString();
+ if (fileName.isEmpty()) {
+ createErrorResponse(QStringLiteral("breakpoint has no file name"));
+ return;
+ }
+
+ int line = args.value(QStringLiteral("line")).toInt(-1);
+ if (line < 0) {
+ createErrorResponse(QStringLiteral("breakpoint has an invalid line number"));
+ return;
+ }
+
+ bool enabled = args.value(QStringLiteral("enabled")).toBool(true);
+ QString condition = args.value(QStringLiteral("condition")).toString();
+
+ // set the break point:
+ int id = debugService->debuggerAgent.addBreakPoint(fileName, line + 1, enabled, condition);
+
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ QJsonObject body;
+ body.insert(QStringLiteral("type"), type);
+ body.insert(QStringLiteral("breakpoint"), id);
+ // It's undocumented, but V8 sends back an actual_locations array too. However, our
+ // Debugger currently doesn't tell us when it resolved a breakpoint, so we'll leave them
+ // pending until the breakpoint is hit for the first time.
+ addBody(body);
+ }
+};
+
+class V8ClearBreakPointRequest: public V8CommandHandler
+{
+public:
+ V8ClearBreakPointRequest(): V8CommandHandler(QStringLiteral("clearbreakpoint")) {}
+
+ virtual void handleRequest()
+ {
+ // decypher the payload:
+ QJsonObject args = req.value(QStringLiteral("arguments")).toObject();
+ if (args.isEmpty())
+ return;
+
+ int id = args.value(QStringLiteral("breakpoint")).toInt(-1);
+ if (id < 0) {
+ createErrorResponse(QStringLiteral("breakpoint has an invalid number"));
+ return;
+ }
+
+ // remove the break point:
+ debugService->debuggerAgent.removeBreakPoint(id);
+
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ QJsonObject body;
+ body.insert(QStringLiteral("type"), QStringLiteral("scriptRegExp"));
+ body.insert(QStringLiteral("breakpoint"), id);
+ addBody(body);
+ }
+};
+
+class V8BacktraceRequest: public V8CommandHandler
+{
+public:
+ V8BacktraceRequest(): V8CommandHandler(QStringLiteral("backtrace")) {}
+
+ virtual void handleRequest()
+ {
+ // decypher the payload:
+
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+ int fromFrame = arguments.value(QStringLiteral("fromFrame")).toInt(0);
+ int toFrame = arguments.value(QStringLiteral("toFrame")).toInt(fromFrame + 10);
+ // no idea what the bottom property is for, so we'll ignore it.
+
+ QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+
+ QJsonArray frameArray;
+ QVector<QV4::StackFrame> frames = debugger->stackTrace(toFrame);
+ for (int i = fromFrame; i < toFrame && i < frames.size(); ++i)
+ frameArray.push_back(debugService->buildFrame(frames[i], i, debugger));
+
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ QJsonObject body;
+ if (frameArray.isEmpty()) {
+ body.insert(QStringLiteral("totalFrames"), 0);
+ } else {
+ body.insert(QStringLiteral("fromFrame"), fromFrame);
+ body.insert(QStringLiteral("toFrame"), fromFrame + frameArray.size());
+ body.insert(QStringLiteral("frames"), frameArray);
+ }
+ addBody(body);
+ addRefs();
+ }
+};
+
+class V8FrameRequest: public V8CommandHandler
+{
+public:
+ V8FrameRequest(): V8CommandHandler(QStringLiteral("frame")) {}
+
+ virtual void handleRequest()
+ {
+ // decypher the payload:
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+ const int frameNr = arguments.value(QStringLiteral("number")).toInt(
+ debugService->selectedFrame());
+
+ QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+ QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1);
+ if (frameNr < 0 || frameNr >= frames.size()) {
+ createErrorResponse(QStringLiteral("frame command has invalid frame number"));
+ return;
+ }
+
+ debugService->selectFrame(frameNr);
+ QJsonObject frame = debugService->buildFrame(frames[frameNr], frameNr, debugger);
+
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ addBody(frame);
+ addRefs();
+ }
+};
+
+class V8ScopeRequest: public V8CommandHandler
+{
+public:
+ V8ScopeRequest(): V8CommandHandler(QStringLiteral("scope")) {}
+
+ virtual void handleRequest()
+ {
+ // decypher the payload:
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+ const int frameNr = arguments.value(QStringLiteral("frameNumber")).toInt(
+ debugService->selectedFrame());
+ const int scopeNr = arguments.value(QStringLiteral("number")).toInt(0);
+
+ QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+ QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1);
+ if (frameNr < 0 || frameNr >= frames.size()) {
+ createErrorResponse(QStringLiteral("scope command has invalid frame number"));
+ return;
+ }
+ if (scopeNr < 0) {
+ createErrorResponse(QStringLiteral("scope command has invalid scope number"));
+ return;
+ }
+
+ QJsonObject scope = debugService->buildScope(frameNr, scopeNr, debugger);
+
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ addBody(scope);
+ addRefs();
+ }
+};
+
+class V8LookupRequest: public V8CommandHandler
+{
+public:
+ V8LookupRequest(): V8CommandHandler(QStringLiteral("lookup")) {}
+
+ virtual void handleRequest()
+ {
+ // decypher the payload:
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+ QJsonArray handles = arguments.value(QStringLiteral("handles")).toArray();
+
+ QJsonObject body;
+ foreach (const QJsonValue &handle, handles)
+ body[QString::number(handle.toInt())] = debugService->lookup(handle.toInt());
+
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ addBody(body);
+ addRefs();
+ }
+};
+
+class V8ContinueRequest: public V8CommandHandler
+{
+public:
+ V8ContinueRequest(): V8CommandHandler(QStringLiteral("continue")) {}
+
+ virtual void handleRequest()
+ {
+ // decypher the payload:
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+
+ QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+
+ if (arguments.empty()) {
+ debugger->resume(QV4::Debugging::V4Debugger::FullThrottle);
+ } else {
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+ QString stepAction = arguments.value(QStringLiteral("stepaction")).toString();
+ const int stepcount = arguments.value(QStringLiteral("stepcount")).toInt(1);
+ if (stepcount != 1)
+ qWarning() << "Step count other than 1 is not supported.";
+
+ if (stepAction == QStringLiteral("in")) {
+ debugger->resume(QV4::Debugging::V4Debugger::StepIn);
+ } else if (stepAction == QStringLiteral("out")) {
+ debugger->resume(QV4::Debugging::V4Debugger::StepOut);
+ } else if (stepAction == QStringLiteral("next")) {
+ debugger->resume(QV4::Debugging::V4Debugger::StepOver);
+ } else {
+ createErrorResponse(QStringLiteral("continue command has invalid stepaction"));
+ return;
+ }
+ }
+
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ }
+};
+
+class V8DisconnectRequest: public V8CommandHandler
+{
+public:
+ V8DisconnectRequest(): V8CommandHandler(QStringLiteral("disconnect")) {}
+
+ virtual void handleRequest()
+ {
+ debugService->debuggerAgent.removeAllBreakPoints();
+ debugService->debuggerAgent.resumeAll();
+
+ // response:
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ }
+};
+
+class V8SetExceptionBreakRequest: public V8CommandHandler
+{
+public:
+ V8SetExceptionBreakRequest(): V8CommandHandler(QStringLiteral("setexceptionbreak")) {}
+
+ virtual void handleRequest()
+ {
+ bool wasEnabled = debugService->debuggerAgent.breakOnThrow();
+
+ //decypher the payload:
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+ QString type = arguments.value(QStringLiteral("type")).toString();
+ bool enabled = arguments.value(QStringLiteral("number")).toBool(!wasEnabled);
+
+ if (type == QStringLiteral("all")) {
+ // that's fine
+ } else if (type == QStringLiteral("uncaught")) {
+ createErrorResponse(QStringLiteral("breaking only on uncaught exceptions is not supported yet"));
+ return;
+ } else {
+ createErrorResponse(QStringLiteral("invalid type for break on exception"));
+ return;
+ }
+
+ // do it:
+ debugService->debuggerAgent.setBreakOnThrow(enabled);
+
+ QJsonObject body;
+ body[QLatin1String("type")] = type;
+ body[QLatin1String("enabled")] = debugService->debuggerAgent.breakOnThrow();
+
+ // response:
+ addBody(body);
+ addRunning();
+ addSuccess(true);
+ addRequestSequence();
+ addCommand();
+ }
+};
+
+class V8ScriptsRequest: public V8CommandHandler
+{
+public:
+ V8ScriptsRequest(): V8CommandHandler(QStringLiteral("scripts")) {}
+
+ virtual void handleRequest()
+ {
+ //decypher the payload:
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+ int types = arguments.value(QStringLiteral("types")).toInt(-1);
+ if (types < 0 || types > 7) {
+ createErrorResponse(QStringLiteral("invalid types value in scripts command"));
+ return;
+ } else if (types != 4) {
+ createErrorResponse(QStringLiteral("unsupported types value in scripts command"));
+ return;
+ }
+
+ // do it:
+ QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+ GatherSourcesJob job(debugger->engine(), requestSequenceNr());
+ debugger->runInEngine(&job);
+
+ // response will be send by
+ }
+};
+
+// Request:
+// {
+// "seq": 4,
+// "type": "request",
+// "command": "evaluate",
+// "arguments": {
+// "expression": "a",
+// "frame": 0
+// }
+// }
+//
+// Response:
+// {
+// "body": {
+// "handle": 3,
+// "type": "number",
+// "value": 1
+// },
+// "command": "evaluate",
+// "refs": [],
+// "request_seq": 4,
+// "running": false,
+// "seq": 5,
+// "success": true,
+// "type": "response"
+// }
+//
+// The "value" key in "body" is the result of evaluating the expression in the request.
+class V8EvaluateRequest: public V8CommandHandler
+{
+public:
+ V8EvaluateRequest(): V8CommandHandler(QStringLiteral("evaluate")) {}
+
+ virtual void handleRequest()
+ {
+ QV4::Debugging::V4Debugger *debugger = debugService->debuggerAgent.firstDebugger();
+ if (debugger->state() == QV4::Debugging::V4Debugger::Paused) {
+ QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
+ QString expression = arguments.value(QStringLiteral("expression")).toString();
+ const int frame = arguments.value(QStringLiteral("frame")).toInt(0);
+
+ QV4DataCollector *collector = debugService->collector();
+ RefHolder holder(collector, debugService->refs());
+ ExpressionEvalJob job(debugger->engine(), frame, expression, collector);
+ debugger->runInEngine(&job);
+ if (job.hasExeption()) {
+ createErrorResponse(job.exceptionMessage());
+ } else {
+ addCommand();
+ addRequestSequence();
+ addSuccess(true);
+ addRunning();
+ addBody(collector->lookupRef(debugService->refs()->last()));
+ addRefs();
+ }
+ } else {
+ createErrorResponse(QStringLiteral("Debugger has to be paused for evaluate to work."));
+ }
+ }
+};
+} // anonymous namespace
+
+void QV4DebugServiceImpl::addHandler(V8CommandHandler* handler)
+{
+ handlers[handler->command()] = handler;
+}
+
+V8CommandHandler *QV4DebugServiceImpl::v8CommandHandler(const QString &command) const
+{
+ V8CommandHandler *handler = handlers.value(command, 0);
+ if (handler)
+ return handler;
+ else
+ return unknownV8CommandHandler.data();
+}
+
+QV4DebugServiceImpl::QV4DebugServiceImpl(QObject *parent) :
+ QQmlConfigurableDebugService<QV4DebugService>(1, parent),
+ debuggerAgent(this), version(1), theSelectedFrame(0),
+ unknownV8CommandHandler(new UnknownV8CommandHandler)
+{
+ addHandler(new V8VersionRequest);
+ addHandler(new V8SetBreakPointRequest);
+ addHandler(new V8ClearBreakPointRequest);
+ addHandler(new V8BacktraceRequest);
+ addHandler(new V8FrameRequest);
+ addHandler(new V8ScopeRequest);
+ addHandler(new V8LookupRequest);
+ addHandler(new V8ContinueRequest);
+ addHandler(new V8DisconnectRequest);
+ addHandler(new V8SetExceptionBreakRequest);
+ addHandler(new V8ScriptsRequest);
+ addHandler(new V8EvaluateRequest);
+}
+
+QV4DebugServiceImpl::~QV4DebugServiceImpl()
+{
+ qDeleteAll(handlers);
+}
+
+void QV4DebugServiceImpl::engineAboutToBeAdded(QQmlEngine *engine)
+{
+ QMutexLocker lock(&m_configMutex);
+ if (engine) {
+ QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
+ if (QQmlDebugConnector *server = QQmlDebugConnector::instance()) {
+ if (ee) {
+ ee->iselFactory.reset(new QV4::Moth::ISelFactory);
+ QV4::Debugging::V4Debugger *debugger = new QV4::Debugging::V4Debugger(ee);
+ if (state() == Enabled)
+ ee->setDebugger(debugger);
+ debuggerMap.insert(debuggerIndex++, debugger);
+ debuggerAgent.addDebugger(debugger);
+ debuggerAgent.moveToThread(server->thread());
+ }
+ }
+ }
+ QQmlConfigurableDebugService<QV4DebugService>::engineAboutToBeAdded(engine);
+}
+
+void QV4DebugServiceImpl::engineAboutToBeRemoved(QQmlEngine *engine)
+{
+ QMutexLocker lock(&m_configMutex);
+ if (engine){
+ const QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
+ if (ee) {
+ QV4::Debugging::V4Debugger *debugger
+ = qobject_cast<QV4::Debugging::V4Debugger *>(ee->debugger);
+ if (debugger) {
+ typedef QMap<int, QV4::Debugging::V4Debugger *>::const_iterator DebuggerMapIterator;
+ const DebuggerMapIterator end = debuggerMap.constEnd();
+ for (DebuggerMapIterator i = debuggerMap.constBegin(); i != end; ++i) {
+ if (i.value() == debugger) {
+ debuggerMap.remove(i.key());
+ break;
+ }
+ }
+ debuggerAgent.removeDebugger(debugger);
+ }
+ }
+ }
+ QQmlConfigurableDebugService<QV4DebugService>::engineAboutToBeRemoved(engine);
+}
+
+void QV4DebugServiceImpl::stateAboutToBeChanged(State state)
+{
+ QMutexLocker lock(&m_configMutex);
+ if (state == Enabled) {
+ typedef QMap<int, QV4::Debugging::V4Debugger *>::const_iterator DebuggerMapIterator;
+ const DebuggerMapIterator end = debuggerMap.constEnd();
+ for (DebuggerMapIterator i = debuggerMap.constBegin(); i != end; ++i) {
+ QV4::ExecutionEngine *ee = i.value()->engine();
+ if (!ee->debugger)
+ ee->setDebugger(i.value());
+ }
+ }
+ QQmlConfigurableDebugService<QV4DebugService>::stateAboutToBeChanged(state);
+}
+
+void QV4DebugServiceImpl::signalEmitted(const QString &signal)
+{
+ //This function is only called by QQmlBoundSignal
+ //only if there is a slot connected to the signal. Hence, there
+ //is no need for additional check.
+
+ //Parse just the name and remove the class info
+ //Normalize to Lower case.
+ QString signalName = signal.left(signal.indexOf(QLatin1Char('('))).toLower();
+
+ foreach (const QString &signal, breakOnSignals) {
+ if (signal == signalName) {
+ // TODO: pause debugger
+ break;
+ }
+ }
+}
+
+void QV4DebugServiceImpl::messageReceived(const QByteArray &message)
+{
+ QMutexLocker lock(&m_configMutex);
+
+ QQmlDebugStream ms(message);
+ QByteArray header;
+ ms >> header;
+
+ TRACE_PROTOCOL(qDebug() << "received message with header" << header);
+
+ if (header == "V8DEBUG") {
+ QByteArray type;
+ QByteArray payload;
+ ms >> type >> payload;
+ TRACE_PROTOCOL(qDebug() << "... type:" << type);
+
+ if (type == V4_CONNECT) {
+ emit messageToClient(name(), packMessage(type));
+ stopWaiting();
+ } else if (type == V4_PAUSE) {
+ debuggerAgent.pauseAll();
+ sendSomethingToSomebody(type);
+ } else if (type == V4_BREAK_ON_SIGNAL) {
+ QByteArray signal;
+ bool enabled;
+ ms >> signal >> enabled;
+ //Normalize to lower case.
+ QString signalName(QString::fromUtf8(signal).toLower());
+ if (enabled)
+ breakOnSignals.append(signalName);
+ else
+ breakOnSignals.removeOne(signalName);
+ } else if (type == "v8request") {
+ handleV8Request(payload);
+ } else if (type == V4_DISCONNECT) {
+ TRACE_PROTOCOL(qDebug() << "... payload:" << payload.constData());
+ handleV8Request(payload);
+ } else {
+ sendSomethingToSomebody(type, 0);
+ }
+ }
+}
+
+void QV4DebugServiceImpl::sendSomethingToSomebody(const char *type, int magicNumber)
+{
+ QByteArray response;
+ QQmlDebugStream rs(&response, QIODevice::WriteOnly);
+ rs << QByteArray(type)
+ << QByteArray::number(version) << QByteArray::number(magicNumber);
+ emit messageToClient(name(), packMessage(type, response));
+}
+
+void QV4DebugServiceImpl::handleV8Request(const QByteArray &payload)
+{
+ TRACE_PROTOCOL(qDebug() << "v8request, payload:" << payload.constData());
+
+ QJsonDocument request = QJsonDocument::fromJson(payload);
+ QJsonObject o = request.object();
+ QJsonValue type = o.value(QStringLiteral("type"));
+ if (type.toString() == QStringLiteral("request")) {
+ QJsonValue command = o.value(QStringLiteral("command"));
+ V8CommandHandler *h = v8CommandHandler(command.toString());
+ if (h)
+ h->handle(o, this);
+ }
+}
+
+QByteArray QV4DebugServiceImpl::packMessage(const QByteArray &command, const QByteArray &message)
+{
+ QByteArray reply;
+ QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
+ static const QByteArray cmd("V8DEBUG");
+ rs << cmd << command << message;
+ return reply;
+}
+
+void QV4DebugServiceImpl::send(QJsonObject v8Payload)
+{
+ v8Payload[QLatin1String("seq")] = sequence++;
+ QJsonDocument doc;
+ doc.setObject(v8Payload);
+#ifdef NO_PROTOCOL_TRACING
+ QByteArray responseData = doc.toJson(QJsonDocument::Compact);
+#else
+ QByteArray responseData = doc.toJson(QJsonDocument::Indented);
+#endif
+
+ TRACE_PROTOCOL(qDebug() << "sending response for:" << responseData.constData() << endl);
+
+ emit messageToClient(name(), packMessage("v8message", responseData));
+}
+
+void QV4DebugServiceImpl::clearHandles(QV4::ExecutionEngine *engine)
+{
+ theCollector.reset(new QV4DataCollector(engine));
+}
+
+QJsonObject QV4DebugServiceImpl::buildFrame(const QV4::StackFrame &stackFrame, int frameNr,
+ QV4::Debugging::V4Debugger *debugger)
+{
+ QV4DataCollector::Ref ref;
+
+ QJsonObject frame;
+ frame[QLatin1String("index")] = frameNr;
+ frame[QLatin1String("debuggerFrame")] = false;
+ ref = theCollector->addFunctionRef(stackFrame.function);
+ collectedRefs.append(ref);
+ frame[QLatin1String("func")] = toRef(ref);
+ ref = theCollector->addScriptRef(stackFrame.source);
+ collectedRefs.append(ref);
+ frame[QLatin1String("script")] = toRef(ref);
+ frame[QLatin1String("line")] = stackFrame.line - 1;
+ if (stackFrame.column >= 0)
+ frame[QLatin1String("column")] = stackFrame.column;
+
+ QJsonArray scopes;
+ if (debugger->state() == QV4::Debugging::V4Debugger::Paused) {
+ RefHolder holder(theCollector.data(), &collectedRefs);
+ bool foundThis = false;
+ ThisCollectJob job(debugger->engine(), theCollector.data(), frameNr, &foundThis);
+ debugger->runInEngine(&job);
+ if (foundThis)
+ frame[QLatin1String("receiver")] = toRef(collectedRefs.last());
+
+ // Only type and index are used by Qt Creator, so we keep it easy:
+ QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes =
+ QV4DataCollector::getScopeTypes(debugger->engine(), frameNr);
+ for (int i = 0, ei = scopeTypes.count(); i != ei; ++i) {
+ int type = encodeScopeType(scopeTypes[i]);
+ if (type == -1)
+ continue;
+
+ QJsonObject scope;
+ scope[QLatin1String("index")] = i;
+ scope[QLatin1String("type")] = type;
+ scopes.push_back(scope);
+ }
+ }
+ frame[QLatin1String("scopes")] = scopes;
+
+ return frame;
+}
+
+int QV4DebugServiceImpl::encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType)
+{
+ switch (scopeType) {
+ case QV4::Heap::ExecutionContext::Type_GlobalContext:
+ return 0;
+ break;
+ case QV4::Heap::ExecutionContext::Type_CatchContext:
+ return 4;
+ break;
+ case QV4::Heap::ExecutionContext::Type_WithContext:
+ return 2;
+ break;
+ case QV4::Heap::ExecutionContext::Type_SimpleCallContext:
+ case QV4::Heap::ExecutionContext::Type_CallContext:
+ return 1;
+ break;
+ case QV4::Heap::ExecutionContext::Type_QmlContext:
+ default:
+ return -1;
+ }
+}
+
+QJsonObject QV4DebugServiceImpl::buildScope(int frameNr, int scopeNr,
+ QV4::Debugging::V4Debugger *debugger)
+{
+ QJsonObject scope;
+
+ QJsonObject object;
+ RefHolder holder(theCollector.data(), &collectedRefs);
+ theCollector->collectScope(&object, debugger, frameNr, scopeNr);
+
+ if (debugger->state() == QV4::Debugging::V4Debugger::Paused) {
+ QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes =
+ QV4DataCollector::getScopeTypes(debugger->engine(), frameNr);
+ scope[QLatin1String("type")] = encodeScopeType(scopeTypes[scopeNr]);
+ } else {
+ scope[QLatin1String("type")] = -1;
+ }
+ scope[QLatin1String("index")] = scopeNr;
+ scope[QLatin1String("frameIndex")] = frameNr;
+ scope[QLatin1String("object")] = object;
+
+ return scope;
+}
+
+QJsonValue QV4DebugServiceImpl::lookup(QV4DataCollector::Ref refId)
+{
+ RefHolder holder(theCollector.data(), &collectedRefs);
+ return theCollector->lookupRef(refId);
+}
+
+QJsonArray QV4DebugServiceImpl::buildRefs()
+{
+ QJsonArray refs;
+ std::sort(collectedRefs.begin(), collectedRefs.end());
+ for (int i = 0, ei = collectedRefs.size(); i != ei; ++i) {
+ QV4DataCollector::Ref ref = collectedRefs.at(i);
+ if (i > 0 && ref == collectedRefs.at(i - 1))
+ continue;
+ refs.append(lookup(ref));
+ }
+
+ collectedRefs.clear();
+ return refs;
+}
+
+QJsonValue QV4DebugServiceImpl::toRef(QV4DataCollector::Ref ref)
+{
+ QJsonObject dict;
+ dict.insert(QStringLiteral("ref"), qint64(ref));
+ return dict;
+}
+
+QV4DataCollector *QV4DebugServiceImpl::collector() const
+{
+ return theCollector.data();
+}
+
+QV4DataCollector::Refs *QV4DebugServiceImpl::refs()
+{
+ return &collectedRefs;
+}
+
+void QV4DebugServiceImpl::selectFrame(int frameNr)
+{
+ theSelectedFrame = frameNr;
+}
+
+int QV4DebugServiceImpl::selectedFrame() const
+{
+ return theSelectedFrame;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h
new file mode 100644
index 0000000000..273e5ffd62
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4DEBUGSERVICE_H
+#define QV4DEBUGSERVICE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qqmlconfigurabledebugservice.h"
+#include "qv4debuggeragent.h"
+#include "qv4datacollector.h"
+#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qv4debugging_p.h>
+
+#include <QtCore/QJsonValue>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 { struct ExecutionEngine; }
+
+class QQmlEngine;
+class VariableCollector;
+class V8CommandHandler;
+class UnknownV8CommandHandler;
+class QV4DebugServiceImpl;
+
+class QV4DebugServiceImpl : public QQmlConfigurableDebugService<QV4DebugService>
+{
+ Q_OBJECT
+public:
+ explicit QV4DebugServiceImpl(QObject *parent = 0);
+ ~QV4DebugServiceImpl();
+
+ void engineAboutToBeAdded(QQmlEngine *engine);
+ void engineAboutToBeRemoved(QQmlEngine *engine);
+
+ void stateAboutToBeChanged(State state);
+
+ void signalEmitted(const QString &signal);
+ void send(QJsonObject v8Payload);
+
+ QJsonObject buildScope(int frameNr, int scopeNr, QV4::Debugging::V4Debugger *debugger);
+ QJsonArray buildRefs();
+ QJsonValue lookup(QV4DataCollector::Ref refId);
+ QJsonValue toRef(QV4DataCollector::Ref ref);
+
+ QJsonObject buildFrame(const QV4::StackFrame &stackFrame, int frameNr,
+ QV4::Debugging::V4Debugger *debugger);
+ int selectedFrame() const;
+ void selectFrame(int frameNr);
+
+ void clearHandles(QV4::ExecutionEngine *engine);
+
+ QV4DataCollector *collector() const;
+ QV4DebuggerAgent debuggerAgent;
+ QV4DataCollector::Refs *refs();
+
+protected:
+ void messageReceived(const QByteArray &);
+ void sendSomethingToSomebody(const char *type, int magicNumber = 1);
+
+private:
+ friend class QQmlDebuggerServiceFactory;
+
+ void handleV8Request(const QByteArray &payload);
+ static QByteArray packMessage(const QByteArray &command,
+ const QByteArray &message = QByteArray());
+ void processCommand(const QByteArray &command, const QByteArray &data);
+ V8CommandHandler *v8CommandHandler(const QString &command) const;
+ int encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType);
+
+ QStringList breakOnSignals;
+ QMap<int, QV4::Debugging::V4Debugger *> debuggerMap;
+ static int debuggerIndex;
+ static int sequence;
+ const int version;
+ QV4DataCollector::Refs collectedRefs;
+
+ QScopedPointer<QV4DataCollector> theCollector;
+ int theSelectedFrame;
+
+ void addHandler(V8CommandHandler* handler);
+ QHash<QString, V8CommandHandler*> handlers;
+ QScopedPointer<UnknownV8CommandHandler> unknownV8CommandHandler;
+};
+
+QT_END_NAMESPACE
+
+#endif // QV4DEBUGSERVICE_H
diff --git a/src/plugins/qmltooling/shared/abstracttool.cpp b/src/plugins/qmltooling/qmldbg_inspector/abstracttool.cpp
index 990bc704b9..3e059bed13 100644
--- a/src/plugins/qmltooling/shared/abstracttool.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/abstracttool.cpp
@@ -35,6 +35,8 @@
#include "abstractviewinspector.h"
+QT_BEGIN_NAMESPACE
+
namespace QmlJSDebugger {
AbstractTool::AbstractTool(AbstractViewInspector *inspector) :
@@ -44,3 +46,5 @@ AbstractTool::AbstractTool(AbstractViewInspector *inspector) :
}
} // namespace QmlJSDebugger
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/shared/abstracttool.h b/src/plugins/qmltooling/qmldbg_inspector/abstracttool.h
index 85f2b5b9ad..c796925866 100644
--- a/src/plugins/qmltooling/shared/abstracttool.h
+++ b/src/plugins/qmltooling/qmldbg_inspector/abstracttool.h
@@ -41,7 +41,6 @@ class QMouseEvent;
class QKeyEvent;
class QWheelEvent;
class QTouchEvent;
-QT_END_NAMESPACE
namespace QmlJSDebugger {
@@ -81,4 +80,6 @@ private:
} // namespace QmlJSDebugger
+QT_END_NAMESPACE
+
#endif // ABSTRACTTOOL_H
diff --git a/src/plugins/qmltooling/shared/abstractviewinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp
index e718cf022f..fa6dca7aca 100644
--- a/src/plugins/qmltooling/shared/abstractviewinspector.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp
@@ -32,14 +32,13 @@
****************************************************************************/
#include "abstractviewinspector.h"
-
#include "abstracttool.h"
#include <QtCore/QDebug>
#include <QtQml/QQmlEngine>
#include <QtQml/QQmlComponent>
#include <QtCore/private/qabstractanimation_p.h>
-#include <QtQml/private/qqmlinspectorservice_p.h>
+#include <QtQml/private/qqmldebugconnector_p.h>
#include <QtQml/private/qqmlcontext_p.h>
#include <QtGui/QMouseEvent>
@@ -61,6 +60,8 @@
// clearCache: void
// Response for "destroyObject" carries the <debugId_int> of the destroyed object.
+QT_BEGIN_NAMESPACE
+
const char REQUEST[] = "request";
const char RESPONSE[] = "response";
const char EVENT[] = "event";
@@ -78,10 +79,10 @@ const char CLEAR_CACHE[] = "clearCache";
namespace QmlJSDebugger {
-AbstractViewInspector::AbstractViewInspector(QObject *parent) :
+AbstractViewInspector::AbstractViewInspector(QQmlDebugService *service, QObject *parent) :
QObject(parent),
m_enabled(false),
- m_debugService(QQmlInspectorService::instance()),
+ m_debugService(service),
m_eventId(0),
m_reloadEventId(-1)
{
@@ -260,14 +261,13 @@ void AbstractViewInspector::onQmlObjectDestroyed(QObject *object)
return;
QPair<int, int> ids = m_hashObjectsTobeDestroyed.take(object);
- QQmlDebugService::removeInvalidObjectsFromHash();
QByteArray response;
QQmlDebugStream rs(&response, QIODevice::WriteOnly);
rs << QByteArray(RESPONSE) << ids.first << true << ids.second;
- m_debugService->sendMessage(response);
+ emit m_debugService->messageToClient(m_debugService->name(), response);
}
void AbstractViewInspector::handleMessage(const QByteArray &message)
@@ -361,7 +361,7 @@ void AbstractViewInspector::handleMessage(const QByteArray &message)
QByteArray response;
QQmlDebugStream rs(&response, QIODevice::WriteOnly);
rs << QByteArray(RESPONSE) << requestId << success;
- m_debugService->sendMessage(response);
+ emit m_debugService->messageToClient(m_debugService->name(), response);
}
void AbstractViewInspector::sendCurrentObjects(const QList<QObject*> &objects)
@@ -372,11 +372,12 @@ void AbstractViewInspector::sendCurrentObjects(const QList<QObject*> &objects)
ds << QByteArray(EVENT) << m_eventId++ << QByteArray(SELECT);
QList<int> debugIds;
+ debugIds.reserve(objects.count());
foreach (QObject *object, objects)
debugIds << QQmlDebugService::idForObject(object);
ds << debugIds;
- m_debugService->sendMessage(message);
+ emit m_debugService->messageToClient(m_debugService->name(), message);
}
void AbstractViewInspector::sendQmlFileReloaded(bool success)
@@ -389,7 +390,7 @@ void AbstractViewInspector::sendQmlFileReloaded(bool success)
QQmlDebugStream rs(&response, QIODevice::WriteOnly);
rs << QByteArray(RESPONSE) << m_reloadEventId << success;
- m_debugService->sendMessage(response);
+ emit m_debugService->messageToClient(m_debugService->name(), response);
}
QString AbstractViewInspector::idStringForObject(QObject *obj) const
@@ -414,3 +415,5 @@ void AbstractViewInspector::removeTool(AbstractTool *tool)
}
} // namespace QmlJSDebugger
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/shared/abstractviewinspector.h b/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.h
index 02b4247bec..8f7ad4ac5b 100644
--- a/src/plugins/qmltooling/shared/abstractviewinspector.h
+++ b/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.h
@@ -38,18 +38,14 @@
#include <QtCore/QObject>
#include <QtCore/QStringList>
-#include "qmlinspectorconstants.h"
-
QT_BEGIN_NAMESPACE
class QQmlEngine;
-class QQmlInspectorService;
+class QQmlDebugService;
class QKeyEvent;
class QMouseEvent;
class QWheelEvent;
class QTouchEvent;
-QT_END_NAMESPACE
-
namespace QmlJSDebugger {
class AbstractTool;
@@ -62,7 +58,7 @@ class AbstractViewInspector : public QObject
Q_OBJECT
public:
- explicit AbstractViewInspector(QObject *parent = 0);
+ explicit AbstractViewInspector(QQmlDebugService *service, QObject *parent = 0);
void handleMessage(const QByteArray &message);
@@ -115,7 +111,7 @@ private:
bool m_enabled;
- QQmlInspectorService *m_debugService;
+ QQmlDebugService *m_debugService;
QList<AbstractTool *> m_tools;
int m_eventId;
int m_reloadEventId;
@@ -125,4 +121,6 @@ private:
} // namespace QmlJSDebugger
+QT_END_NAMESPACE
+
#endif // ABSTRACTVIEWINSPECTOR_H
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/highlight.cpp b/src/plugins/qmltooling/qmldbg_inspector/highlight.cpp
index 5af7a225fd..4d4e3aa720 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/highlight.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/highlight.cpp
@@ -38,8 +38,9 @@
#include <QtGui/QStaticText>
#include <QtQuick/QQuickWindow>
+QT_BEGIN_NAMESPACE
+
namespace QmlJSDebugger {
-namespace QtQuick2 {
Highlight::Highlight(QQuickItem *parent) : QQuickPaintedItem(parent)
{
@@ -193,5 +194,6 @@ void SelectionHighlight::disableNameDisplay()
update();
}
-} // namespace QtQuick2
} // namespace QmlJSDebugger
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/highlight.h b/src/plugins/qmltooling/qmldbg_inspector/highlight.h
index 29d2f0d911..05f6382353 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/highlight.h
+++ b/src/plugins/qmltooling/qmldbg_inspector/highlight.h
@@ -39,9 +39,9 @@
#include <QtGui/QTransform>
#include <QtQuick/QQuickPaintedItem>
+QT_BEGIN_NAMESPACE
namespace QmlJSDebugger {
-namespace QtQuick2 {
class Highlight : public QQuickPaintedItem
{
@@ -104,7 +104,8 @@ public:
void paint(QPainter *painter);
};
-} // namespace QtQuick2
} // namespace QmlJSDebugger
+QT_END_NAMESPACE
+
#endif // HIGHLIGHT_H
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.cpp b/src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp
index f86225fa0a..cc6b4ffb8c 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/inspecttool.cpp
@@ -48,8 +48,12 @@
#include <QtQuick/QQuickView>
#include <QtQuick/QQuickItem>
+QT_BEGIN_NAMESPACE
+
namespace QmlJSDebugger {
-namespace QtQuick2 {
+
+static const double ZoomSnapDelta = 0.04;
+static const int PressAndHoldTimeout = 800;
InspectTool::InspectTool(QQuickViewInspector *inspector, QQuickView *view) :
AbstractTool(inspector),
@@ -60,7 +64,7 @@ InspectTool::InspectTool(QQuickViewInspector *inspector, QQuickView *view) :
m_tapEvent(false),
m_contentItem(view->contentItem()),
m_originalPosition(view->contentItem()->position()),
- m_smoothScaleFactor(Constants::ZoomSnapDelta),
+ m_smoothScaleFactor(ZoomSnapDelta),
m_minScale(0.125f),
m_maxScale(48.0f),
m_originalScale(view->contentItem()->scale()),
@@ -71,7 +75,7 @@ InspectTool::InspectTool(QQuickViewInspector *inspector, QQuickView *view) :
{
//Press and Hold Timer
m_pressAndHoldTimer.setSingleShot(true);
- m_pressAndHoldTimer.setInterval(Constants::PressAndHoldTimeout);
+ m_pressAndHoldTimer.setInterval(PressAndHoldTimeout);
connect(&m_pressAndHoldTimer, SIGNAL(timeout()), SLOT(zoomTo100()));
//Timer to display selected item's name
m_nameDisplayTimer.setSingleShot(true);
@@ -418,5 +422,6 @@ void InspectTool::showSelectedItemName()
inspector()->showSelectedItemName(m_lastItem, m_mousePosition);
}
-} // namespace QtQuick2
} // namespace QmlJSDebugger
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.h b/src/plugins/qmltooling/qmldbg_inspector/inspecttool.h
index 0b1b49fd93..fdb763d4b3 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.h
+++ b/src/plugins/qmltooling/qmldbg_inspector/inspecttool.h
@@ -40,11 +40,12 @@
#include <QtCore/QPointer>
#include <QtCore/QTimer>
-QT_FORWARD_DECLARE_CLASS(QQuickView)
-QT_FORWARD_DECLARE_CLASS(QQuickItem)
+QT_BEGIN_NAMESPACE
+
+class QQuickView;
+class QQuickItem;
namespace QmlJSDebugger {
-namespace QtQuick2 {
class QQuickViewInspector;
class HoverHighlight;
@@ -119,7 +120,8 @@ private:
QQuickItem *m_lastClickedItem;
};
-} // namespace QtQuick2
} // namespace QmlJSDebugger
+QT_END_NAMESPACE
+
#endif // INSPECTTOOL_H
diff --git a/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro b/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro
new file mode 100644
index 0000000000..1c3e5f387b
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro
@@ -0,0 +1,27 @@
+TARGET = qmldbg_inspector
+QT += qml-private quick-private core-private gui-private
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QQmlInspectorServiceFactory
+load(qt_plugin)
+
+INCLUDEPATH *= $$PWD $$PWD/../shared
+
+SOURCES += \
+ $$PWD/highlight.cpp \
+ $$PWD/qquickviewinspector.cpp \
+ $$PWD/abstracttool.cpp \
+ $$PWD/abstractviewinspector.cpp \
+ $$PWD/inspecttool.cpp \
+ $$PWD/qqmlinspectorservice.cpp
+
+HEADERS += \
+ $$PWD/highlight.h \
+ $$PWD/qquickviewinspector.h \
+ $$PWD/qqmlinspectorservicefactory.h \
+ $$PWD/abstracttool.h \
+ $$PWD/abstractviewinspector.h \
+ $$PWD/inspecttool.h
+
+OTHER_FILES += \
+ qqmlinspectorservice.json
diff --git a/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp
new file mode 100644
index 0000000000..1707091df3
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlinspectorservicefactory.h"
+#include "qquickviewinspector.h"
+
+#include <private/qqmlglobal_p.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QPluginLoader>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlInspectorServiceImpl : public QQmlInspectorService
+{
+ Q_OBJECT
+
+public:
+ QQmlInspectorServiceImpl(QObject *parent = 0);
+
+ void addView(QObject *);
+ void removeView(QObject *);
+
+protected:
+ virtual void stateChanged(State state);
+ virtual void messageReceived(const QByteArray &);
+
+private Q_SLOTS:
+ void processMessage(const QByteArray &message);
+ void updateState();
+
+private:
+ friend class QQmlInspectorServiceFactory;
+
+ QList<QObject*> m_views;
+ QmlJSDebugger::AbstractViewInspector *m_currentInspector;
+};
+
+QQmlInspectorServiceImpl::QQmlInspectorServiceImpl(QObject *parent):
+ QQmlInspectorService(1, parent), m_currentInspector(0)
+{
+}
+
+void QQmlInspectorServiceImpl::addView(QObject *view)
+{
+ m_views.append(view);
+ updateState();
+}
+
+void QQmlInspectorServiceImpl::removeView(QObject *view)
+{
+ m_views.removeAll(view);
+ updateState();
+}
+
+void QQmlInspectorServiceImpl::stateChanged(State /*state*/)
+{
+ QMetaObject::invokeMethod(this, "updateState", Qt::QueuedConnection);
+}
+
+void QQmlInspectorServiceImpl::updateState()
+{
+ delete m_currentInspector;
+ m_currentInspector = 0;
+
+ if (m_views.isEmpty() || state() != Enabled)
+ return;
+
+ QQuickView *qtQuickView = qobject_cast<QQuickView*>(m_views.first());
+ if (qtQuickView)
+ m_currentInspector = new QmlJSDebugger::QQuickViewInspector(this, qtQuickView, this);
+ else
+ qWarning() << "QQmlInspector: No inspector available for view '"
+ << m_views.first()->metaObject()->className() << "'.";
+}
+
+void QQmlInspectorServiceImpl::messageReceived(const QByteArray &message)
+{
+ QMetaObject::invokeMethod(this, "processMessage", Qt::QueuedConnection, Q_ARG(QByteArray, message));
+}
+
+void QQmlInspectorServiceImpl::processMessage(const QByteArray &message)
+{
+ if (m_currentInspector)
+ m_currentInspector->handleMessage(message);
+}
+
+QQmlDebugService *QQmlInspectorServiceFactory::create(const QString &key)
+{
+ return key == QQmlInspectorServiceImpl::s_key ? new QQmlInspectorServiceImpl(this) : 0;
+}
+
+QT_END_NAMESPACE
+
+#include "qqmlinspectorservice.moc"
diff --git a/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.json b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.json
new file mode 100644
index 0000000000..9ace8dad2f
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "QmlInspector" ]
+}
diff --git a/src/qml/debugger/qqmlinspectorinterface_p.h b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservicefactory.h
index 9b29d383c7..52f84a362d 100644
--- a/src/qml/debugger/qqmlinspectorinterface_p.h
+++ b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservicefactory.h
@@ -31,8 +31,8 @@
**
****************************************************************************/
-#ifndef QQMLINSPECTORINTERFACE_H
-#define QQMLINSPECTORINTERFACE_H
+#ifndef QQMLINSPECTORSERVICE_H
+#define QQMLINSPECTORSERVICE_H
//
// W A R N I N G
@@ -45,30 +45,22 @@
// We mean it.
//
+#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qqmldebugservicefactory_p.h>
+
#include <QtQml/qtqmlglobal.h>
-#include <private/qqmlglobal_p.h>
+#include <QtCore/QList>
QT_BEGIN_NAMESPACE
-
-class Q_QML_PRIVATE_EXPORT QQmlInspectorInterface
+class QQmlInspectorServiceFactory : public QQmlDebugServiceFactory
{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlDebugServiceFactory_iid FILE "qqmlinspectorservice.json")
public:
- QQmlInspectorInterface() {}
- virtual ~QQmlInspectorInterface() {}
-
- virtual bool canHandleView(QObject *view) = 0;
-
- virtual void activate(QObject *view) = 0;
- virtual void deactivate() = 0;
-
- virtual void clientMessage(const QByteArray &message) = 0;
+ QQmlDebugService *create(const QString &key);
};
-#define QQmlInspectorInterface_iid "org.qt-project.Qt.QQmlInspectorInterface"
-
-Q_DECLARE_INTERFACE(QQmlInspectorInterface, QQmlInspectorInterface_iid)
-
QT_END_NAMESPACE
-#endif // QQMLINSPECTORINTERFACE_H
+#endif // QQMLINSPECTORSERVICE_H
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.cpp
index e61c421bfa..de9d5617b5 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.cpp
@@ -37,7 +37,6 @@
#include "inspecttool.h"
#include <QtQml/private/qqmlengine_p.h>
-#include <QtQml/private/qqmldebugservice_p.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/QQuickView>
@@ -45,8 +44,8 @@
#include <cfloat>
+QT_BEGIN_NAMESPACE
namespace QmlJSDebugger {
-namespace QtQuick2 {
/*
* Collects all the items at the given position, from top to bottom.
@@ -110,8 +109,9 @@ static QQuickItem *itemAt(QQuickItem *item, const QPointF &pos,
}
-QQuickViewInspector::QQuickViewInspector(QQuickView *view, QObject *parent) :
- AbstractViewInspector(parent),
+QQuickViewInspector::QQuickViewInspector(QQmlDebugService *service, QQuickView *view,
+ QObject *parent) :
+ AbstractViewInspector(service, parent),
m_view(view),
m_overlay(new QQuickItem),
m_inspectTool(new InspectTool(this, view)),
@@ -211,6 +211,7 @@ void QQuickViewInspector::setSelectedItems(const QList<QQuickItem *> &items)
return;
QList<QObject*> objectList;
+ objectList.reserve(items.count());
foreach (QQuickItem *item, items)
objectList << item;
@@ -314,8 +315,6 @@ void QQuickViewInspector::reloadQmlFile(const QHash<QString, QByteArray> &change
// Reset the selection since we are reloading the main qml
setSelectedItems(QList<QQuickItem *>());
- QQmlDebugService::clearObjectsFromHash();
-
QHash<QUrl, QByteArray> debugCache;
foreach (const QString &str, changesHash.keys())
@@ -373,5 +372,6 @@ void QQuickViewInspector::applyAppOnTop()
setWindowFlags(flags);
}
-} // namespace QtQuick2
} // namespace QmlJSDebugger
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.h b/src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.h
index be3ede4d07..e823e5a03d 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.h
+++ b/src/plugins/qmltooling/qmldbg_inspector/qquickviewinspector.h
@@ -43,10 +43,8 @@
QT_BEGIN_NAMESPACE
class QQuickView;
class QQuickItem;
-QT_END_NAMESPACE
namespace QmlJSDebugger {
-namespace QtQuick2 {
class InspectTool;
class SelectionHighlight;
@@ -55,7 +53,7 @@ class QQuickViewInspector : public AbstractViewInspector
{
Q_OBJECT
public:
- explicit QQuickViewInspector(QQuickView *view, QObject *parent = 0);
+ explicit QQuickViewInspector(QQmlDebugService *service, QQuickView *view, QObject *parent = 0);
// AbstractViewInspector
void changeCurrentObjects(const QList<QObject*> &objects);
@@ -104,7 +102,8 @@ private:
bool m_appOnTop;
};
-} // namespace QtQuick2
} // namespace QmlJSDebugger
+QT_END_NAMESPACE
+
#endif // QQUICKVIEWINSPECTOR_H
diff --git a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
new file mode 100644
index 0000000000..057bf9523e
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlocalclientconnectionfactory.h"
+#include "qpacketprotocol.h"
+#include "qqmldebugserver.h"
+
+#include <QtCore/qplugin.h>
+#include <QtNetwork/qlocalsocket.h>
+
+QT_BEGIN_NAMESPACE
+
+
+class QLocalClientConnection : public QQmlDebugServerConnection
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QLocalClientConnection)
+
+public:
+ QLocalClientConnection();
+ ~QLocalClientConnection();
+
+ void setServer(QQmlDebugServer *server);
+ bool setPortRange(int portFrom, int portTo, bool block, const QString &hostaddress);
+ bool setFileName(const QString &filename, bool block);
+
+ bool isConnected() const;
+ void disconnect();
+
+ void waitForConnection();
+ void flush();
+
+private slots:
+ void connectionEstablished();
+
+private:
+ bool connectToServer();
+
+ bool m_block;
+ QString m_filename;
+ QLocalSocket *m_socket;
+ QQmlDebugServer *m_debugServer;
+};
+
+QLocalClientConnection::QLocalClientConnection() :
+ m_block(false),
+ m_socket(0),
+ m_debugServer(0)
+{
+}
+
+QLocalClientConnection::~QLocalClientConnection()
+{
+ if (isConnected())
+ disconnect();
+}
+
+void QLocalClientConnection::setServer(QQmlDebugServer *server)
+{
+ m_debugServer = server;
+}
+
+bool QLocalClientConnection::isConnected() const
+{
+ return m_socket && m_socket->state() == QLocalSocket::ConnectedState;
+}
+
+void QLocalClientConnection::disconnect()
+{
+ while (m_socket && m_socket->bytesToWrite() > 0)
+ m_socket->waitForBytesWritten();
+
+ m_socket->deleteLater();
+ m_socket = 0;
+}
+
+bool QLocalClientConnection::setPortRange(int portFrom, int portTo, bool block,
+ const QString &hostaddress)
+{
+ Q_UNUSED(portFrom);
+ Q_UNUSED(portTo);
+ Q_UNUSED(block);
+ Q_UNUSED(hostaddress);
+ return false;
+}
+
+bool QLocalClientConnection::setFileName(const QString &filename, bool block)
+{
+ m_filename = filename;
+ m_block = block;
+ return connectToServer();
+}
+
+void QLocalClientConnection::waitForConnection()
+{
+ m_socket->waitForConnected(-1);
+}
+
+bool QLocalClientConnection::connectToServer()
+{
+ m_socket = new QLocalSocket;
+ m_socket->setParent(this);
+ QObject::connect(m_socket, SIGNAL(connected()), this, SLOT(connectionEstablished()));
+ m_socket->connectToServer(m_filename);
+ qDebug("QML Debugger: Connecting to socket %s...", m_filename.toLatin1().constData());
+ return true;
+}
+
+void QLocalClientConnection::flush()
+{
+ if (m_socket)
+ m_socket->flush();
+}
+
+void QLocalClientConnection::connectionEstablished()
+{
+ m_debugServer->setDevice(m_socket);
+}
+
+QQmlDebugServerConnection *QLocalClientConnectionFactory::create(const QString &key)
+{
+ return (key == QLatin1String("QLocalClientConnection") ? new QLocalClientConnection : 0);
+}
+
+QT_END_NAMESPACE
+
+#include "qlocalclientconnection.moc"
diff --git a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.json b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.json
new file mode 100644
index 0000000000..5f8fd49296
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "QLocalClientConnection" ]
+}
diff --git a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnectionfactory.h b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnectionfactory.h
new file mode 100644
index 0000000000..110e0c2395
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnectionfactory.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLOCALCLIENTCONNECTIONFACTORY_H
+#define QLOCALCLIENTCONNECTIONFACTORY_H
+
+#include "qqmldebugserverconnection.h"
+
+QT_BEGIN_NAMESPACE
+
+class QLocalClientConnectionFactory : public QQmlDebugServerConnectionFactory
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlDebugServerConnectionFactory_iid FILE "qlocalclientconnection.json")
+ Q_INTERFACES(QQmlDebugServerConnectionFactory)
+public:
+ QQmlDebugServerConnection *create(const QString &key);
+};
+
+QT_END_NAMESPACE
+
+#endif // QLOCALCLIENTCONNECTIONFACTORY_H
diff --git a/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro b/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro
new file mode 100644
index 0000000000..491be04b15
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_local/qmldbg_local.pro
@@ -0,0 +1,20 @@
+TARGET = qmldbg_local
+QT = qml-private
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QLocalClientConnectionFactory
+load(qt_plugin)
+
+SOURCES += \
+ $$PWD/qlocalclientconnection.cpp
+
+HEADERS += \
+ $$PWD/qlocalclientconnectionfactory.h \
+ $$PWD/../shared/qqmldebugserver.h \
+ $$PWD/../shared/qqmldebugserverconnection.h
+
+INCLUDEPATH += $$PWD \
+ $$PWD/../shared
+
+OTHER_FILES += \
+ $$PWD/qlocalclientconnection.json
diff --git a/src/plugins/qmltooling/qmldbg_native/qmldbg_native.pro b/src/plugins/qmltooling/qmldbg_native/qmldbg_native.pro
new file mode 100644
index 0000000000..7dc16b8c44
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_native/qmldbg_native.pro
@@ -0,0 +1,12 @@
+TARGET = qmldbg_native
+QT += qml-private core-private
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QQmlNativeDebugConnectorFactory
+load(qt_plugin)
+
+SOURCES += \
+ $$PWD/qqmlnativedebugconnector.cpp
+
+OTHER_FILES += \
+ $$PWD/qqmlnativedebugconnector.json
diff --git a/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp
new file mode 100644
index 0000000000..6621eafb27
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp
@@ -0,0 +1,383 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qqmldebugconnector_p.h>
+#include <private/qhooks_p.h>
+
+#include <qqmlengine.h>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qjsonarray.h>
+#include <QtCore/qjsondocument.h>
+#include <QtCore/qjsonobject.h>
+#include <QtCore/qjsonvalue.h>
+#include <QtCore/qpointer.h>
+#include <QtCore/qvector.h>
+
+//#define TRACE_PROTOCOL(s) qDebug() << s
+#define TRACE_PROTOCOL(s)
+
+QT_USE_NAMESPACE
+
+static bool expectSyncronousResponse = false;
+Q_GLOBAL_STATIC(QByteArray, responseBuffer)
+
+extern "C" {
+
+Q_DECL_EXPORT const char *qt_qmlDebugMessageBuffer;
+Q_DECL_EXPORT int qt_qmlDebugMessageLength;
+Q_DECL_EXPORT bool qt_qmlDebugConnectionBlocker;
+
+// In blocking mode, this will busy wait until the debugger sets block to false.
+Q_DECL_EXPORT void qt_qmlDebugConnectorOpen();
+
+// First thing, set the debug stream version. Please use this function as we might move the version
+// member to some other place.
+Q_DECL_EXPORT void qt_qmlDebugSetStreamVersion(int version)
+{
+ QQmlDebugStream::s_dataStreamVersion = version;
+}
+
+
+// Break in this one to process output from an asynchronous message/
+Q_DECL_EXPORT void qt_qmlDebugMessageAvailable()
+{
+}
+
+
+// Break in this one to get notified about construction and destruction of
+// interesting objects, such as QmlEngines.
+Q_DECL_EXPORT void qt_qmlDebugObjectAvailable()
+{
+}
+
+Q_DECL_EXPORT void qt_qmlDebugClearBuffer()
+{
+ responseBuffer->clear();
+}
+
+// Send a message to a service.
+Q_DECL_EXPORT bool qt_qmlDebugSendDataToService(const char *serviceName, const char *hexData)
+{
+ QByteArray msg = QByteArray::fromHex(hexData);
+
+ QQmlDebugConnector *instance = QQmlDebugConnector::instance();
+ if (!instance)
+ return false;
+
+ QQmlDebugService *recipient = instance->service(serviceName);
+ if (!recipient)
+ return false;
+
+ TRACE_PROTOCOL("Recipient: " << recipient << " got message: " << msg);
+ expectSyncronousResponse = true;
+ recipient->messageReceived(msg);
+ expectSyncronousResponse = false;
+
+ return true;
+}
+
+// Enable a service.
+Q_DECL_EXPORT bool qt_qmlDebugEnableService(const char *data)
+{
+ QQmlDebugConnector *instance = QQmlDebugConnector::instance();
+ if (!instance)
+ return false;
+
+ QString name = QString::fromLatin1(data);
+ QQmlDebugService *service = instance->service(name);
+ if (!service || service->state() == QQmlDebugService::Enabled)
+ return false;
+
+ service->stateAboutToBeChanged(QQmlDebugService::Enabled);
+ service->setState(QQmlDebugService::Enabled);
+ service->stateChanged(QQmlDebugService::Enabled);
+ return true;
+}
+
+Q_DECL_EXPORT bool qt_qmlDebugDisableService(const char *data)
+{
+ QQmlDebugConnector *instance = QQmlDebugConnector::instance();
+ if (!instance)
+ return false;
+
+ QString name = QString::fromLatin1(data);
+ QQmlDebugService *service = instance->service(name);
+ if (!service || service->state() == QQmlDebugService::Unavailable)
+ return false;
+
+ service->stateAboutToBeChanged(QQmlDebugService::Unavailable);
+ service->setState(QQmlDebugService::Unavailable);
+ service->stateChanged(QQmlDebugService::Unavailable);
+ return true;
+}
+
+quintptr qt_qmlDebugTestHooks[] = {
+ quintptr(1), // Internal Version
+ quintptr(6), // Number of entries following
+ quintptr(&qt_qmlDebugMessageBuffer),
+ quintptr(&qt_qmlDebugMessageLength),
+ quintptr(&qt_qmlDebugSendDataToService),
+ quintptr(&qt_qmlDebugEnableService),
+ quintptr(&qt_qmlDebugDisableService),
+ quintptr(&qt_qmlDebugObjectAvailable)
+};
+
+// In blocking mode, this will busy wait until the debugger sets block to false.
+Q_DECL_EXPORT void qt_qmlDebugConnectorOpen()
+{
+ TRACE_PROTOCOL("Opening native debug connector");
+
+ // FIXME: Use a dedicated hook. Startup is a safe workaround, though,
+ // as we are already beyond its only use.
+ qtHookData[QHooks::Startup] = quintptr(&qt_qmlDebugTestHooks);
+
+ while (qt_qmlDebugConnectionBlocker)
+ ;
+
+ TRACE_PROTOCOL("Opened native debug connector");
+}
+
+} // extern "C"
+
+QT_BEGIN_NAMESPACE
+
+class QQmlNativeDebugConnector : public QQmlDebugConnector
+{
+ Q_OBJECT
+
+public:
+ QQmlNativeDebugConnector();
+ ~QQmlNativeDebugConnector();
+
+ bool blockingMode() const;
+ QQmlDebugService *service(const QString &name) const;
+ void addEngine(QQmlEngine *engine);
+ void removeEngine(QQmlEngine *engine);
+ bool addService(const QString &name, QQmlDebugService *service);
+ bool removeService(const QString &name);
+ bool open(const QVariantHash &configuration);
+
+private slots:
+ void sendMessage(const QString &name, const QByteArray &message);
+ void sendMessages(const QString &name, const QList<QByteArray> &messages);
+
+private:
+ void announceObjectAvailability(const QString &objectType, QObject *object, bool available);
+
+ QVector<QQmlDebugService *> m_services;
+ bool m_blockingMode;
+};
+
+QQmlNativeDebugConnector::QQmlNativeDebugConnector()
+ : m_blockingMode(false)
+{
+ const QString args = commandLineArguments();
+ const QStringList lstjsDebugArguments = args.split(QLatin1Char(','));
+ QStringList services;
+ QStringList::const_iterator argsItEnd = lstjsDebugArguments.cend();
+ QStringList::const_iterator argsIt = lstjsDebugArguments.cbegin();
+ for (; argsIt != argsItEnd; ++argsIt) {
+ const QString strArgument = *argsIt;
+ if (strArgument == QLatin1String("block")) {
+ m_blockingMode = true;
+ } else if (strArgument == QLatin1String("native")) {
+ // Ignore. This is used to signal that this connector
+ // should be loaded and that has already happened.
+ } else if (strArgument.startsWith(QLatin1String("services:"))) {
+ services.append(strArgument.mid(9));
+ } else if (!services.isEmpty()) {
+ services.append(strArgument);
+ } else {
+ qWarning("QML Debugger: Invalid argument \"%s\" detected. Ignoring the same.",
+ qUtf8Printable(strArgument));
+ }
+ }
+ setServices(services);
+}
+
+QQmlNativeDebugConnector::~QQmlNativeDebugConnector()
+{
+ foreach (QQmlDebugService *service, m_services) {
+ service->stateAboutToBeChanged(QQmlDebugService::NotConnected);
+ service->setState(QQmlDebugService::NotConnected);
+ service->stateChanged(QQmlDebugService::NotConnected);
+ }
+}
+
+bool QQmlNativeDebugConnector::blockingMode() const
+{
+ return m_blockingMode;
+}
+
+QQmlDebugService *QQmlNativeDebugConnector::service(const QString &name) const
+{
+ for (QVector<QQmlDebugService *>::ConstIterator i = m_services.begin(); i != m_services.end();
+ ++i) {
+ if ((*i)->name() == name)
+ return *i;
+ }
+ return 0;
+}
+
+void QQmlNativeDebugConnector::addEngine(QQmlEngine *engine)
+{
+ TRACE_PROTOCOL("Add engine to connector:" << engine);
+ foreach (QQmlDebugService *service, m_services)
+ service->engineAboutToBeAdded(engine);
+
+ announceObjectAvailability(QLatin1String("qmlengine"), engine, true);
+
+ foreach (QQmlDebugService *service, m_services)
+ service->engineAdded(engine);
+}
+
+void QQmlNativeDebugConnector::removeEngine(QQmlEngine *engine)
+{
+ TRACE_PROTOCOL("Remove engine from connector:" << engine);
+ foreach (QQmlDebugService *service, m_services)
+ service->engineAboutToBeRemoved(engine);
+
+ announceObjectAvailability(QLatin1String("qmlengine"), engine, false);
+
+ foreach (QQmlDebugService *service, m_services)
+ service->engineRemoved(engine);
+}
+
+void QQmlNativeDebugConnector::announceObjectAvailability(const QString &objectType,
+ QObject *object, bool available)
+{
+ QJsonObject ob;
+ ob.insert(QLatin1String("objecttype"), objectType);
+ ob.insert(QLatin1String("object"), QString::number(quintptr(object)));
+ ob.insert(QLatin1String("available"), available);
+ QJsonDocument doc;
+ doc.setObject(ob);
+
+ QByteArray ba = doc.toJson(QJsonDocument::Compact);
+ qt_qmlDebugMessageBuffer = ba.constData();
+ qt_qmlDebugMessageLength = ba.size();
+ TRACE_PROTOCOL("Reporting engine availabilty");
+ qt_qmlDebugObjectAvailable(); // Trigger native breakpoint.
+}
+
+bool QQmlNativeDebugConnector::addService(const QString &name, QQmlDebugService *service)
+{
+ TRACE_PROTOCOL("Add service to connector: " << qPrintable(name) << service);
+ for (QVector<QQmlDebugService *>::ConstIterator i = m_services.begin(); i != m_services.end();
+ ++i) {
+ if ((*i)->name() == name)
+ return false;
+ }
+
+ connect(service, &QQmlDebugService::messageToClient,
+ this, &QQmlNativeDebugConnector::sendMessage);
+ connect(service, &QQmlDebugService::messagesToClient,
+ this, &QQmlNativeDebugConnector::sendMessages);
+
+ service->setState(QQmlDebugService::Unavailable);
+
+ m_services << service;
+ return true;
+}
+
+bool QQmlNativeDebugConnector::removeService(const QString &name)
+{
+ for (QVector<QQmlDebugService *>::Iterator i = m_services.begin(); i != m_services.end(); ++i) {
+ if ((*i)->name() == name) {
+ QQmlDebugService *service = *i;
+ m_services.erase(i);
+ service->setState(QQmlDebugService::NotConnected);
+
+ disconnect(service, &QQmlDebugService::messagesToClient,
+ this, &QQmlNativeDebugConnector::sendMessages);
+ disconnect(service, &QQmlDebugService::messageToClient,
+ this, &QQmlNativeDebugConnector::sendMessage);
+
+ return true;
+ }
+ }
+ return false;
+}
+
+bool QQmlNativeDebugConnector::open(const QVariantHash &configuration)
+{
+ m_blockingMode = configuration.value(QStringLiteral("block"), m_blockingMode).toBool();
+ qt_qmlDebugConnectionBlocker = m_blockingMode;
+ qt_qmlDebugConnectorOpen();
+ return true;
+}
+
+void QQmlNativeDebugConnector::sendMessage(const QString &name, const QByteArray &message)
+{
+ (*responseBuffer) += name.toUtf8() + ' ' + QByteArray::number(message.size()) + ' ' + message;
+ qt_qmlDebugMessageBuffer = responseBuffer->constData();
+ qt_qmlDebugMessageLength = responseBuffer->size();
+ // Responses are allowed to accumulate, the buffer will be cleared by
+ // separate calls to qt_qmlDebugClearBuffer() once the synchronous
+ // function return ('if' branch below) or in the native breakpoint handler
+ // ('else' branch below).
+ if (expectSyncronousResponse) {
+ TRACE_PROTOCOL("Expected synchronous response in " << message);
+ // Do not trigger the native breakpoint on qt_qmlDebugMessageFromService.
+ } else {
+ TRACE_PROTOCOL("Found asynchronous message in " << message);
+ // Trigger native breakpoint.
+ qt_qmlDebugMessageAvailable();
+ }
+}
+
+void QQmlNativeDebugConnector::sendMessages(const QString &name, const QList<QByteArray> &messages)
+{
+ for (int i = 0; i != messages.size(); ++i)
+ sendMessage(name, messages.at(i));
+}
+
+class QQmlNativeDebugConnectorFactory : public QQmlDebugConnectorFactory
+{
+ Q_OBJECT
+
+ Q_PLUGIN_METADATA(IID QQmlDebugConnectorFactory_iid FILE "qqmlnativedebugconnector.json")
+
+public:
+ QQmlNativeDebugConnectorFactory() {}
+
+ QQmlDebugConnector *create(const QString &key)
+ {
+ return key == QLatin1String("QQmlNativeDebugConnector") ? new QQmlNativeDebugConnector : 0;
+ }
+};
+
+QT_END_NAMESPACE
+
+#include "qqmlnativedebugconnector.moc"
diff --git a/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.json b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.json
new file mode 100644
index 0000000000..925e6a665c
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "QQmlNativeDebugConnector" ]
+}
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro b/src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro
new file mode 100644
index 0000000000..e1c4095d88
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_profiler/qmldbg_profiler.pro
@@ -0,0 +1,28 @@
+TARGET = qmldbg_profiler
+QT = qml-private core-private
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QQmlProfilerServiceFactory
+load(qt_plugin)
+
+SOURCES += \
+ $$PWD/qqmlenginecontrolservice.cpp \
+ $$PWD/qqmlprofileradapter.cpp \
+ $$PWD/qqmlprofilerservice.cpp \
+ $$PWD/qqmlprofilerservicefactory.cpp \
+ $$PWD/qv4profileradapter.cpp
+
+HEADERS += \
+ $$PWD/../shared/qqmlconfigurabledebugservice.h \
+ $$PWD/qqmlenginecontrolservice.h \
+ $$PWD/qqmlprofileradapter.h \
+ $$PWD/qqmlprofilerservice.h \
+ $$PWD/qqmlprofilerservicefactory.h \
+ $$PWD/qv4profileradapter.h
+
+INCLUDEPATH += $$PWD \
+ $$PWD/../shared
+
+OTHER_FILES += \
+ $$PWD/qqmlprofilerservice.json
+
diff --git a/src/qml/debugger/qqmlenginecontrolservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp
index 07c6715524..4f131ac481 100644
--- a/src/qml/debugger/qqmlenginecontrolservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp
@@ -31,24 +31,16 @@
**
****************************************************************************/
+#include "qqmlenginecontrolservice.h"
#include <QQmlEngine>
-#include "qqmldebug.h"
-#include "qqmlenginecontrolservice_p.h"
QT_BEGIN_NAMESPACE
-Q_GLOBAL_STATIC(QQmlEngineControlService, qmlEngineControlService)
+const QString QQmlEngineControlService::s_key = QStringLiteral("EngineControl");
-QQmlEngineControlService::QQmlEngineControlService() :
- QQmlDebugService(QStringLiteral("EngineControl"), 1)
+QQmlEngineControlService::QQmlEngineControlService(QObject *parent) :
+ QQmlDebugService(s_key, 1, parent)
{
- QMutexLocker lock(&dataMutex);
- registerService();
-}
-
-QQmlEngineControlService *QQmlEngineControlService::instance()
-{
- return qmlEngineControlService();
}
void QQmlEngineControlService::messageReceived(const QByteArray &message)
@@ -119,7 +111,7 @@ void QQmlEngineControlService::sendMessage(QQmlEngineControlService::MessageType
QByteArray message;
QQmlDebugStream d(&message, QIODevice::WriteOnly);
d << type << idForObject(engine);
- QQmlDebugService::sendMessage(message);
+ emit messageToClient(name(), message);
}
void QQmlEngineControlService::stateChanged(State)
diff --git a/src/qml/debugger/qqmlenginecontrolservice_p.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.h
index 2171937efe..e2a93e562a 100644
--- a/src/qml/debugger/qqmlenginecontrolservice_p.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.h
@@ -35,7 +35,7 @@
#define QQMLENGINECONTROLSERVICE_H
#include <QMutex>
-#include "qqmldebugservice_p.h"
+#include <private/qqmldebugservice_p.h>
//
// W A R N I N G
@@ -53,6 +53,8 @@ QT_BEGIN_NAMESPACE
class QQmlEngineControlService : public QQmlDebugService
{
public:
+ static const QString s_key;
+
enum MessageType {
EngineAboutToBeAdded,
EngineAdded,
@@ -65,9 +67,7 @@ public:
StopWaitingEngine
};
- QQmlEngineControlService();
-
- static QQmlEngineControlService *instance();
+ QQmlEngineControlService(QObject *parent = 0);
protected:
QMutex dataMutex;
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
new file mode 100644
index 0000000000..245900abae
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlprofileradapter.h"
+#include <private/qqmldebugserviceinterfaces_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine) :
+ QQmlAbstractProfilerAdapter(service), next(0)
+{
+ engine->enableProfiler();
+ connect(this, SIGNAL(profilingEnabled(quint64)), engine->profiler, SLOT(startProfiling(quint64)));
+ connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
+ engine->profiler, SLOT(startProfiling(quint64)), Qt::DirectConnection);
+ connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
+ connect(this, SIGNAL(profilingDisabledWhileWaiting()),
+ engine->profiler, SLOT(stopProfiling()), Qt::DirectConnection);
+ connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
+ connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
+ engine->profiler, SLOT(setTimer(QElapsedTimer)));
+ connect(engine->profiler, SIGNAL(dataReady(QVector<QQmlProfilerData>)),
+ this, SLOT(receiveData(QVector<QQmlProfilerData>)));
+}
+
+// convert to QByteArrays that can be sent to the debug client
+// use of QDataStream can skew results
+// (see tst_qqmldebugtrace::trace() benchmark)
+static void qQmlProfilerDataToByteArrays(const QQmlProfilerData *d, QList<QByteArray> &messages)
+{
+ QByteArray data;
+ Q_ASSERT_X(((d->messageType | d->detailType) & (1 << 31)) == 0, Q_FUNC_INFO,
+ "You can use at most 31 message types and 31 detail types.");
+ for (uint decodedMessageType = 0; (d->messageType >> decodedMessageType) != 0;
+ ++decodedMessageType) {
+ if ((d->messageType & (1 << decodedMessageType)) == 0)
+ continue;
+
+ for (uint decodedDetailType = 0; (d->detailType >> decodedDetailType) != 0;
+ ++decodedDetailType) {
+ if ((d->detailType & (1 << decodedDetailType)) == 0)
+ continue;
+
+ //### using QDataStream is relatively expensive
+ QQmlDebugStream ds(&data, QIODevice::WriteOnly);
+ ds << d->time << decodedMessageType << decodedDetailType;
+
+ switch (decodedMessageType) {
+ case QQmlProfilerDefinitions::RangeStart:
+ if (decodedDetailType == (int)QQmlProfilerDefinitions::Binding)
+ ds << QQmlProfilerDefinitions::QmlBinding;
+ break;
+ case QQmlProfilerDefinitions::RangeData:
+ ds << (d->detailString.isEmpty() ? d->detailUrl.toString() : d->detailString);
+ break;
+ case QQmlProfilerDefinitions::RangeLocation:
+ ds << (d->detailUrl.isEmpty() ? d->detailString : d->detailUrl.toString()) << d->x
+ << d->y;
+ break;
+ case QQmlProfilerDefinitions::RangeEnd: break;
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
+ break;
+ }
+ messages << data;
+ data.clear();
+ }
+ }
+}
+
+qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
+{
+ while (next != data.length()) {
+ if (data[next].time > until)
+ return data[next].time;
+ qQmlProfilerDataToByteArrays(&(data[next++]), messages);
+ }
+
+ next = 0;
+ data.clear();
+ return -1;
+}
+
+void QQmlProfilerAdapter::receiveData(const QVector<QQmlProfilerData> &new_data)
+{
+ if (data.isEmpty())
+ data = new_data;
+ else
+ data.append(new_data);
+ service->dataReady(this);
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlconfigurabledebugservice_p_p.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
index 6d693b6352..eceb58ce3a 100644
--- a/src/qml/debugger/qqmlconfigurabledebugservice_p_p.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
@@ -31,9 +31,6 @@
**
****************************************************************************/
-#ifndef QQMLCONFIGURABLEDEBUGSERVICE_P_H
-#define QQMLCONFIGURABLEDEBUGSERVICE_P_H
-
//
// W A R N I N G
// -------------
@@ -45,26 +42,28 @@
// We mean it.
//
-#include "qqmldebugservice_p.h"
-#include "qqmldebugservice_p_p.h"
+#ifndef QQMLPROFILERADAPTER_H
+#define QQMLPROFILERADAPTER_H
-#include <QMutex>
+#include <private/qqmlabstractprofileradapter_p.h>
+#include <private/qqmlprofiler_p.h>
QT_BEGIN_NAMESPACE
-class QQmlEngine;
-
-class QQmlConfigurableDebugServicePrivate : public QQmlDebugServicePrivate
-{
- Q_DECLARE_PUBLIC(QQmlConfigurableDebugService)
+class QQmlProfilerAdapter : public QQmlAbstractProfilerAdapter {
+ Q_OBJECT
public:
- QQmlConfigurableDebugServicePrivate() : configMutex(QMutex::Recursive) {}
+ QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine);
+ qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
+
+public slots:
+ void receiveData(const QVector<QQmlProfilerData> &new_data);
- QMutex configMutex;
- QList<QQmlEngine *> waitingEngines;
- bool waitingForConfiguration;
+private:
+ QVector<QQmlProfilerData> data;
+ int next;
};
QT_END_NAMESPACE
-#endif // QQMLCONFIGURABLEDEBUGSERVICE_P_H
+#endif // QQMLPROFILERADAPTER_H
diff --git a/src/qml/debugger/qqmlprofilerservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
index 85556836e6..2654cf662b 100644
--- a/src/qml/debugger/qqmlprofilerservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
@@ -31,10 +31,10 @@
**
****************************************************************************/
-#include "qqmlprofilerservice_p.h"
-#include "qqmldebugserver_p.h"
-#include "qv4profileradapter_p.h"
-#include "qqmlprofiler_p.h"
+#include "qqmlprofilerservice.h"
+#include "qv4profileradapter.h"
+#include "qqmlprofileradapter.h"
+#include "qqmlprofilerservicefactory.h"
#include <private/qqmlengine_p.h>
#include <QtCore/qdatastream.h>
@@ -45,30 +45,24 @@
QT_BEGIN_NAMESPACE
-Q_GLOBAL_STATIC(QQmlProfilerService, profilerInstance)
-
-QQmlProfilerService::QQmlProfilerService()
- : QQmlConfigurableDebugService(QStringLiteral("CanvasFrameRate"), 1)
+QQmlProfilerServiceImpl::QQmlProfilerServiceImpl(QObject *parent) :
+ QQmlConfigurableDebugService<QQmlProfilerService>(1, parent),
+ m_waitingForStop(false)
{
m_timer.start();
-
- QMutexLocker lock(configMutex());
- // If there is no debug server it doesn't matter as we'll never get enabled anyway.
- if (QQmlDebugServer::instance() != 0)
- moveToThread(QQmlDebugServer::instance()->thread());
}
-QQmlProfilerService::~QQmlProfilerService()
+QQmlProfilerServiceImpl::~QQmlProfilerServiceImpl()
{
// No need to lock here. If any engine or global profiler is still trying to register at this
// point we have a nasty bug anyway.
- qDeleteAll(m_engineProfilers.values());
+ qDeleteAll(m_engineProfilers);
qDeleteAll(m_globalProfilers);
}
-void QQmlProfilerService::dataReady(QQmlAbstractProfilerAdapter *profiler)
+void QQmlProfilerServiceImpl::dataReady(QQmlAbstractProfilerAdapter *profiler)
{
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
bool dataComplete = true;
for (QMultiMap<qint64, QQmlAbstractProfilerAdapter *>::iterator i(m_startTimes.begin()); i != m_startTimes.end();) {
if (i.value() == profiler) {
@@ -98,38 +92,35 @@ void QQmlProfilerService::dataReady(QQmlAbstractProfilerAdapter *profiler)
}
}
-QQmlProfilerService *QQmlProfilerService::instance()
-{
- // just make sure that the service is properly registered
- return profilerInstance();
-}
-
-void QQmlProfilerService::engineAboutToBeAdded(QQmlEngine *engine)
+void QQmlProfilerServiceImpl::engineAboutToBeAdded(QQmlEngine *engine)
{
- Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be added from the engine thread");
+ Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO,
+ "QML profilers have to be added from the engine thread");
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
QQmlProfilerAdapter *qmlAdapter = new QQmlProfilerAdapter(this, QQmlEnginePrivate::get(engine));
QV4ProfilerAdapter *v4Adapter = new QV4ProfilerAdapter(this, QV8Engine::getV4(engine->handle()));
addEngineProfiler(qmlAdapter, engine);
addEngineProfiler(v4Adapter, engine);
- QQmlConfigurableDebugService::engineAboutToBeAdded(engine);
+ QQmlConfigurableDebugService<QQmlProfilerService>::engineAboutToBeAdded(engine);
}
-void QQmlProfilerService::engineAdded(QQmlEngine *engine)
+void QQmlProfilerServiceImpl::engineAdded(QQmlEngine *engine)
{
- Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be added from the engine thread");
+ Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO,
+ "QML profilers have to be added from the engine thread");
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine))
profiler->stopWaiting();
}
-void QQmlProfilerService::engineAboutToBeRemoved(QQmlEngine *engine)
+void QQmlProfilerServiceImpl::engineAboutToBeRemoved(QQmlEngine *engine)
{
- Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be removed from the engine thread");
+ Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO,
+ "QML profilers have to be removed from the engine thread");
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
bool isRunning = false;
foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine)) {
if (profiler->isRunning())
@@ -144,11 +135,12 @@ void QQmlProfilerService::engineAboutToBeRemoved(QQmlEngine *engine)
}
}
-void QQmlProfilerService::engineRemoved(QQmlEngine *engine)
+void QQmlProfilerServiceImpl::engineRemoved(QQmlEngine *engine)
{
- Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be removed from the engine thread");
+ Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO,
+ "QML profilers have to be removed from the engine thread");
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine)) {
removeProfilerFromStartTimes(profiler);
delete profiler;
@@ -156,16 +148,16 @@ void QQmlProfilerService::engineRemoved(QQmlEngine *engine)
m_engineProfilers.remove(engine);
}
-void QQmlProfilerService::addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QQmlEngine *engine)
+void QQmlProfilerServiceImpl::addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QQmlEngine *engine)
{
profiler->moveToThread(thread());
profiler->synchronize(m_timer);
m_engineProfilers.insert(engine, profiler);
}
-void QQmlProfilerService::addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler)
+void QQmlProfilerServiceImpl::addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler)
{
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
profiler->synchronize(m_timer);
m_globalProfilers.append(profiler);
// Global profiler, not connected to a specific engine.
@@ -179,15 +171,15 @@ void QQmlProfilerService::addGlobalProfiler(QQmlAbstractProfilerAdapter *profile
profiler->startProfiling(features);
}
-void QQmlProfilerService::removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler)
+void QQmlProfilerServiceImpl::removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler)
{
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
removeProfilerFromStartTimes(profiler);
m_globalProfilers.removeOne(profiler);
delete profiler;
}
-void QQmlProfilerService::removeProfilerFromStartTimes(const QQmlAbstractProfilerAdapter *profiler)
+void QQmlProfilerServiceImpl::removeProfilerFromStartTimes(const QQmlAbstractProfilerAdapter *profiler)
{
for (QMultiMap<qint64, QQmlAbstractProfilerAdapter *>::iterator i(m_startTimes.begin());
i != m_startTimes.end();) {
@@ -206,9 +198,9 @@ void QQmlProfilerService::removeProfilerFromStartTimes(const QQmlAbstractProfile
*
* If any engine profiler is started like that also start all global profilers.
*/
-void QQmlProfilerService::startProfiling(QQmlEngine *engine, quint64 features)
+void QQmlProfilerServiceImpl::startProfiling(QQmlEngine *engine, quint64 features)
{
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
QByteArray message;
QQmlDebugStream d(&message, QIODevice::WriteOnly);
@@ -243,9 +235,11 @@ void QQmlProfilerService::startProfiling(QQmlEngine *engine, quint64 features)
if (!profiler->isRunning())
profiler->startProfiling(features);
}
+
+ emit startFlushTimer();
}
- QQmlDebugService::sendMessage(message);
+ emit messageToClient(name(), message);
}
/*!
@@ -255,9 +249,9 @@ void QQmlProfilerService::startProfiling(QQmlEngine *engine, quint64 features)
* If afterwards no more engine profilers are running, also stop all global profilers. Otherwise
* only make them report their data.
*/
-void QQmlProfilerService::stopProfiling(QQmlEngine *engine)
+void QQmlProfilerServiceImpl::stopProfiling(QQmlEngine *engine)
{
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
QList<QQmlAbstractProfilerAdapter *> stopping;
QList<QQmlAbstractProfilerAdapter *> reporting;
@@ -274,6 +268,9 @@ void QQmlProfilerService::stopProfiling(QQmlEngine *engine)
}
}
+ if (stopping.isEmpty())
+ return;
+
foreach (QQmlAbstractProfilerAdapter *profiler, m_globalProfilers) {
if (!profiler->isRunning())
continue;
@@ -285,6 +282,9 @@ void QQmlProfilerService::stopProfiling(QQmlEngine *engine)
}
}
+ emit stopFlushTimer();
+ m_waitingForStop = true;
+
foreach (QQmlAbstractProfilerAdapter *profiler, reporting)
profiler->reportData();
@@ -295,21 +295,24 @@ void QQmlProfilerService::stopProfiling(QQmlEngine *engine)
/*
Send the queued up messages.
*/
-void QQmlProfilerService::sendMessages()
+void QQmlProfilerServiceImpl::sendMessages()
{
QList<QByteArray> messages;
QByteArray data;
- QQmlDebugStream traceEnd(&data, QIODevice::WriteOnly);
- traceEnd << m_timer.nsecsElapsed() << (int)Event << (int)EndTrace;
- QSet<QQmlEngine *> seen;
- foreach (QQmlAbstractProfilerAdapter *profiler, m_startTimes) {
- for (QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *>::iterator i(m_engineProfilers.begin());
- i != m_engineProfilers.end(); ++i) {
- if (i.value() == profiler && !seen.contains(i.key())) {
- seen << i.key();
- traceEnd << idForObject(i.key());
+ if (m_waitingForStop) {
+ QQmlDebugStream traceEnd(&data, QIODevice::WriteOnly);
+ traceEnd << m_timer.nsecsElapsed() << (int)Event << (int)EndTrace;
+
+ QSet<QQmlEngine *> seen;
+ foreach (QQmlAbstractProfilerAdapter *profiler, m_startTimes) {
+ for (QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *>::iterator i(m_engineProfilers.begin());
+ i != m_engineProfilers.end(); ++i) {
+ if (i.value() == profiler && !seen.contains(i.key())) {
+ seen << i.key();
+ traceEnd << idForObject(i.key());
+ }
}
}
}
@@ -326,20 +329,31 @@ void QQmlProfilerService::sendMessages()
}
}
- //indicate completion
- messages << data;
- data.clear();
+ if (m_waitingForStop) {
+ //indicate completion
+ messages << data;
+ data.clear();
- QQmlDebugStream ds(&data, QIODevice::WriteOnly);
- ds << (qint64)-1 << (int)Complete;
- messages << data;
+ QQmlDebugStream ds(&data, QIODevice::WriteOnly);
+ ds << (qint64)-1 << (int)Complete;
+ messages << data;
+ m_waitingForStop = false;
+ }
+
+ emit messagesToClient(name(), messages);
- QQmlDebugService::sendMessages(messages);
+ // Restart flushing if any profilers are still running
+ foreach (const QQmlAbstractProfilerAdapter *profiler, m_engineProfilers) {
+ if (profiler->isRunning()) {
+ emit startFlushTimer();
+ break;
+ }
+ }
}
-void QQmlProfilerService::stateAboutToBeChanged(QQmlDebugService::State newState)
+void QQmlProfilerServiceImpl::stateAboutToBeChanged(QQmlDebugService::State newState)
{
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
if (state() == newState)
return;
@@ -351,9 +365,9 @@ void QQmlProfilerService::stateAboutToBeChanged(QQmlDebugService::State newState
}
}
-void QQmlProfilerService::messageReceived(const QByteArray &message)
+void QQmlProfilerServiceImpl::messageReceived(const QByteArray &message)
{
- QMutexLocker lock(configMutex());
+ QMutexLocker lock(&m_configMutex);
QByteArray rwData = message;
QQmlDebugStream stream(&rwData, QIODevice::ReadOnly);
@@ -361,11 +375,25 @@ void QQmlProfilerService::messageReceived(const QByteArray &message)
int engineId = -1;
quint64 features = std::numeric_limits<quint64>::max();
bool enabled;
+ uint flushInterval = 0;
stream >> enabled;
if (!stream.atEnd())
stream >> engineId;
if (!stream.atEnd())
stream >> features;
+ if (!stream.atEnd()) {
+ stream >> flushInterval;
+ m_flushTimer.setInterval(flushInterval);
+ if (flushInterval > 0) {
+ connect(&m_flushTimer, SIGNAL(timeout()), this, SLOT(flush()));
+ connect(this, SIGNAL(startFlushTimer()), &m_flushTimer, SLOT(start()));
+ connect(this, SIGNAL(stopFlushTimer()), &m_flushTimer, SLOT(stop()));
+ } else {
+ disconnect(&m_flushTimer, SIGNAL(timeout()), this, SLOT(flush()));
+ disconnect(this, SIGNAL(startFlushTimer()), &m_flushTimer, SLOT(start()));
+ disconnect(this, SIGNAL(stopFlushTimer()), &m_flushTimer, SLOT(stop()));
+ }
+ }
// If engineId == -1 objectForId() and then the cast will return 0.
if (enabled)
@@ -376,4 +404,23 @@ void QQmlProfilerService::messageReceived(const QByteArray &message)
stopWaiting();
}
+void QQmlProfilerServiceImpl::flush()
+{
+ QMutexLocker lock(&m_configMutex);
+
+ foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers) {
+ if (profiler->isRunning()) {
+ m_startTimes.insert(-1, profiler);
+ profiler->reportData();
+ }
+ }
+
+ foreach (QQmlAbstractProfilerAdapter *profiler, m_globalProfilers) {
+ if (profiler->isRunning()) {
+ m_startTimes.insert(-1, profiler);
+ profiler->reportData();
+ }
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlprofilerservice_p.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h
index 978d8413a7..9b139ffabb 100644
--- a/src/qml/debugger/qqmlprofilerservice_p.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h
@@ -45,10 +45,10 @@
// We mean it.
//
-#include "qqmlconfigurabledebugservice_p.h"
-#include "qqmlprofilerdefinitions_p.h"
-#include "qqmlabstractprofileradapter_p.h"
-
+#include "qqmlconfigurabledebugservice.h"
+#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qqmlprofilerdefinitions_p.h>
+#include <private/qqmlabstractprofileradapter_p.h>
#include <private/qqmlboundsignal_p.h>
#include <QtCore/qelapsedtimer.h>
@@ -57,6 +57,7 @@
#include <QtCore/qvector.h>
#include <QtCore/qstringbuilder.h>
#include <QtCore/qwaitcondition.h>
+#include <QtCore/qtimer.h>
#include <limits>
@@ -66,12 +67,13 @@ class QUrl;
class QQmlEngine;
-class Q_QML_PRIVATE_EXPORT QQmlProfilerService : public QQmlConfigurableDebugService, public QQmlProfilerDefinitions
+class QQmlProfilerServiceImpl :
+ public QQmlConfigurableDebugService<QQmlProfilerService>,
+ public QQmlProfilerDefinitions
{
Q_OBJECT
public:
- static QQmlProfilerService *instance();
void engineAboutToBeAdded(QQmlEngine *engine);
void engineAboutToBeRemoved(QQmlEngine *engine);
void engineAdded(QQmlEngine *engine);
@@ -83,22 +85,32 @@ public:
void startProfiling(QQmlEngine *engine, quint64 features = std::numeric_limits<quint64>::max());
void stopProfiling(QQmlEngine *engine);
- QQmlProfilerService();
- ~QQmlProfilerService();
+ QQmlProfilerServiceImpl(QObject *parent = 0);
+ ~QQmlProfilerServiceImpl();
void dataReady(QQmlAbstractProfilerAdapter *profiler);
+signals:
+ void startFlushTimer();
+ void stopFlushTimer();
+
+private slots:
+ void flush();
+
protected:
virtual void stateAboutToBeChanged(State state);
virtual void messageReceived(const QByteArray &);
private:
+ friend class QQmlProfilerServiceFactory;
void sendMessages();
void addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QQmlEngine *engine);
void removeProfilerFromStartTimes(const QQmlAbstractProfilerAdapter *profiler);
QElapsedTimer m_timer;
+ QTimer m_flushTimer;
+ bool m_waitingForStop;
QList<QQmlAbstractProfilerAdapter *> m_globalProfilers;
QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *> m_engineProfilers;
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.json b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.json
new file mode 100644
index 0000000000..ec1ec364da
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "CanvasFrameRate", "EngineControl" ]
+}
diff --git a/src/qml/jsruntime/qv4qmlextensions.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.cpp
index c1c4e0ec78..83c2075246 100644
--- a/src/qml/jsruntime/qv4qmlextensions.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.cpp
@@ -31,13 +31,21 @@
**
****************************************************************************/
-#include "qv4qmlextensions_p.h"
-#include "qv4object_p.h"
+#include "qqmlprofilerservice.h"
+#include "qqmlenginecontrolservice.h"
+#include "qqmlprofilerservicefactory.h"
-using namespace QV4;
+QT_BEGIN_NAMESPACE
-void QmlExtensions::markObjects(ExecutionEngine *e)
+QQmlDebugService *QQmlProfilerServiceFactory::create(const QString &key)
{
- if (valueTypeWrapperPrototype)
- valueTypeWrapperPrototype->mark(e);
+ if (key == QQmlProfilerServiceImpl::s_key)
+ return new QQmlProfilerServiceImpl(this);
+
+ if (key == QQmlEngineControlService::s_key)
+ return new QQmlEngineControlService(this);
+
+ return 0;
}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.h
new file mode 100644
index 0000000000..b570136e5b
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservicefactory.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPROFILERSERVICE_H
+#define QQMLPROFILERSERVICE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qqmldebugservicefactory_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlProfilerServiceFactory : public QQmlDebugServiceFactory
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlDebugServiceFactory_iid FILE "qqmlprofilerservice.json")
+public:
+ QQmlDebugService *create(const QString &key);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPROFILERSERVICE_H
diff --git a/src/qml/debugger/qv4profileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
index 2b8183dc69..24e01f4c68 100644
--- a/src/qml/debugger/qv4profileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
@@ -31,14 +31,13 @@
**
****************************************************************************/
-#include "qv4profileradapter_p.h"
-#include "qqmlprofilerservice_p.h"
-#include "qqmldebugservice_p.h"
+#include "qv4profileradapter.h"
+#include "qqmlprofilerservice.h"
QT_BEGIN_NAMESPACE
QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::ExecutionEngine *engine) :
- QQmlAbstractProfilerAdapter(service)
+ QQmlAbstractProfilerAdapter(service), dataPos(0), memoryPos(0)
{
engine->enableProfiler();
connect(this, SIGNAL(profilingEnabled(quint64)),
@@ -51,45 +50,63 @@ QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::Execut
connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
engine->profiler, SLOT(setTimer(QElapsedTimer)));
- connect(engine->profiler, SIGNAL(dataReady(QList<QV4::Profiling::FunctionCallProperties>,
- QList<QV4::Profiling::MemoryAllocationProperties>)),
- this, SLOT(receiveData(QList<QV4::Profiling::FunctionCallProperties>,
- QList<QV4::Profiling::MemoryAllocationProperties>)));
+ connect(engine->profiler, SIGNAL(dataReady(QVector<QV4::Profiling::FunctionCallProperties>,
+ QVector<QV4::Profiling::MemoryAllocationProperties>)),
+ this, SLOT(receiveData(QVector<QV4::Profiling::FunctionCallProperties>,
+ QVector<QV4::Profiling::MemoryAllocationProperties>)));
}
qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &messages)
{
QByteArray message;
- while (!memory_data.empty() && memory_data.front().timestamp <= until) {
+ while (memory_data.length() > memoryPos && memory_data[memoryPos].timestamp <= until) {
QQmlDebugStream d(&message, QIODevice::WriteOnly);
- QV4::Profiling::MemoryAllocationProperties &props = memory_data.front();
+ QV4::Profiling::MemoryAllocationProperties &props = memory_data[memoryPos];
d << props.timestamp << MemoryAllocation << props.type << props.size;
- memory_data.pop_front();
+ ++memoryPos;
messages.append(message);
}
- return memory_data.empty() ? -1 : memory_data.front().timestamp;
+ return memory_data.length() == memoryPos ? -1 : memory_data[memoryPos].timestamp;
+}
+
+qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &messages,
+ qint64 callNext)
+{
+ if (callNext == -1) {
+ data.clear();
+ dataPos = 0;
+ }
+
+ qint64 memoryNext = appendMemoryEvents(until, messages);
+
+ if (memoryNext == -1) {
+ memory_data.clear();
+ memoryPos = 0;
+ return callNext;
+ }
+
+ return callNext == -1 ? memoryNext : qMin(callNext, memoryNext);
}
qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
{
QByteArray message;
while (true) {
- while (!stack.empty() && (data.empty() || stack.top() <= data.front().start)) {
- if (stack.top() > until) {
- qint64 memory_next = appendMemoryEvents(until, messages);
- return memory_next == -1 ? stack.top() : qMin(stack.top(), memory_next);
- }
+ while (!stack.isEmpty() && (dataPos == data.length() ||
+ stack.top() <= data[dataPos].start)) {
+ if (stack.top() > until)
+ return finalizeMessages(until, messages, stack.top());
+
appendMemoryEvents(stack.top(), messages);
QQmlDebugStream d(&message, QIODevice::WriteOnly);
d << stack.pop() << RangeEnd << Javascript;
messages.append(message);
}
- while (!data.empty() && (stack.empty() || data.front().start < stack.top())) {
- const QV4::Profiling::FunctionCallProperties &props = data.front();
- if (props.start > until) {
- qint64 memory_next = appendMemoryEvents(until, messages);
- return memory_next == -1 ? props.start : qMin(props.start, memory_next);
- }
+ while (dataPos != data.length() && (stack.empty() || data[dataPos].start < stack.top())) {
+ const QV4::Profiling::FunctionCallProperties &props = data[dataPos];
+ if (props.start > until)
+ return finalizeMessages(until, messages, props.start);
+
appendMemoryEvents(props.start, messages);
QQmlDebugStream d_start(&message, QIODevice::WriteOnly);
@@ -106,19 +123,30 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message
messages.push_back(message);
message.clear();
stack.push(props.end);
- data.pop_front();
+ ++dataPos;
}
- if (stack.empty() && data.empty())
- return appendMemoryEvents(until, messages);
+ if (stack.empty() && dataPos == data.length())
+ return finalizeMessages(until, messages, -1);
}
}
-void QV4ProfilerAdapter::receiveData(const QList<QV4::Profiling::FunctionCallProperties> &new_data,
- const QList<QV4::Profiling::MemoryAllocationProperties> &new_memory_data)
+void QV4ProfilerAdapter::receiveData(
+ const QVector<QV4::Profiling::FunctionCallProperties> &new_data,
+ const QVector<QV4::Profiling::MemoryAllocationProperties> &new_memory_data)
{
- data = new_data;
- memory_data = new_memory_data;
- stack.clear();
+ // In rare cases it could be that another flush or stop event is processed while data from
+ // the previous one is still pending. In that case we just append the data.
+
+ if (data.isEmpty())
+ data = new_data;
+ else
+ data.append(new_data);
+
+ if (memory_data.isEmpty())
+ memory_data = new_memory_data;
+ else
+ memory_data.append(new_memory_data);
+
service->dataReady(this);
}
diff --git a/src/qml/debugger/qv4profileradapter_p.h b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
index 2f467f4beb..cea3da72e3 100644
--- a/src/qml/debugger/qv4profileradapter_p.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
@@ -45,8 +45,8 @@
// We mean it.
//
-#include "qv4profiling_p.h"
-#include "qqmlabstractprofileradapter_p.h"
+#include <private/qv4profiling_p.h>
+#include <private/qqmlabstractprofileradapter_p.h>
#include <QStack>
#include <QList>
@@ -63,14 +63,17 @@ public:
virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
public slots:
- void receiveData(const QList<QV4::Profiling::FunctionCallProperties> &,
- const QList<QV4::Profiling::MemoryAllocationProperties> &);
+ void receiveData(const QVector<QV4::Profiling::FunctionCallProperties> &,
+ const QVector<QV4::Profiling::MemoryAllocationProperties> &);
private:
- QList<QV4::Profiling::FunctionCallProperties> data;
- QList<QV4::Profiling::MemoryAllocationProperties> memory_data;
+ QVector<QV4::Profiling::FunctionCallProperties> data;
+ QVector<QV4::Profiling::MemoryAllocationProperties> memory_data;
+ int dataPos;
+ int memoryPos;
QStack<qint64> stack;
qint64 appendMemoryEvents(qint64 until, QList<QByteArray> &messages);
+ qint64 finalizeMessages(qint64 until, QList<QByteArray> &messages, qint64 callNext);
};
QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro b/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro
deleted file mode 100644
index 2ee0d703b2..0000000000
--- a/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro
+++ /dev/null
@@ -1,27 +0,0 @@
-TARGET = qmldbg_qtquick2
-QT += qml-private quick-private core-private gui-private
-
-PLUGIN_TYPE = qmltooling
-PLUGIN_CLASS_NAME = QtQuick2Plugin
-load(qt_plugin)
-
-INCLUDEPATH *= $$PWD $$PWD/../shared
-
-SOURCES += \
- qtquick2plugin.cpp \
- highlight.cpp \
- qquickviewinspector.cpp \
- ../shared/abstracttool.cpp \
- ../shared/abstractviewinspector.cpp \
- inspecttool.cpp
-
-HEADERS += \
- qtquick2plugin.h \
- highlight.h \
- qquickviewinspector.h \
- ../shared/abstracttool.h \
- ../shared/abstractviewinspector.h \
- ../shared/qmlinspectorconstants.h \
- inspecttool.h
-
-OTHER_FILES += qtquick2plugin.json
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.cpp b/src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.cpp
deleted file mode 100644
index 88801ec9db..0000000000
--- a/src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qtquick2plugin.h"
-#include "qquickviewinspector.h"
-
-#include <QtCore/qplugin.h>
-#include <QtQml/private/qqmlinspectorservice_p.h>
-#include <QtQuick/QQuickView>
-
-namespace QmlJSDebugger {
-namespace QtQuick2 {
-
-QtQuick2Plugin::QtQuick2Plugin() :
- m_inspector(0)
-{
-}
-
-QtQuick2Plugin::~QtQuick2Plugin()
-{
- delete m_inspector;
-}
-
-bool QtQuick2Plugin::canHandleView(QObject *view)
-{
- return qobject_cast<QQuickView*>(view);
-}
-
-void QtQuick2Plugin::activate(QObject *view)
-{
- QQuickView *qtQuickView = qobject_cast<QQuickView*>(view);
- Q_ASSERT(qtQuickView);
- m_inspector = new QQuickViewInspector(qtQuickView, qtQuickView);
-}
-
-void QtQuick2Plugin::deactivate()
-{
- delete m_inspector;
-}
-
-void QtQuick2Plugin::clientMessage(const QByteArray &message)
-{
- if (m_inspector)
- m_inspector->handleMessage(message);
-}
-
-} // namespace QtQuick2
-} // namespace QmlJSDebugger
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.h b/src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.h
deleted file mode 100644
index 6866e74aa1..0000000000
--- a/src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QTQUICK2PLUGINPLUGIN_H
-#define QTQUICK2PLUGINPLUGIN_H
-
-#include <QtCore/QPointer>
-#include <QtQml/private/qqmlinspectorinterface_p.h>
-
-namespace QmlJSDebugger {
-
-class AbstractViewInspector;
-
-namespace QtQuick2 {
-
-class QtQuick2Plugin : public QObject, public QQmlInspectorInterface
-{
- Q_OBJECT
- Q_DISABLE_COPY(QtQuick2Plugin)
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlInspectorInterface")
- Q_INTERFACES(QQmlInspectorInterface)
-
-public:
- QtQuick2Plugin();
- ~QtQuick2Plugin();
-
- // QQmlInspectorInterface
- bool canHandleView(QObject *view);
- void activate(QObject *view);
- void deactivate();
- void clientMessage(const QByteArray &message);
-
-private:
- QPointer<AbstractViewInspector> m_inspector;
-};
-
-} // namespace QtQuick2
-} // namespace QmlJSDebugger
-
-#endif // QTQUICK2PLUGINPLUGIN_H
diff --git a/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro b/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro
new file mode 100644
index 0000000000..5e2d0874df
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_server/qmldbg_server.pro
@@ -0,0 +1,22 @@
+TARGET = qmldbg_server
+QT = qml-private core-private
+
+PLUGIN_TYPE = qmltooling
+PLUGIN_CLASS_NAME = QQmlDebugServerFactory
+load(qt_plugin)
+
+SOURCES += \
+ $$PWD/qqmldebugserver.cpp \
+ $$PWD/../shared/qpacketprotocol.cpp
+
+HEADERS += \
+ $$PWD/qqmldebugserverfactory.h \
+ $$PWD/../shared/qqmldebugserver.h \
+ $$PWD/../shared/qpacketprotocol.h \
+ $$PWD/../shared/qqmldebugserverconnection.h
+
+INCLUDEPATH += $$PWD \
+ $$PWD/../shared
+
+OTHER_FILES += \
+ qqmldebugserver.json
diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
new file mode 100644
index 0000000000..69d36beaca
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
@@ -0,0 +1,693 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmldebugserver.h"
+#include "qqmldebugserverfactory.h"
+#include "qpacketprotocol.h"
+#include "qqmldebugserverconnection.h"
+
+#include <private/qqmldebugservice_p.h>
+#include <private/qqmlengine_p.h>
+#include <private/qqmlglobal_p.h>
+#include <private/qqmldebugpluginmanager_p.h>
+
+#include <QtCore/QAtomicInt>
+#include <QtCore/QDir>
+#include <QtCore/QPluginLoader>
+#include <QtCore/QStringList>
+#include <QtCore/qwaitcondition.h>
+
+#include <private/qobject_p.h>
+#include <private/qcoreapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ QQmlDebug Protocol (Version 1):
+
+ handshake:
+ 1. Client sends
+ "QDeclarativeDebugServer" 0 version pluginNames [QDataStream version]
+ version: an int representing the highest protocol version the client knows
+ pluginNames: plugins available on client side
+ 2. Server sends
+ "QDeclarativeDebugClient" 0 version pluginNames pluginVersions [QDataStream version]
+ version: an int representing the highest protocol version the client & server know
+ pluginNames: plugins available on server side. plugins both in the client and server message are enabled.
+ client plugin advertisement
+ 1. Client sends
+ "QDeclarativeDebugServer" 1 pluginNames
+ server plugin advertisement (not implemented: all services are required to register before open())
+ 1. Server sends
+ "QDeclarativeDebugClient" 1 pluginNames pluginVersions
+ plugin communication:
+ Everything send with a header different to "QDeclarativeDebugServer" is sent to the appropriate plugin.
+ */
+
+Q_QML_DEBUG_PLUGIN_LOADER(QQmlDebugServerConnection)
+Q_QML_IMPORT_DEBUG_PLUGIN(QTcpServerConnectionFactory)
+Q_QML_IMPORT_DEBUG_PLUGIN(QLocalClientConnectionFactory)
+
+const int protocolVersion = 1;
+
+class QQmlDebugServerImpl;
+class QQmlDebugServerThread : public QThread
+{
+public:
+ QQmlDebugServerThread() : m_server(0), m_portFrom(-1), m_portTo(-1) {}
+
+ void setServer(QQmlDebugServerImpl *server)
+ {
+ m_server = server;
+ }
+
+ void setPortRange(int portFrom, int portTo, const QString &hostAddress)
+ {
+ m_pluginName = QLatin1String("QTcpServerConnection");
+ m_portFrom = portFrom;
+ m_portTo = portTo;
+ m_hostAddress = hostAddress;
+ }
+
+ void setFileName(const QString &fileName)
+ {
+ m_pluginName = QLatin1String("QLocalClientConnection");
+ m_fileName = fileName;
+ }
+
+ void run();
+
+private:
+ QQmlDebugServerImpl *m_server;
+ QString m_pluginName;
+ int m_portFrom;
+ int m_portTo;
+ QString m_hostAddress;
+ QString m_fileName;
+};
+
+class QQmlDebugServerImpl : public QQmlDebugServer
+{
+ Q_OBJECT
+public:
+ QQmlDebugServerImpl();
+
+ bool blockingMode() const;
+
+ QQmlDebugService *service(const QString &name) const;
+
+ void addEngine(QQmlEngine *engine);
+ void removeEngine(QQmlEngine *engine);
+
+ bool addService(const QString &name, QQmlDebugService *service);
+ bool removeService(const QString &name);
+
+ bool open(const QVariantHash &configuration);
+ void setDevice(QIODevice *socket);
+
+ void parseArguments();
+
+ static void cleanup();
+
+private slots:
+ void wakeEngine(QQmlEngine *engine);
+ void sendMessage(const QString &name, const QByteArray &message);
+ void sendMessages(const QString &name, const QList<QByteArray> &messages);
+ void changeServiceState(const QString &serviceName, QQmlDebugService::State state);
+ void removeThread();
+ void receiveMessage();
+ void invalidPacket();
+
+private:
+ friend class QQmlDebugServerThread;
+ friend class QQmlDebugServerFactory;
+
+ class EngineCondition {
+ public:
+ EngineCondition() : numServices(0), condition(new QWaitCondition) {}
+
+ bool waitForServices(QMutex *locked, int numEngines);
+
+ void wake();
+ private:
+ int numServices;
+
+ // shared pointer to allow for QHash-inflicted copying.
+ QSharedPointer<QWaitCondition> condition;
+ };
+
+ bool canSendMessage(const QString &name);
+ void doSendMessage(const QString &name, const QByteArray &message);
+
+ QQmlDebugServerConnection *m_connection;
+ QHash<QString, QQmlDebugService *> m_plugins;
+ QStringList m_clientPlugins;
+ bool m_gotHello;
+ bool m_blockingMode;
+
+ QHash<QQmlEngine *, EngineCondition> m_engineConditions;
+
+ QMutex m_helloMutex;
+ QWaitCondition m_helloCondition;
+ QQmlDebugServerThread m_thread;
+ QPacketProtocol *m_protocol;
+ QAtomicInt m_changeServiceStateCalls;
+};
+
+void QQmlDebugServerImpl::cleanup()
+{
+ QQmlDebugServerImpl *server = static_cast<QQmlDebugServerImpl *>(
+ QQmlDebugConnector::instance());
+ if (!server)
+ return;
+
+ for (QHash<QString, QQmlDebugService *>::ConstIterator i = server->m_plugins.constBegin();
+ i != server->m_plugins.constEnd(); ++i) {
+ server->m_changeServiceStateCalls.ref();
+ QMetaObject::invokeMethod(server, "changeServiceState", Qt::QueuedConnection,
+ Q_ARG(QString, i.key()),
+ Q_ARG(QQmlDebugService::State,
+ QQmlDebugService::NotConnected));
+ }
+
+ // Wait for changeServiceState calls to finish
+ // (while running an event loop because some services
+ // might again use slots to execute stuff in the GUI thread)
+ QEventLoop loop;
+ while (!server->m_changeServiceStateCalls.testAndSetOrdered(0, 0))
+ loop.processEvents();
+
+ // Stop the thread while the application is still there.
+ server->m_thread.exit();
+ server->m_thread.wait();
+}
+
+void QQmlDebugServerThread::run()
+{
+ Q_ASSERT_X(m_server != 0, Q_FUNC_INFO, "There should always be a debug server available here.");
+ QQmlDebugServerConnection *connection = loadQQmlDebugServerConnection(m_pluginName);
+ if (connection) {
+ {
+ QMutexLocker connectionLocker(&m_server->m_helloMutex);
+ m_server->m_connection = connection;
+ connection->setServer(m_server);
+ m_server->m_helloCondition.wakeAll();
+ }
+
+ if (m_fileName.isEmpty()) {
+ if (!connection->setPortRange(m_portFrom, m_portTo, m_server->blockingMode(),
+ m_hostAddress))
+ return;
+ } else if (!connection->setFileName(m_fileName, m_server->blockingMode())) {
+ return;
+ }
+
+ if (m_server->blockingMode())
+ connection->waitForConnection();
+ } else {
+ qWarning() << "QML Debugger: Couldn't load plugin" << m_pluginName;
+ return;
+ }
+
+ exec();
+
+ // make sure events still waiting are processed
+ QEventLoop eventLoop;
+ eventLoop.processEvents(QEventLoop::AllEvents);
+}
+
+bool QQmlDebugServerImpl::blockingMode() const
+{
+ return m_blockingMode;
+}
+
+static void cleanupOnShutdown()
+{
+ // We cannot do this in the destructor as the connection plugin will get unloaded before the
+ // server plugin and we need the connection to send any remaining data. This function is
+ // triggered before any plugins are unloaded.
+ QQmlDebugServerImpl::cleanup();
+}
+
+QQmlDebugServerImpl::QQmlDebugServerImpl() :
+ m_connection(0),
+ m_gotHello(false),
+ m_blockingMode(false)
+{
+ static bool postRoutineAdded = false;
+ if (!postRoutineAdded) {
+ qAddPostRoutine(cleanupOnShutdown);
+ postRoutineAdded = true;
+ }
+
+ // used in sendMessages
+ qRegisterMetaType<QList<QByteArray> >("QList<QByteArray>");
+ // used in changeServiceState
+ qRegisterMetaType<QQmlDebugService::State>("QQmlDebugService::State");
+
+ m_thread.setServer(this);
+ moveToThread(&m_thread);
+
+ // Remove the thread immmediately when it finishes, so that we don't have to wait for the
+ // event loop to signal that.
+ QObject::connect(&m_thread, SIGNAL(finished()), this, SLOT(removeThread()),
+ Qt::DirectConnection);
+ m_thread.setObjectName(QStringLiteral("QQmlDebugServerThread"));
+ parseArguments();
+}
+
+bool QQmlDebugServerImpl::open(const QVariantHash &configuration = QVariantHash())
+{
+ if (m_thread.isRunning())
+ return false;
+ if (!configuration.isEmpty()) {
+ m_blockingMode = configuration[QLatin1String("block")].toBool();
+ if (configuration.contains(QLatin1String("portFrom"))) {
+ int portFrom = configuration[QLatin1String("portFrom")].toInt();
+ int portTo = configuration[QLatin1String("portTo")].toInt();
+ m_thread.setPortRange(portFrom, portTo == -1 ? portFrom : portTo,
+ configuration[QLatin1String("hostAddress")].toString());
+ } else if (configuration.contains(QLatin1String("fileName"))) {
+ m_thread.setFileName(configuration[QLatin1String("fileName")].toString());
+ } else {
+ return false;
+ }
+ }
+
+ QMutexLocker locker(&m_helloMutex);
+ m_thread.start();
+ m_helloCondition.wait(&m_helloMutex); // wait for connection
+ if (m_blockingMode && !m_gotHello)
+ m_helloCondition.wait(&m_helloMutex); // wait for hello
+ return true;
+}
+
+void QQmlDebugServerImpl::parseArguments()
+{
+ // format: qmljsdebugger=port:<port_from>[,port_to],host:<ip address>][,block]
+ const QString args = commandLineArguments();
+ if (args.isEmpty())
+ return; // Manual initialization, through QQmlDebugServer::open()
+
+ // ### remove port definition when protocol is changed
+ int portFrom = 0;
+ int portTo = 0;
+ bool block = false;
+ bool ok = false;
+ QString hostAddress;
+ QString fileName;
+ QStringList services;
+
+ const QStringList lstjsDebugArguments = args.split(QLatin1Char(','));
+ QStringList::const_iterator argsItEnd = lstjsDebugArguments.cend();
+ QStringList::const_iterator argsIt = lstjsDebugArguments.cbegin();
+ for (; argsIt != argsItEnd; ++argsIt) {
+ const QString strArgument = *argsIt;
+ if (strArgument.startsWith(QLatin1String("port:"))) {
+ portFrom = strArgument.mid(5).toInt(&ok);
+ portTo = portFrom;
+ QStringList::const_iterator argsNext = argsIt + 1;
+ if (argsNext == argsItEnd)
+ break;
+ const QString nextArgument = *argsNext;
+
+ // Don't use QStringLiteral here. QRegExp has a global cache and will save an implicitly
+ // shared copy of the passed string. That copy isn't properly detached when the library
+ // is unloaded if the original string lives in the library's .rodata
+ if (ok && nextArgument.contains(QRegExp(QLatin1String("^\\s*\\d+\\s*$")))) {
+ portTo = nextArgument.toInt(&ok);
+ ++argsIt;
+ }
+ } else if (strArgument.startsWith(QLatin1String("host:"))) {
+ hostAddress = strArgument.mid(5);
+ } else if (strArgument == QLatin1String("block")) {
+ block = true;
+ } else if (strArgument.startsWith(QLatin1String("file:"))) {
+ fileName = strArgument.mid(5);
+ ok = !fileName.isEmpty();
+ } else if (strArgument.startsWith(QLatin1String("services:"))) {
+ services.append(strArgument.mid(9));
+ } else if (!services.isEmpty()) {
+ services.append(strArgument);
+ } else {
+ qWarning() << QString::fromLatin1("QML Debugger: Invalid argument '%1' "
+ "detected. Ignoring the same.")
+ .arg(strArgument);
+ }
+ }
+
+ if (ok) {
+ setServices(services);
+ m_blockingMode = block;
+ if (!fileName.isEmpty())
+ m_thread.setFileName(fileName);
+ else
+ m_thread.setPortRange(portFrom, portTo, hostAddress);
+ } else {
+ qWarning() << QString::fromLatin1("QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
+ "Format is qmljsdebugger=port:<port_from>[,port_to],host:"
+ "<ip address>][,block]").arg(args);
+ }
+}
+
+void QQmlDebugServerImpl::receiveMessage()
+{
+ typedef QHash<QString, QQmlDebugService*>::const_iterator DebugServiceConstIt;
+
+ // to be executed in debugger thread
+ Q_ASSERT(QThread::currentThread() == thread());
+
+ if (!m_protocol)
+ return;
+
+ QQmlDebugStream in(m_protocol->read().data());
+
+ QString name;
+
+ in >> name;
+ if (name == QLatin1String("QDeclarativeDebugServer")) {
+ int op = -1;
+ in >> op;
+ if (op == 0) {
+ int version;
+ in >> version >> m_clientPlugins;
+
+ //Get the supported QDataStream version
+ if (!in.atEnd()) {
+ in >> QQmlDebugStream::s_dataStreamVersion;
+ if (QQmlDebugStream::s_dataStreamVersion > QDataStream().version())
+ QQmlDebugStream::s_dataStreamVersion = QDataStream().version();
+ }
+
+ // Send the hello answer immediately, since it needs to arrive before
+ // the plugins below start sending messages.
+
+ QByteArray helloAnswer;
+ QQmlDebugStream out(&helloAnswer, QIODevice::WriteOnly);
+ QStringList pluginNames;
+ QList<float> pluginVersions;
+ const int count = m_plugins.count();
+ pluginNames.reserve(count);
+ pluginVersions.reserve(count);
+ for (QHash<QString, QQmlDebugService *>::ConstIterator i = m_plugins.constBegin();
+ i != m_plugins.constEnd(); ++i) {
+ pluginNames << i.key();
+ pluginVersions << i.value()->version();
+ }
+
+ out << QString(QStringLiteral("QDeclarativeDebugClient")) << 0 << protocolVersion
+ << pluginNames << pluginVersions << QQmlDebugStream::s_dataStreamVersion;
+
+ QPacket pack;
+ pack.writeRawData(helloAnswer.data(), helloAnswer.length());
+ m_protocol->send(pack);
+ m_connection->flush();
+
+ QMutexLocker helloLock(&m_helloMutex);
+ m_gotHello = true;
+
+ for (DebugServiceConstIt iter = m_plugins.constBegin(), cend = m_plugins.constEnd(); iter != cend; ++iter) {
+ QQmlDebugService::State newState = QQmlDebugService::Unavailable;
+ if (m_clientPlugins.contains(iter.key()))
+ newState = QQmlDebugService::Enabled;
+ m_changeServiceStateCalls.ref();
+ changeServiceState(iter.key(), newState);
+ }
+
+ m_helloCondition.wakeAll();
+
+ } else if (op == 1) {
+ // Service Discovery
+ QStringList oldClientPlugins = m_clientPlugins;
+ in >> m_clientPlugins;
+
+ for (DebugServiceConstIt iter = m_plugins.constBegin(), cend = m_plugins.constEnd(); iter != cend; ++iter) {
+ const QString pluginName = iter.key();
+ QQmlDebugService::State newState = QQmlDebugService::Unavailable;
+ if (m_clientPlugins.contains(pluginName))
+ newState = QQmlDebugService::Enabled;
+
+ if (oldClientPlugins.contains(pluginName)
+ != m_clientPlugins.contains(pluginName)) {
+ m_changeServiceStateCalls.ref();
+ changeServiceState(iter.key(), newState);
+ }
+ }
+
+ } else {
+ qWarning("QML Debugger: Invalid control message %d.", op);
+ invalidPacket();
+ return;
+ }
+
+ } else {
+ if (m_gotHello) {
+ QByteArray message;
+ in >> message;
+
+ QHash<QString, QQmlDebugService *>::Iterator iter = m_plugins.find(name);
+ if (iter == m_plugins.end()) {
+ qWarning() << "QML Debugger: Message received for missing plugin" << name << '.';
+ } else {
+ (*iter)->messageReceived(message);
+ }
+ } else {
+ qWarning("QML Debugger: Invalid hello message.");
+ }
+
+ }
+}
+
+void QQmlDebugServerImpl::changeServiceState(const QString &serviceName,
+ QQmlDebugService::State newState)
+{
+ // to be executed in debugger thread
+ Q_ASSERT(QThread::currentThread() == thread());
+
+ QQmlDebugService *service = m_plugins.value(serviceName);
+ if (service && service->state() != newState) {
+ service->stateAboutToBeChanged(newState);
+ service->setState(newState);
+ service->stateChanged(newState);
+ }
+
+ m_changeServiceStateCalls.deref();
+}
+
+void QQmlDebugServerImpl::removeThread()
+{
+ Q_ASSERT(m_thread.isFinished());
+ Q_ASSERT(QThread::currentThread() == thread());
+
+ QThread *parentThread = m_thread.thread();
+
+ delete m_connection;
+ m_connection = 0;
+
+ // Move it back to the parent thread so that we can potentially restart it on a new thread.
+ moveToThread(parentThread);
+}
+
+QQmlDebugService *QQmlDebugServerImpl::service(const QString &name) const
+{
+ return m_plugins.value(name);
+}
+
+void QQmlDebugServerImpl::addEngine(QQmlEngine *engine)
+{
+ // to be executed outside of debugger thread
+ Q_ASSERT(QThread::currentThread() != &m_thread);
+
+ QMutexLocker locker(&m_helloMutex);
+ foreach (QQmlDebugService *service, m_plugins)
+ service->engineAboutToBeAdded(engine);
+
+ m_engineConditions[engine].waitForServices(&m_helloMutex, m_plugins.count());
+
+ foreach (QQmlDebugService *service, m_plugins)
+ service->engineAdded(engine);
+}
+
+void QQmlDebugServerImpl::removeEngine(QQmlEngine *engine)
+{
+ // to be executed outside of debugger thread
+ Q_ASSERT(QThread::currentThread() != &m_thread);
+
+ QMutexLocker locker(&m_helloMutex);
+ foreach (QQmlDebugService *service, m_plugins)
+ service->engineAboutToBeRemoved(engine);
+
+ m_engineConditions[engine].waitForServices(&m_helloMutex, m_plugins.count());
+
+ foreach (QQmlDebugService *service, m_plugins)
+ service->engineRemoved(engine);
+}
+
+bool QQmlDebugServerImpl::addService(const QString &name, QQmlDebugService *service)
+{
+ // to be executed before thread starts
+ Q_ASSERT(!m_thread.isRunning());
+
+ if (!service || m_plugins.contains(name))
+ return false;
+
+ connect(service, SIGNAL(messageToClient(QString,QByteArray)),
+ this, SLOT(sendMessage(QString,QByteArray)));
+ connect(service, SIGNAL(messagesToClient(QString,QList<QByteArray>)),
+ this, SLOT(sendMessages(QString,QList<QByteArray>)));
+
+ connect(service, SIGNAL(attachedToEngine(QQmlEngine*)),
+ this, SLOT(wakeEngine(QQmlEngine*)), Qt::QueuedConnection);
+ connect(service, SIGNAL(detachedFromEngine(QQmlEngine*)),
+ this, SLOT(wakeEngine(QQmlEngine*)), Qt::QueuedConnection);
+
+ service->setState(QQmlDebugService::Unavailable);
+ m_plugins.insert(name, service);
+
+ return true;
+}
+
+bool QQmlDebugServerImpl::removeService(const QString &name)
+{
+ // to be executed after thread ends
+ Q_ASSERT(!m_thread.isRunning());
+
+ QQmlDebugService *service = m_plugins.value(name);
+ if (!service)
+ return false;
+
+ m_plugins.remove(name);
+ service->setState(QQmlDebugService::NotConnected);
+
+ disconnect(service, SIGNAL(detachedFromEngine(QQmlEngine*)),
+ this, SLOT(wakeEngine(QQmlEngine*)));
+ disconnect(service, SIGNAL(attachedToEngine(QQmlEngine*)),
+ this, SLOT(wakeEngine(QQmlEngine*)));
+
+ disconnect(service, SIGNAL(messagesToClient(QString,QList<QByteArray>)),
+ this, SLOT(sendMessages(QString,QList<QByteArray>)));
+ disconnect(service, SIGNAL(messageToClient(QString,QByteArray)),
+ this, SLOT(sendMessage(QString,QByteArray)));
+
+ m_plugins.remove(service->name());
+
+ return true;
+}
+
+bool QQmlDebugServerImpl::canSendMessage(const QString &name)
+{
+ // to be executed in debugger thread
+ Q_ASSERT(QThread::currentThread() == thread());
+ return m_connection && m_connection->isConnected() && m_protocol &&
+ m_clientPlugins.contains(name);
+}
+
+void QQmlDebugServerImpl::doSendMessage(const QString &name, const QByteArray &message)
+{
+ QByteArray prefixed;
+ QQmlDebugStream out(&prefixed, QIODevice::WriteOnly);
+ out << name << message;
+
+ QPacket pack;
+ pack.writeRawData(prefixed.data(), prefixed.length());
+ m_protocol->send(pack);
+}
+
+void QQmlDebugServerImpl::sendMessage(const QString &name, const QByteArray &message)
+{
+ if (canSendMessage(name)) {
+ doSendMessage(name, message);
+ m_connection->flush();
+ }
+}
+
+void QQmlDebugServerImpl::sendMessages(const QString &name, const QList<QByteArray> &messages)
+{
+ if (canSendMessage(name)) {
+ foreach (const QByteArray &message, messages)
+ doSendMessage(name, message);
+ m_connection->flush();
+ }
+}
+
+void QQmlDebugServerImpl::wakeEngine(QQmlEngine *engine)
+{
+ // to be executed in debugger thread
+ Q_ASSERT(QThread::currentThread() == thread());
+
+ QMutexLocker locker(&m_helloMutex);
+ m_engineConditions[engine].wake();
+}
+
+bool QQmlDebugServerImpl::EngineCondition::waitForServices(QMutex *locked, int num)
+{
+ Q_ASSERT_X(numServices == 0, Q_FUNC_INFO, "Request to wait again before previous wait finished");
+ numServices = num;
+ return numServices > 0 ? condition->wait(locked) : true;
+}
+
+void QQmlDebugServerImpl::EngineCondition::wake()
+{
+ if (--numServices == 0)
+ condition->wakeAll();
+ Q_ASSERT_X(numServices >=0, Q_FUNC_INFO, "Woken more often than #services.");
+}
+
+void QQmlDebugServerImpl::setDevice(QIODevice *socket)
+{
+ m_protocol = new QPacketProtocol(socket, this);
+ QObject::connect(m_protocol, SIGNAL(readyRead()), this, SLOT(receiveMessage()));
+ QObject::connect(m_protocol, SIGNAL(invalidPacket()), this, SLOT(invalidPacket()));
+
+ if (blockingMode())
+ m_protocol->waitForReadyRead(-1);
+}
+
+void QQmlDebugServerImpl::invalidPacket()
+{
+ qWarning("QML Debugger: Received a corrupted packet! Giving up ...");
+ m_connection->disconnect();
+ // protocol might still be processing packages at this point
+ m_protocol->deleteLater();
+ m_protocol = 0;
+}
+
+QQmlDebugConnector *QQmlDebugServerFactory::create(const QString &key)
+{
+ // Cannot parent it to this because it gets moved to another thread
+ return (key == QLatin1String("QQmlDebugServer") ? new QQmlDebugServerImpl : 0);
+}
+
+QT_END_NAMESPACE
+
+#include "qqmldebugserver.moc"
diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.json b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.json
new file mode 100644
index 0000000000..9b8dd3ae79
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "QQmlDebugServer" ]
+}
diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserverfactory.h b/src/plugins/qmltooling/qmldbg_server/qqmldebugserverfactory.h
new file mode 100644
index 0000000000..825a71bab8
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserverfactory.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLDEBUGSERVERFACTORY_H
+#define QQMLDEBUGSERVERFACTORY_H
+
+#include <private/qqmldebugconnector_p.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// ementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlDebugServerFactory : public QQmlDebugConnectorFactory
+{
+ Q_OBJECT
+
+ // The interface for the code that loads this thing is QQmlDebugConnector.
+ // QQmlDebugServer is for connection plugins.
+ Q_PLUGIN_METADATA(IID QQmlDebugConnectorFactory_iid FILE "qqmldebugserver.json")
+public:
+ QQmlDebugConnector *create(const QString &key);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLDEBUGSERVERFACTORY_H
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pri b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pri
deleted file mode 100644
index 4b78707c3d..0000000000
--- a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pri
+++ /dev/null
@@ -1,14 +0,0 @@
-QT += network core-private
-
-SOURCES += \
- $$PWD/qtcpserverconnection.cpp \
- $$PWD/../shared/qpacketprotocol.cpp
-
-HEADERS += \
- $$PWD/qtcpserverconnection.h \
- $$PWD/../shared/qpacketprotocol.h
-
-INCLUDEPATH += $$PWD \
- $$PWD/../shared
-
-OTHER_FILES += $$PWD/qtcpserverconnection.json
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
index e1284b7233..fd419aeb56 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
+++ b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
@@ -1,8 +1,20 @@
TARGET = qmldbg_tcp
-QT = qml-private core-private
+QT = qml-private network
PLUGIN_TYPE = qmltooling
-PLUGIN_CLASS_NAME = QTcpServerConnection
+PLUGIN_CLASS_NAME = QTcpServerConnectionFactory
load(qt_plugin)
-include(qmldbg_tcp.pri)
+SOURCES += \
+ $$PWD/qtcpserverconnection.cpp
+
+HEADERS += \
+ $$PWD/qtcpserverconnectionfactory.h \
+ $$PWD/../shared/qqmldebugserver.h \
+ $$PWD/../shared/qqmldebugserverconnection.h
+
+INCLUDEPATH += $$PWD \
+ $$PWD/../shared
+
+OTHER_FILES += \
+ $$PWD/qtcpserverconnection.json
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
index 2ae4edfce4..c8010a4aa9 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
@@ -31,136 +31,125 @@
**
****************************************************************************/
-#include "qtcpserverconnection.h"
-#include "qpacketprotocol.h"
+#include "qtcpserverconnectionfactory.h"
+#include "qqmldebugserver.h"
#include <QtCore/qplugin.h>
#include <QtNetwork/qtcpserver.h>
#include <QtNetwork/qtcpsocket.h>
-#include <private/qqmldebugserver_p.h>
-
QT_BEGIN_NAMESPACE
-class QTcpServerConnectionPrivate {
+class QTcpServerConnection : public QQmlDebugServerConnection
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QTcpServerConnection)
+
public:
- QTcpServerConnectionPrivate();
+ QTcpServerConnection();
+ ~QTcpServerConnection();
- int portFrom;
- int portTo;
- bool block;
- QString hostaddress;
- QTcpSocket *socket;
- QPacketProtocol *protocol;
- QTcpServer *tcpServer;
+ void setServer(QQmlDebugServer *server);
+ bool setPortRange(int portFrom, int portTo, bool block, const QString &hostaddress);
+ bool setFileName(const QString &fileName, bool block);
- QQmlDebugServer *debugServer;
-};
+ bool isConnected() const;
+ void disconnect();
-QTcpServerConnectionPrivate::QTcpServerConnectionPrivate() :
- portFrom(0),
- portTo(0),
- block(false),
- socket(0),
- protocol(0),
- tcpServer(0),
- debugServer(0)
-{
-}
+ void waitForConnection();
+ void flush();
+
+private slots:
+ void newConnection();
+
+private:
+ bool listen();
+
+ int m_portFrom;
+ int m_portTo;
+ bool m_block;
+ QString m_hostaddress;
+ QTcpSocket *m_socket;
+ QTcpServer *m_tcpServer;
+ QQmlDebugServer *m_debugServer;
+};
QTcpServerConnection::QTcpServerConnection() :
- d_ptr(new QTcpServerConnectionPrivate)
+ m_portFrom(0),
+ m_portTo(0),
+ m_block(false),
+ m_socket(0),
+ m_tcpServer(0),
+ m_debugServer(0)
{
-
}
QTcpServerConnection::~QTcpServerConnection()
{
if (isConnected())
disconnect();
- delete d_ptr;
}
void QTcpServerConnection::setServer(QQmlDebugServer *server)
{
- Q_D(QTcpServerConnection);
- d->debugServer = server;
+ m_debugServer = server;
}
bool QTcpServerConnection::isConnected() const
{
- Q_D(const QTcpServerConnection);
- return d->socket && d->socket->state() == QTcpSocket::ConnectedState;
-}
-
-void QTcpServerConnection::send(const QList<QByteArray> &messages)
-{
- Q_D(QTcpServerConnection);
-
- if (!isConnected()
- || !d->protocol || !d->socket)
- return;
-
- foreach (const QByteArray &message, messages) {
- QPacket pack;
- pack.writeRawData(message.data(), message.length());
- d->protocol->send(pack);
- }
- d->socket->flush();
+ return m_socket && m_socket->state() == QTcpSocket::ConnectedState;
}
void QTcpServerConnection::disconnect()
{
- Q_D(QTcpServerConnection);
-
- while (d->socket && d->socket->bytesToWrite() > 0) {
- if (!d->socket->waitForBytesWritten()) {
+ while (m_socket && m_socket->bytesToWrite() > 0) {
+ if (!m_socket->waitForBytesWritten()) {
qWarning("QML Debugger: Failed to send remaining %lld bytes on disconnect.",
- d->socket->bytesToWrite());
+ m_socket->bytesToWrite());
break;
}
}
- // protocol might still be processing packages at this point
- d->protocol->deleteLater();
- d->protocol = 0;
- d->socket->deleteLater();
- d->socket = 0;
-}
-
-bool QTcpServerConnection::waitForMessage()
-{
- Q_D(QTcpServerConnection);
- return d->protocol->waitForReadyRead(-1);
+ m_socket->deleteLater();
+ m_socket = 0;
}
bool QTcpServerConnection::setPortRange(int portFrom, int portTo, bool block,
const QString &hostaddress)
{
- Q_D(QTcpServerConnection);
- d->portFrom = portFrom;
- d->portTo = portTo;
- d->block = block;
- d->hostaddress = hostaddress;
+ m_portFrom = portFrom;
+ m_portTo = portTo;
+ m_block = block;
+ m_hostaddress = hostaddress;
return listen();
}
+bool QTcpServerConnection::setFileName(const QString &fileName, bool block)
+{
+ Q_UNUSED(fileName);
+ Q_UNUSED(block);
+ return false;
+}
+
void QTcpServerConnection::waitForConnection()
{
- Q_D(QTcpServerConnection);
- d->tcpServer->waitForNewConnection(-1);
+ m_tcpServer->waitForNewConnection(-1);
}
-bool QTcpServerConnection::listen()
+void QTcpServerConnection::flush()
{
- Q_D(QTcpServerConnection);
+ if (m_socket)
+ m_socket->flush();
+}
- d->tcpServer = new QTcpServer(this);
- QObject::connect(d->tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection()));
+bool QTcpServerConnection::listen()
+{
+ m_tcpServer = new QTcpServer(this);
+ QObject::connect(m_tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection()));
QHostAddress hostaddress;
- if (!d->hostaddress.isEmpty()) {
- if (!hostaddress.setAddress(d->hostaddress)) {
+ if (!m_hostaddress.isEmpty()) {
+ if (!hostaddress.setAddress(m_hostaddress)) {
hostaddress = QHostAddress::Any;
qDebug("QML Debugger: Incorrect host address provided. So accepting connections "
"from any host.");
@@ -168,64 +157,45 @@ bool QTcpServerConnection::listen()
} else {
hostaddress = QHostAddress::Any;
}
- int port = d->portFrom;
+ int port = m_portFrom;
do {
- if (d->tcpServer->listen(hostaddress, port)) {
+ if (m_tcpServer->listen(hostaddress, port)) {
qDebug("QML Debugger: Waiting for connection on port %d...", port);
break;
}
++port;
- } while (port <= d->portTo);
- if (port > d->portTo) {
- if (d->portFrom == d->portTo)
- qWarning("QML Debugger: Unable to listen to port %d.", d->portFrom);
+ } while (port <= m_portTo);
+ if (port > m_portTo) {
+ if (m_portFrom == m_portTo)
+ qWarning("QML Debugger: Unable to listen to port %d.", m_portFrom);
else
- qWarning("QML Debugger: Unable to listen to ports %d - %d.", d->portFrom, d->portTo);
+ qWarning("QML Debugger: Unable to listen to ports %d - %d.", m_portFrom, m_portTo);
return false;
} else {
return true;
}
}
-
-void QTcpServerConnection::readyRead()
-{
- Q_D(QTcpServerConnection);
- if (!d->protocol)
- return;
-
- QPacket packet = d->protocol->read();
-
- QByteArray content = packet.data();
- d->debugServer->receiveMessage(content);
-}
-
void QTcpServerConnection::newConnection()
{
- Q_D(QTcpServerConnection);
-
- if (d->socket && d->socket->peerPort()) {
+ if (m_socket && m_socket->peerPort()) {
qWarning("QML Debugger: Another client is already connected.");
- QTcpSocket *faultyConnection = d->tcpServer->nextPendingConnection();
+ QTcpSocket *faultyConnection = m_tcpServer->nextPendingConnection();
delete faultyConnection;
return;
}
- delete d->socket;
- d->socket = d->tcpServer->nextPendingConnection();
- d->socket->setParent(this);
- d->protocol = new QPacketProtocol(d->socket, this);
- QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead()));
- QObject::connect(d->protocol, SIGNAL(invalidPacket()), this, SLOT(invalidPacket()));
-
- if (d->block) {
- d->protocol->waitForReadyRead(-1);
- }
+ delete m_socket;
+ m_socket = m_tcpServer->nextPendingConnection();
+ m_socket->setParent(this);
+ m_debugServer->setDevice(m_socket);
}
-void QTcpServerConnection::invalidPacket()
+QQmlDebugServerConnection *QTcpServerConnectionFactory::create(const QString &key)
{
- qWarning("QML Debugger: Received a corrupted packet! Giving up ...");
+ return (key == QLatin1String("QTcpServerConnection") ? new QTcpServerConnection : 0);
}
QT_END_NAMESPACE
+
+#include "qtcpserverconnection.moc"
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
deleted file mode 100644
index 942fb6e12c..0000000000
--- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QTCPSERVERCONNECTION_H
-#define QTCPSERVERCONNECTION_H
-
-#include <private/qqmldebugserverconnection_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQmlDebugServer;
-class QTcpServerConnectionPrivate;
-class QTcpServerConnection : public QObject, public QQmlDebugServerConnection
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QTcpServerConnection)
- Q_DISABLE_COPY(QTcpServerConnection)
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlDebugServerConnection")
- Q_INTERFACES(QQmlDebugServerConnection)
-
-public:
- QTcpServerConnection();
- ~QTcpServerConnection();
-
- void setServer(QQmlDebugServer *server);
- bool setPortRange(int portFrom, int portTo, bool bock, const QString &hostaddress);
-
- bool isConnected() const;
- void send(const QList<QByteArray> &messages);
- void disconnect();
- bool waitForMessage();
-
- bool listen();
- void waitForConnection();
-
-private Q_SLOTS:
- void readyRead();
- void newConnection();
- void invalidPacket();
-
-private:
- QTcpServerConnectionPrivate *d_ptr;
-};
-
-QT_END_NAMESPACE
-
-#endif // QTCPSERVERCONNECTION_H
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.json b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.json
new file mode 100644
index 0000000000..201a1b3fcb
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "QTcpServerConnection" ]
+}
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnectionfactory.h b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnectionfactory.h
new file mode 100644
index 0000000000..97dde03087
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnectionfactory.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCPSERVERCONNECTIONFACTORY_H
+#define QTCPSERVERCONNECTIONFACTORY_H
+
+#include "qqmldebugserverconnection.h"
+
+QT_BEGIN_NAMESPACE
+
+class QTcpServerConnectionFactory : public QQmlDebugServerConnectionFactory
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlDebugServerConnectionFactory_iid FILE "qtcpserverconnection.json")
+ Q_INTERFACES(QQmlDebugServerConnectionFactory)
+public:
+ QQmlDebugServerConnection *create(const QString &key);
+};
+
+QT_END_NAMESPACE
+
+#endif // QTCPSERVERCONNECTIONFACTORY_H
diff --git a/src/plugins/qmltooling/qmltooling.pro b/src/plugins/qmltooling/qmltooling.pro
index 3bc48a6b33..263e76e016 100644
--- a/src/plugins/qmltooling/qmltooling.pro
+++ b/src/plugins/qmltooling/qmltooling.pro
@@ -1,4 +1,15 @@
TEMPLATE = subdirs
-SUBDIRS = qmldbg_tcp
-qtHaveModule(quick): SUBDIRS += qmldbg_qtquick2
+# Connectors
+SUBDIRS += \
+ qmldbg_native \
+ qmldbg_server \
+ qmldbg_local \
+ qmldbg_tcp
+
+# Services
+SUBDIRS += \
+ qmldbg_debugger \
+ qmldbg_profiler
+
+qtHaveModule(quick): SUBDIRS += qmldbg_inspector
diff --git a/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h b/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h
new file mode 100644
index 0000000000..9aa4531428
--- /dev/null
+++ b/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QQMLCONFIGURABLEDEBUGSEVICE_H
+#define QQMLCONFIGURABLEDEBUGSEVICE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qqmldebugservice_p.h>
+#include <private/qqmldebugconnector_p.h>
+#include <QtCore/qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+template <class Base>
+class QQmlConfigurableDebugService : public Base
+{
+protected:
+ QQmlConfigurableDebugService(float version, QObject *parent = 0) :
+ Base(version, parent), m_configMutex(QMutex::Recursive)
+ {
+ init();
+ }
+
+ void stopWaiting()
+ {
+ QMutexLocker lock(&m_configMutex);
+ m_waitingForConfiguration = false;
+ foreach (QQmlEngine *engine, m_waitingEngines)
+ emit Base::attachedToEngine(engine);
+ m_waitingEngines.clear();
+ }
+
+ void init()
+ {
+ QMutexLocker lock(&m_configMutex);
+ // If we're not enabled or not blocking, don't wait for configuration
+ m_waitingForConfiguration = (Base::state() == QQmlDebugService::Enabled &&
+ QQmlDebugConnector::instance()->blockingMode());
+ }
+
+ void stateChanged(QQmlDebugService::State newState)
+ {
+ if (newState != QQmlDebugService::Enabled)
+ stopWaiting();
+ else
+ init();
+ }
+
+ void engineAboutToBeAdded(QQmlEngine *engine)
+ {
+ QMutexLocker lock(&m_configMutex);
+ if (m_waitingForConfiguration)
+ m_waitingEngines.append(engine);
+ else
+ emit Base::attachedToEngine(engine);
+ }
+
+ QMutex m_configMutex;
+ QList<QQmlEngine *> m_waitingEngines;
+ bool m_waitingForConfiguration;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLCONFIGURABLEDEBUGSEVICE_H
diff --git a/src/plugins/qmltooling/shared/qqmldebugserver.h b/src/plugins/qmltooling/shared/qqmldebugserver.h
new file mode 100644
index 0000000000..a7c17075d9
--- /dev/null
+++ b/src/plugins/qmltooling/shared/qqmldebugserver.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLDEBUGSERVER_H
+#define QQMLDEBUGSERVER_H
+
+#include <private/qqmldebugconnector_p.h>
+#include <private/qtqmlglobal_p.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlDebugServer : protected QQmlDebugConnector
+{
+ Q_OBJECT
+public:
+ virtual void setDevice(QIODevice *socket) = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLDEBUGSERVER_H
diff --git a/src/qml/debugger/qqmldebugserverconnection_p.h b/src/plugins/qmltooling/shared/qqmldebugserverconnection.h
index 9170238b46..9bdb1bcc8b 100644
--- a/src/qml/debugger/qqmldebugserverconnection_p.h
+++ b/src/plugins/qmltooling/shared/qqmldebugserverconnection.h
@@ -34,8 +34,8 @@
#ifndef QQMLDEBUGSERVERCONNECTION_H
#define QQMLDEBUGSERVERCONNECTION_H
-#include <QtQml/qtqmlglobal.h>
-#include <private/qqmlglobal_p.h>
+#include <private/qtqmlglobal_p.h>
+#include <QtCore/qobject.h>
//
// W A R N I N G
@@ -52,24 +52,30 @@ QT_BEGIN_NAMESPACE
class QQmlDebugServer;
-class Q_QML_PRIVATE_EXPORT QQmlDebugServerConnection
+class QQmlDebugServerConnection : public QObject
{
+ Q_OBJECT
public:
- QQmlDebugServerConnection() {}
- virtual ~QQmlDebugServerConnection() {}
+ QQmlDebugServerConnection(QObject *parent = 0) : QObject(parent) {}
virtual void setServer(QQmlDebugServer *server) = 0;
- virtual bool setPortRange(int portFrom, int portTo, bool bock, const QString &hostaddress) = 0;
+ virtual bool setPortRange(int portFrom, int portTo, bool block, const QString &hostaddress) = 0;
+ virtual bool setFileName(const QString &fileName, bool block) = 0;
virtual bool isConnected() const = 0;
- virtual void send(const QList<QByteArray> &messages) = 0;
virtual void disconnect() = 0;
virtual void waitForConnection() = 0;
- virtual bool waitForMessage() = 0;
+ virtual void flush() = 0;
};
-#define QQmlDebugServerConnection_iid "org.qt-project.Qt.QQmlDebugServerConnection"
+class QQmlDebugServerConnectionFactory : public QObject
+{
+ Q_OBJECT
+public:
+ virtual QQmlDebugServerConnection *create(const QString &key) = 0;
+};
-Q_DECLARE_INTERFACE(QQmlDebugServerConnection, QQmlDebugServerConnection_iid)
+#define QQmlDebugServerConnectionFactory_iid "org.qt-project.Qt.QQmlDebugServerConnectionFactory"
+Q_DECLARE_INTERFACE(QQmlDebugServerConnectionFactory, QQmlDebugServerConnectionFactory_iid)
QT_END_NAMESPACE
diff --git a/src/qml/Qt5QmlConfigExtras.cmake.in b/src/qml/Qt5QmlConfigExtras.cmake.in
new file mode 100644
index 0000000000..9ddb9885cd
--- /dev/null
+++ b/src/qml/Qt5QmlConfigExtras.cmake.in
@@ -0,0 +1,5 @@
+file(GLOB _qt5qml_other_plugins "${CMAKE_CURRENT_LIST_DIR}/Qt5Qml_*Factory.cmake")
+
+foreach(_other_plugin ${_qt5qml_other_plugins})
+ include(${_other_plugin} OPTIONAL)
+endforeach()
diff --git a/src/qml/animations/qabstractanimationjob_p.h b/src/qml/animations/qabstractanimationjob_p.h
index 5a3e9d2025..14dbf85a3d 100644
--- a/src/qml/animations/qabstractanimationjob_p.h
+++ b/src/qml/animations/qabstractanimationjob_p.h
@@ -34,6 +34,17 @@
#ifndef QABSTRACTANIMATIONJOB_P_H
#define QABSTRACTANIMATIONJOB_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qtqmlglobal_p.h>
#include <QtCore/QObject>
#include <QtCore/private/qabstractanimation_p.h>
diff --git a/src/qml/animations/qanimationgroupjob_p.h b/src/qml/animations/qanimationgroupjob_p.h
index fa8fc08bfe..c97a18f089 100644
--- a/src/qml/animations/qanimationgroupjob_p.h
+++ b/src/qml/animations/qanimationgroupjob_p.h
@@ -34,6 +34,17 @@
#ifndef QANIMATIONGROUPJOB_P_H
#define QANIMATIONGROUPJOB_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "private/qabstractanimationjob_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/qml/animations/qanimationjobutil_p.h b/src/qml/animations/qanimationjobutil_p.h
index 3c38fc1599..d2aceb72d0 100644
--- a/src/qml/animations/qanimationjobutil_p.h
+++ b/src/qml/animations/qanimationjobutil_p.h
@@ -34,6 +34,17 @@
#ifndef QANIMATIONJOBUTIL_P_H
#define QANIMATIONJOBUTIL_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#define RETURN_IF_DELETED(func) \
{ \
bool *prevWasDeleted = m_wasDeleted; \
diff --git a/src/qml/animations/qcontinuinganimationgroupjob_p.h b/src/qml/animations/qcontinuinganimationgroupjob_p.h
index 3df0e676a7..b9827ab936 100644
--- a/src/qml/animations/qcontinuinganimationgroupjob_p.h
+++ b/src/qml/animations/qcontinuinganimationgroupjob_p.h
@@ -34,6 +34,17 @@
#ifndef QCONTINUINGANIMATIONGROUPJOB_P_H
#define QCONTINUINGANIMATIONGROUPJOB_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "private/qanimationgroupjob_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/qml/animations/qparallelanimationgroupjob_p.h b/src/qml/animations/qparallelanimationgroupjob_p.h
index 1ac7709f21..83e5457cdd 100644
--- a/src/qml/animations/qparallelanimationgroupjob_p.h
+++ b/src/qml/animations/qparallelanimationgroupjob_p.h
@@ -34,6 +34,17 @@
#ifndef QPARALLELANIMATIONGROUPJOB_P_H
#define QPARALLELANIMATIONGROUPJOB_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "private/qanimationgroupjob_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/qml/animations/qpauseanimationjob_p.h b/src/qml/animations/qpauseanimationjob_p.h
index b909c71f49..725e9b62e9 100644
--- a/src/qml/animations/qpauseanimationjob_p.h
+++ b/src/qml/animations/qpauseanimationjob_p.h
@@ -34,6 +34,17 @@
#ifndef QPAUSEANIMATIONJOB_P_H
#define QPAUSEANIMATIONJOB_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qanimationgroupjob_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/animations/qsequentialanimationgroupjob_p.h b/src/qml/animations/qsequentialanimationgroupjob_p.h
index 5286fda28a..dab086e851 100644
--- a/src/qml/animations/qsequentialanimationgroupjob_p.h
+++ b/src/qml/animations/qsequentialanimationgroupjob_p.h
@@ -34,6 +34,17 @@
#ifndef QSEQUENTIALANIMATIONGROUPJOB_P_H
#define QSEQUENTIALANIMATIONGROUPJOB_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qanimationgroupjob_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 63833504f1..16c4cb28ed 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -33,7 +33,7 @@
#include "qqmlirbuilder_p.h"
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4compileddata_p.h>
#include <private/qqmljsparser_p.h>
#include <private/qqmljslexer_p.h>
@@ -1456,10 +1456,8 @@ JSCodeGen::JSCodeGen(const QString &fileName, const QString &sourceCode, QV4::IR
, _disableAcceleratedLookups(false)
, _contextObject(0)
, _scopeObject(0)
- , _contextObjectTemp(-1)
- , _scopeObjectTemp(-1)
+ , _qmlContextTemp(-1)
, _importedScriptsTemp(-1)
- , _idArrayTemp(-1)
{
_module = jsModule;
_module->setFileName(fileName);
@@ -1592,7 +1590,7 @@ static QV4::IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, QV4::IR::Membe
if (member->name->constData()->isUpper()) {
bool ok = false;
- int value = type->enumValue(*member->name, &ok);
+ int value = type->enumValue(qmlEngine, *member->name, &ok);
if (ok) {
member->setEnumValue(value);
resolver->clear();
@@ -1617,10 +1615,10 @@ static QV4::IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, QV4::IR::Membe
member->kind = QV4::IR::Member::MemberOfSingletonObject;
return resolver->resolveMember(qmlEngine, resolver, member);
}
- } else if (const QMetaObject *attachedMeta = type->attachedPropertiesType()) {
+ } else if (const QMetaObject *attachedMeta = type->attachedPropertiesType(qmlEngine)) {
QQmlPropertyCache *cache = qmlEngine->cache(attachedMeta);
initMetaObjectResolver(resolver, cache);
- member->setAttachedPropertiesId(type->attachedPropertiesId());
+ member->setAttachedPropertiesId(type->attachedPropertiesId(qmlEngine));
return resolver->resolveMember(qmlEngine, resolver, member);
}
@@ -1695,7 +1693,8 @@ static QV4::IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, QV4
}
}
- if (qmlEngine && !(resolver->flags & LookupsExcludeProperties)) {
+ if (member->kind != QV4::IR::Member::MemberOfIdObjectsArray && member->kind != QV4::IR::Member::MemberOfSingletonObject &&
+ qmlEngine && !(resolver->flags & LookupsExcludeProperties)) {
QQmlPropertyData *property = member->property;
if (!property && metaObject) {
if (QQmlPropertyData *candidate = metaObject->property(*member->name, /*object*/0, /*context*/0)) {
@@ -1764,24 +1763,14 @@ static void initMetaObjectResolver(QV4::IR::MemberExpressionResolver *resolver,
void JSCodeGen::beginFunctionBodyHook()
{
- _contextObjectTemp = _block->newTemp();
- _scopeObjectTemp = _block->newTemp();
+ _qmlContextTemp = _block->newTemp();
_importedScriptsTemp = _block->newTemp();
- _idArrayTemp = _block->newTemp();
#ifndef V4_BOOTSTRAP
- QV4::IR::Temp *temp = _block->TEMP(_contextObjectTemp);
- temp->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
- initMetaObjectResolver(temp->memberResolver, _contextObject);
- move(temp, _block->NAME(QV4::IR::Name::builtin_qml_context_object, 0, 0));
-
- temp = _block->TEMP(_scopeObjectTemp);
- temp->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
- initMetaObjectResolver(temp->memberResolver, _scopeObject);
- move(temp, _block->NAME(QV4::IR::Name::builtin_qml_scope_object, 0, 0));
+ QV4::IR::Temp *temp = _block->TEMP(_qmlContextTemp);
+ move(temp, _block->NAME(QV4::IR::Name::builtin_qml_context, 0, 0));
move(_block->TEMP(_importedScriptsTemp), _block->NAME(QV4::IR::Name::builtin_qml_imported_scripts_object, 0, 0));
- move(_block->TEMP(_idArrayTemp), _block->NAME(QV4::IR::Name::builtin_qml_id_array, 0, 0));
#endif
}
@@ -1807,7 +1796,7 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
foreach (const IdMapping &mapping, _idObjects)
if (name == mapping.name) {
_function->idObjectDependencies.insert(mapping.idIndex);
- QV4::IR::Expr *s = subscript(_block->TEMP(_idArrayTemp), _block->CONST(QV4::IR::SInt32Type, mapping.idIndex));
+ QV4::IR::Expr *s = _block->MEMBER(_block->TEMP(_qmlContextTemp), _function->newString(name), 0, QV4::IR::Member::MemberOfIdObjectsArray, mapping.idIndex);
QV4::IR::Temp *result = _block->TEMP(_block->newTemp());
_block->MOVE(result, s);
result = _block->TEMP(result->index);
@@ -1857,7 +1846,7 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
if (propertyExistsButForceNameLookup)
return 0;
if (pd) {
- QV4::IR::Temp *base = _block->TEMP(_scopeObjectTemp);
+ QV4::IR::Temp *base = _block->TEMP(_qmlContextTemp);
base->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
initMetaObjectResolver(base->memberResolver, _scopeObject);
return _block->MEMBER(base, _function->newString(name), pd, QV4::IR::Member::MemberOfQmlScopeObject);
@@ -1870,7 +1859,7 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
if (propertyExistsButForceNameLookup)
return 0;
if (pd) {
- QV4::IR::Temp *base = _block->TEMP(_contextObjectTemp);
+ QV4::IR::Temp *base = _block->TEMP(_qmlContextTemp);
base->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
initMetaObjectResolver(base->memberResolver, _contextObject);
return _block->MEMBER(base, _function->newString(name), pd, QV4::IR::Member::MemberOfQmlContextObject);
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 120de91321..9a659f4d72 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -33,8 +33,18 @@
#ifndef QQMLIRBUILDER_P_H
#define QQMLIRBUILDER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qqmljsast_p.h>
-#include <private/qqmlpool_p.h>
#include <private/qqmljsengine_p.h>
#include <private/qv4compiler_p.h>
#include <private/qv4compileddata_p.h>
@@ -496,10 +506,8 @@ private:
ObjectIdMapping _idObjects;
QQmlPropertyCache *_contextObject;
QQmlPropertyCache *_scopeObject;
- int _contextObjectTemp;
- int _scopeObjectTemp;
+ int _qmlContextTemp;
int _importedScriptsTemp;
- int _idArrayTemp;
};
} // namespace QmlIR
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 4e9817aa0d..cde7a2acb4 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -104,11 +104,10 @@ bool QQmlTypeCompiler::compile()
}
if (ref->type->containsRevisionedAttributes()) {
- QQmlError cacheError;
ref->typePropertyCache = engine->cache(ref->type,
- resolvedType->minorVersion,
- cacheError);
+ resolvedType->minorVersion);
if (!ref->typePropertyCache) {
+ QQmlError cacheError;
cacheError.setColumn(resolvedType->location.column);
cacheError.setLine(resolvedType->location.line);
recordError(cacheError);
@@ -521,7 +520,24 @@ bool QQmlPropertyCacheCreator::buildMetaObjectRecursively(int objectIndex, int r
} else if (instantiatingBinding && instantiatingBinding->isAttachedProperty()) {
QQmlCompiledData::TypeReference *typeRef = resolvedTypes->value(instantiatingBinding->propertyNameIndex);
Q_ASSERT(typeRef);
- const QMetaObject *attachedMo = typeRef->type ? typeRef->type->attachedPropertiesType() : 0;
+ QQmlType *qmltype = typeRef->type;
+ if (!qmltype) {
+ QString propertyName = stringAt(instantiatingBinding->propertyNameIndex);
+ if (imports->resolveType(propertyName, &qmltype, 0, 0, 0)) {
+ if (qmltype->isComposite()) {
+ QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype->sourceUrl());
+ Q_ASSERT(tdata);
+ Q_ASSERT(tdata->isComplete());
+
+ QQmlCompiledData *data = tdata->compiledData();
+ qmltype = QQmlMetaType::qmlType(data->metaTypeId);
+
+ tdata->release();
+ }
+ }
+ }
+
+ const QMetaObject *attachedMo = qmltype ? qmltype->attachedPropertiesType(enginePrivate) : 0;
if (!attachedMo) {
recordError(instantiatingBinding->location, tr("Non-existent attached object"));
return false;
@@ -668,17 +684,14 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
}
// First set up notify signals for properties - first normal, then var, then alias
- enum { NSS_Normal = 0, NSS_Var = 1, NSS_Alias = 2 };
+ enum { NSS_Normal = 0, NSS_Alias = 1 };
for (int ii = NSS_Normal; ii <= NSS_Alias; ++ii) { // 0 == normal, 1 == var, 2 == alias
- if (ii == NSS_Var && varPropCount == 0) continue;
- else if (ii == NSS_Alias && aliasCount == 0) continue;
+ if (ii == NSS_Alias && aliasCount == 0) continue;
for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next) {
- if ((ii == NSS_Normal && (p->type == QV4::CompiledData::Property::Alias ||
- p->type == QV4::CompiledData::Property::Var)) ||
- ((ii == NSS_Var) && (p->type != QV4::CompiledData::Property::Var)) ||
- ((ii == NSS_Alias) && (p->type != QV4::CompiledData::Property::Alias)))
+ if ((ii == NSS_Normal && p->type == QV4::CompiledData::Property::Alias) ||
+ (ii == NSS_Alias && p->type != QV4::CompiledData::Property::Alias))
continue;
quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
@@ -696,6 +709,7 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
const int paramCount = s->parameters->count;
QList<QByteArray> names;
+ names.reserve(paramCount);
QVarLengthArray<int, 10> paramTypes(paramCount?(paramCount + 1):0);
if (paramCount) {
@@ -780,15 +794,18 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
int propertyIdx = 0;
for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next, ++propertyIdx) {
- if (p->type == QV4::CompiledData::Property::Alias ||
- p->type == QV4::CompiledData::Property::Var)
+ if (p->type == QV4::CompiledData::Property::Alias)
continue;
int propertyType = 0;
int vmePropertyType = 0;
quint32 propertyFlags = 0;
- if (p->type < builtinTypeCount) {
+ if (p->type == QV4::CompiledData::Property::Var) {
+ propertyType = QMetaType::QVariant;
+ vmePropertyType = QQmlVMEMetaData::VarPropertyType;
+ propertyFlags = QQmlPropertyData::IsVarProperty;
+ } else if (p->type < builtinTypeCount) {
propertyType = builtinTypes[p->type].metaType;
vmePropertyType = propertyType;
@@ -852,30 +869,6 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
vmd->propertyCount++;
}
- // Now do var properties
- propertyIdx = 0;
- for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next, ++propertyIdx) {
-
- if (p->type != QV4::CompiledData::Property::Var)
- continue;
-
- quint32 propertyFlags = QQmlPropertyData::IsVarProperty;
- if (!(p->flags & QV4::CompiledData::Property::IsReadOnly))
- propertyFlags |= QQmlPropertyData::IsWritable;
-
- VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
- (vmd->propertyData() + vmd->propertyCount)->propertyType = QMetaType::QVariant;
- vmd->propertyCount++;
- ((QQmlVMEMetaData *)dynamicData.data())->varPropertyCount++;
-
- QString propertyName = stringAt(p->nameIndex);
- if (propertyIdx == obj->indexOfDefaultProperty) cache->_defaultPropertyName = propertyName;
- cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
- QMetaType::QVariant, effectiveSignalIndex);
-
- effectiveSignalIndex++;
- }
-
// Alias property count. Actual data is setup in buildDynamicMetaAliases
((QQmlVMEMetaData *)dynamicData.data())->aliasCount = aliasCount;
@@ -904,7 +897,9 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
SignalHandlerConverter::SignalHandlerConverter(QQmlTypeCompiler *typeCompiler)
: QQmlCompilePass(typeCompiler)
+ , enginePrivate(typeCompiler->enginePrivate())
, qmlObjects(*typeCompiler->qmlObjects())
+ , imports(typeCompiler->imports())
, customParsers(typeCompiler->customParserCache())
, resolvedTypes(*typeCompiler->resolvedTypes())
, illegalNames(QV8Engine::get(QQmlEnginePrivate::get(typeCompiler->enginePrivate()))->illegalNames())
@@ -942,7 +937,22 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
const QmlIR::Object *attachedObj = qmlObjects.at(binding->value.objectIndex);
QQmlCompiledData::TypeReference *typeRef = resolvedTypes.value(binding->propertyNameIndex);
QQmlType *type = typeRef ? typeRef->type : 0;
- const QMetaObject *attachedType = type ? type->attachedPropertiesType() : 0;
+ if (!type) {
+ if (imports->resolveType(propertyName, &type, 0, 0, 0)) {
+ if (type->isComposite()) {
+ QQmlTypeData *tdata = enginePrivate->typeLoader.getType(type->sourceUrl());
+ Q_ASSERT(tdata);
+ Q_ASSERT(tdata->isComplete());
+
+ QQmlCompiledData *data = tdata->compiledData();
+ type = QQmlMetaType::qmlType(data->metaTypeId);
+
+ tdata->release();
+ }
+ }
+ }
+
+ const QMetaObject *attachedType = type ? type->attachedPropertiesType(enginePrivate) : 0;
if (!attachedType)
COMPILE_EXCEPTION(binding, tr("Non-existent attached object"));
QQmlPropertyCache *cache = compiler->enginePrivate()->cache(attachedType);
@@ -1022,10 +1032,10 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
}
}
- QHash<QString, QStringList>::ConstIterator entry = customSignals.find(propertyName);
+ QHash<QString, QStringList>::ConstIterator entry = customSignals.constFind(propertyName);
if (entry == customSignals.constEnd() && propertyName.endsWith(QStringLiteral("Changed"))) {
QString alternateName = propertyName.mid(0, propertyName.length() - static_cast<int>(strlen("Changed")));
- entry = customSignals.find(alternateName);
+ entry = customSignals.constFind(alternateName);
}
if (entry == customSignals.constEnd()) {
@@ -1067,16 +1077,29 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
paramList = paramList->finish();
QmlIR::CompiledFunctionOrExpression *foe = obj->functionsAndExpressions->slowAt(binding->value.compiledScriptIndex);
- QQmlJS::AST::Statement *statement = static_cast<QQmlJS::AST::Statement*>(foe->node);
- QQmlJS::AST::SourceElement *sourceElement = new (pool) QQmlJS::AST::StatementSourceElement(statement);
- QQmlJS::AST::SourceElements *elements = new (pool) QQmlJS::AST::SourceElements(sourceElement);
- elements = elements->finish();
-
- QQmlJS::AST::FunctionBody *body = new (pool) QQmlJS::AST::FunctionBody(elements);
+ QQmlJS::AST::FunctionDeclaration *functionDeclaration = 0;
+ if (QQmlJS::AST::ExpressionStatement *es = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement*>(foe->node)) {
+ if (QQmlJS::AST::FunctionExpression *fe = QQmlJS::AST::cast<QQmlJS::AST::FunctionExpression*>(es->expression)) {
+ functionDeclaration = new (pool) QQmlJS::AST::FunctionDeclaration(fe->name, fe->formals, fe->body);
+ functionDeclaration->functionToken = fe->functionToken;
+ functionDeclaration->identifierToken = fe->identifierToken;
+ functionDeclaration->lparenToken = fe->lparenToken;
+ functionDeclaration->rparenToken = fe->rparenToken;
+ functionDeclaration->lbraceToken = fe->lbraceToken;
+ functionDeclaration->rbraceToken = fe->rbraceToken;
+ }
+ }
+ if (!functionDeclaration) {
+ QQmlJS::AST::Statement *statement = static_cast<QQmlJS::AST::Statement*>(foe->node);
+ QQmlJS::AST::SourceElement *sourceElement = new (pool) QQmlJS::AST::StatementSourceElement(statement);
+ QQmlJS::AST::SourceElements *elements = new (pool) QQmlJS::AST::SourceElements(sourceElement);
+ elements = elements->finish();
- QQmlJS::AST::FunctionDeclaration *functionDeclaration = new (pool) QQmlJS::AST::FunctionDeclaration(compiler->newStringRef(stringAt(binding->propertyNameIndex)), paramList, body);
- functionDeclaration->functionToken = foe->node->firstSourceLocation();
+ QQmlJS::AST::FunctionBody *body = new (pool) QQmlJS::AST::FunctionBody(elements);
+ functionDeclaration = new (pool) QQmlJS::AST::FunctionDeclaration(compiler->newStringRef(stringAt(binding->propertyNameIndex)), paramList, body);
+ functionDeclaration->functionToken = foe->node->firstSourceLocation();
+ }
foe->node = functionDeclaration;
binding->propertyNameIndex = compiler->registerString(propertyName);
binding->flags |= QV4::CompiledData::Binding::IsSignalHandlerExpression;
@@ -1174,8 +1197,6 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
if (!type && typeName != QLatin1String("Qt"))
return true;
- if (type && type->isComposite()) //No enums on composite (or composite singleton) types
- return true;
int value = 0;
bool ok = false;
@@ -1193,7 +1214,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
} else {
// Otherwise we have to search the whole type
if (type) {
- value = type->enumValue(QHashedStringRef(enumValue), &ok);
+ value = type->enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue), &ok);
} else {
QByteArray enumName = enumValue.toUtf8();
const QMetaObject *metaObject = StaticQtMetaObject::get();
@@ -1221,7 +1242,9 @@ int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QByteArray &e
if (scope != QLatin1String("Qt")) {
QQmlType *type = 0;
imports->resolveType(scope, &type, 0, 0, 0);
- return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
+ if (!type)
+ return -1;
+ return type ? type->enumValue(compiler->enginePrivate(), QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
}
const QMetaObject *mo = StaticQtMetaObject::get();
@@ -1730,17 +1753,6 @@ const QQmlImports &QQmlPropertyValidator::imports() const
return *compiler->imports();
}
-QString QQmlPropertyValidator::bindingAsString(int objectIndex, const QV4::CompiledData::Binding *binding) const
-{
- const QmlIR::Object *object = compiler->qmlObjects()->value(objectIndex);
- if (!object)
- return QString();
- int reverseIndex = object->runtimeFunctionIndices->indexOf(binding->value.compiledScriptIndex);
- if (reverseIndex == -1)
- return QString();
- return compiler->bindingAsString(object, reverseIndex);
-}
-
typedef QVarLengthArray<const QV4::CompiledData::Binding *, 8> GroupPropertyVector;
struct BindingFinder
@@ -2009,15 +2021,17 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
if (customParser && !customBindings.isEmpty()) {
customParser->clearErrors();
- customParser->compiler = this;
+ customParser->validator = this;
+ customParser->engine = enginePrivate;
customParser->imports = compiler->imports();
customParser->verifyBindings(qmlUnit, customBindings);
- customParser->compiler = 0;
+ customParser->validator = 0;
+ customParser->engine = 0;
customParser->imports = (QQmlImports*)0;
customParserBindingsPerObject->insert(objectIndex, customParserBindings);
const QList<QQmlError> parserErrors = customParser->errors();
if (!parserErrors.isEmpty()) {
- foreach (QQmlError error, parserErrors)
+ foreach (const QQmlError &error, parserErrors)
compiler->recordError(error);
return false;
}
@@ -2623,10 +2637,8 @@ void QQmlJavaScriptBindingExpressionSimplificationPass::visitMove(QV4::IR::Move
}
if (QV4::IR::Name *n = move->source->asName()) {
- if (n->builtin == QV4::IR::Name::builtin_qml_id_array
- || n->builtin == QV4::IR::Name::builtin_qml_imported_scripts_object
- || n->builtin == QV4::IR::Name::builtin_qml_context_object
- || n->builtin == QV4::IR::Name::builtin_qml_scope_object) {
+ if (n->builtin == QV4::IR::Name::builtin_qml_context
+ || n->builtin == QV4::IR::Name::builtin_qml_imported_scripts_object) {
// these are free of side-effects
return;
}
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index 75987af656..c5be92d256 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -33,6 +33,17 @@
#ifndef QQMLTYPECOMPILER_P_H
#define QQMLTYPECOMPILER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qglobal.h>
#include <qqmlerror.h>
#include <qhash.h>
@@ -158,7 +169,9 @@ public:
private:
bool convertSignalHandlerExpressionsToFunctionDeclarations(const QmlIR::Object *obj, const QString &typeName, QQmlPropertyCache *propertyCache);
+ QQmlEnginePrivate *enginePrivate;
const QList<QmlIR::Object*> &qmlObjects;
+ const QQmlImports *imports;
const QHash<int, QQmlCustomParser*> &customParsers;
const QHash<int, QQmlCompiledData::TypeReference*> &resolvedTypes;
const QSet<QString> &illegalNames;
@@ -264,7 +277,7 @@ protected:
QHash<int, QHash<int, int> > *objectIndexToIdPerComponent;
};
-class QQmlPropertyValidator : public QQmlCompilePass, public QQmlCustomParserCompilerBackend
+class QQmlPropertyValidator : public QQmlCompilePass
{
Q_DECLARE_TR_FUNCTIONS(QQmlPropertyValidator)
public:
@@ -272,9 +285,8 @@ public:
bool validate();
- // Re-implemented for QQmlCustomParser
- virtual const QQmlImports &imports() const;
- virtual QString bindingAsString(int objectIndex, const QV4::CompiledData::Binding *binding) const;
+ const QQmlImports &imports() const;
+ QQmlEnginePrivate *engine() const { return enginePrivate; }
private:
bool validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty = false) const;
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 9168889c8c..ea82d07e69 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -33,6 +33,7 @@
#include "qv4codegen_p.h"
#include "qv4util_p.h"
+#include "qv4engine_p.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QStringList>
@@ -43,7 +44,7 @@
#include <QtCore/QStack>
#include <private/qqmljsast_p.h>
#include <private/qv4string_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#ifndef V4_BOOTSTRAP
#include <qv4context_p.h>
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index aec51cc19c..a7b0b06fe2 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -33,6 +33,17 @@
#ifndef QV4CODEGEN_P_H
#define QV4CODEGEN_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "private/qv4global_p.h"
#include "qv4jsir_p.h"
#include <private/qqmljsastvisitor_p.h>
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 5d954eb4fc..20db5edaa3 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -33,7 +33,7 @@
#include "qv4compileddata_p.h"
#include "qv4jsir_p.h"
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#ifndef V4_BOOTSTRAP
#include <private/qv4engine_p.h>
#include <private/qv4function_p.h>
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 48324fbbc4..0d6e4b15a7 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -33,6 +33,17 @@
#ifndef QV4COMPILEDDATA_P_H
#define QV4COMPILEDDATA_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qstring.h>
#include <QVector>
#include <QStringList>
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index 450889c275..ba4bde7a31 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -35,7 +35,7 @@
#include <qv4compileddata_p.h>
#include <qv4isel_p.h>
#include <private/qv4string_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
QV4::Compiler::StringTableGenerator::StringTableGenerator()
{
@@ -44,8 +44,8 @@ QV4::Compiler::StringTableGenerator::StringTableGenerator()
int QV4::Compiler::StringTableGenerator::registerString(const QString &str)
{
- QHash<QString, int>::ConstIterator it = stringToId.find(str);
- if (it != stringToId.end())
+ QHash<QString, int>::ConstIterator it = stringToId.constFind(str);
+ if (it != stringToId.cend())
return *it;
stringToId.insert(str, strings.size());
strings.append(str);
@@ -169,6 +169,7 @@ int QV4::Compiler::JSUnitGenerator::registerJSClass(int count, IR::ExprList *arg
// ### re-use existing class definitions.
QList<CompiledData::JSClassMember> members;
+ members.reserve(count);
IR::ExprList *it = args;
for (int i = 0; i < count; ++i, it = it->next) {
diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h
index 3cf80a9791..d999a93f4f 100644
--- a/src/qml/compiler/qv4compiler_p.h
+++ b/src/qml/compiler/qv4compiler_p.h
@@ -33,6 +33,17 @@
#ifndef QV4COMPILER_P_H
#define QV4COMPILER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qstring.h>
#include "qv4jsir_p.h"
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 5c2ad45da2..97aee80e91 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -34,6 +34,17 @@
#ifndef QV4INSTR_MOTH_P_H
#define QV4INSTR_MOTH_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qglobal.h>
#include <private/qv4value_p.h>
#include <private/qv4function_p.h>
@@ -64,12 +75,19 @@ QT_BEGIN_NAMESPACE
F(SetLookup, setLookup) \
F(StoreQObjectProperty, storeQObjectProperty) \
F(LoadQObjectProperty, loadQObjectProperty) \
+ F(StoreScopeObjectProperty, storeScopeObjectProperty) \
+ F(StoreContextObjectProperty, storeContextObjectProperty) \
+ F(LoadScopeObjectProperty, loadScopeObjectProperty) \
+ F(LoadContextObjectProperty, loadContextObjectProperty) \
+ F(LoadIdObject, loadIdObject) \
F(LoadAttachedQObjectProperty, loadAttachedQObjectProperty) \
F(LoadSingletonQObjectProperty, loadQObjectProperty) \
F(Push, push) \
F(CallValue, callValue) \
F(CallProperty, callProperty) \
F(CallPropertyLookup, callPropertyLookup) \
+ F(CallScopeObjectProperty, callScopeObjectProperty) \
+ F(CallContextObjectProperty, callContextObjectProperty) \
F(CallElement, callElement) \
F(CallActivationProperty, callActivationProperty) \
F(CallGlobalLookup, callGlobalLookup) \
@@ -84,6 +102,8 @@ QT_BEGIN_NAMESPACE
F(CallBuiltinDeleteMember, callBuiltinDeleteMember) \
F(CallBuiltinDeleteSubscript, callBuiltinDeleteSubscript) \
F(CallBuiltinDeleteName, callBuiltinDeleteName) \
+ F(CallBuiltinTypeofScopeObjectProperty, callBuiltinTypeofScopeObjectProperty) \
+ F(CallBuiltinTypeofContextObjectProperty, callBuiltinTypeofContextObjectProperty) \
F(CallBuiltinTypeofMember, callBuiltinTypeofMember) \
F(CallBuiltinTypeofSubscript, callBuiltinTypeofSubscript) \
F(CallBuiltinTypeofName, callBuiltinTypeofName) \
@@ -125,10 +145,8 @@ QT_BEGIN_NAMESPACE
F(Sub, sub) \
F(BinopContext, binopContext) \
F(LoadThis, loadThis) \
- F(LoadQmlIdArray, loadQmlIdArray) \
+ F(LoadQmlContext, loadQmlContext) \
F(LoadQmlImportedScripts, loadQmlImportedScripts) \
- F(LoadQmlContextObject, loadQmlContextObject) \
- F(LoadQmlScopeObject, loadQmlScopeObject) \
F(LoadQmlSingleton, loadQmlSingleton)
#if defined(Q_CC_GNU) && (!defined(Q_CC_INTEL) || __INTEL_COMPILER >= 1200)
@@ -293,6 +311,24 @@ union Instr
Param base;
Param result;
};
+ struct instr_loadScopeObjectProperty {
+ MOTH_INSTR_HEADER
+ int propertyIndex;
+ Param base;
+ Param result;
+ };
+ struct instr_loadContextObjectProperty {
+ MOTH_INSTR_HEADER
+ int propertyIndex;
+ Param base;
+ Param result;
+ };
+ struct instr_loadIdObject {
+ MOTH_INSTR_HEADER
+ int index;
+ Param base;
+ Param result;
+ };
struct instr_loadQObjectProperty {
MOTH_INSTR_HEADER
int propertyIndex;
@@ -318,6 +354,18 @@ union Instr
Param base;
Param source;
};
+ struct instr_storeScopeObjectProperty {
+ MOTH_INSTR_HEADER
+ Param base;
+ int propertyIndex;
+ Param source;
+ };
+ struct instr_storeContextObjectProperty {
+ MOTH_INSTR_HEADER
+ Param base;
+ int propertyIndex;
+ Param source;
+ };
struct instr_storeQObjectProperty {
MOTH_INSTR_HEADER
Param base;
@@ -377,6 +425,22 @@ union Instr
Param base;
Param result;
};
+ struct instr_callScopeObjectProperty {
+ MOTH_INSTR_HEADER
+ int index;
+ quint32 argc;
+ quint32 callData;
+ Param base;
+ Param result;
+ };
+ struct instr_callContextObjectProperty {
+ MOTH_INSTR_HEADER
+ int index;
+ quint32 argc;
+ quint32 callData;
+ Param base;
+ Param result;
+ };
struct instr_callElement {
MOTH_INSTR_HEADER
Param base;
@@ -449,6 +513,18 @@ union Instr
int name;
Param result;
};
+ struct instr_callBuiltinTypeofScopeObjectProperty {
+ MOTH_INSTR_HEADER
+ int index;
+ Param base;
+ Param result;
+ };
+ struct instr_callBuiltinTypeofContextObjectProperty {
+ MOTH_INSTR_HEADER
+ int index;
+ Param base;
+ Param result;
+ };
struct instr_callBuiltinTypeofMember {
MOTH_INSTR_HEADER
int member;
@@ -684,7 +760,7 @@ union Instr
MOTH_INSTR_HEADER
Param result;
};
- struct instr_loadQmlIdArray {
+ struct instr_loadQmlContext {
MOTH_INSTR_HEADER
Param result;
};
@@ -692,14 +768,6 @@ union Instr
MOTH_INSTR_HEADER
Param result;
};
- struct instr_loadQmlContextObject {
- MOTH_INSTR_HEADER
- Param result;
- };
- struct instr_loadQmlScopeObject {
- MOTH_INSTR_HEADER
- Param result;
- };
struct instr_loadQmlSingleton {
MOTH_INSTR_HEADER
Param result;
@@ -725,15 +793,22 @@ union Instr
instr_storeElementLookup storeElementLookup;
instr_loadProperty loadProperty;
instr_getLookup getLookup;
+ instr_loadScopeObjectProperty loadScopeObjectProperty;
+ instr_loadContextObjectProperty loadContextObjectProperty;
+ instr_loadIdObject loadIdObject;
instr_loadQObjectProperty loadQObjectProperty;
instr_loadAttachedQObjectProperty loadAttachedQObjectProperty;
instr_storeProperty storeProperty;
instr_setLookup setLookup;
+ instr_storeScopeObjectProperty storeScopeObjectProperty;
+ instr_storeContextObjectProperty storeContextObjectProperty;
instr_storeQObjectProperty storeQObjectProperty;
instr_push push;
instr_callValue callValue;
instr_callProperty callProperty;
instr_callPropertyLookup callPropertyLookup;
+ instr_callScopeObjectProperty callScopeObjectProperty;
+ instr_callContextObjectProperty callContextObjectProperty;
instr_callElement callElement;
instr_callActivationProperty callActivationProperty;
instr_callGlobalLookup callGlobalLookup;
@@ -748,6 +823,8 @@ union Instr
instr_callBuiltinDeleteMember callBuiltinDeleteMember;
instr_callBuiltinDeleteSubscript callBuiltinDeleteSubscript;
instr_callBuiltinDeleteName callBuiltinDeleteName;
+ instr_callBuiltinTypeofScopeObjectProperty callBuiltinTypeofScopeObjectProperty;
+ instr_callBuiltinTypeofContextObjectProperty callBuiltinTypeofContextObjectProperty;
instr_callBuiltinTypeofMember callBuiltinTypeofMember;
instr_callBuiltinTypeofSubscript callBuiltinTypeofSubscript;
instr_callBuiltinTypeofName callBuiltinTypeofName;
@@ -789,10 +866,8 @@ union Instr
instr_sub sub;
instr_binopContext binopContext;
instr_loadThis loadThis;
- instr_loadQmlIdArray loadQmlIdArray;
+ instr_loadQmlContext loadQmlContext;
instr_loadQmlImportedScripts loadQmlImportedScripts;
- instr_loadQmlContextObject loadQmlContextObject;
- instr_loadQmlScopeObject loadQmlScopeObject;
instr_loadQmlSingleton loadQmlSingleton;
static int size(Type type);
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index eb78a0c054..afb36c5f14 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -350,7 +350,7 @@ void InstructionSelection::run(int functionIndex)
opt.run(qmlEngine, useTypeInference, /*peelLoops =*/ false);
if (opt.isInSSA()) {
static const bool doStackSlotAllocation =
- qgetenv("QV4_NO_INTERPRETER_STACK_SLOT_ALLOCATION").isEmpty();
+ qEnvironmentVariableIsEmpty("QV4_NO_INTERPRETER_STACK_SLOT_ALLOCATION");
if (doStackSlotAllocation) {
AllocateStackSlots(opt.lifeTimeIntervals()).forFunction(_function);
@@ -447,7 +447,7 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> InstructionSelection::backend
foreach (IR::Function *irFunction, irModule->functions)
compilationUnit->codeRefs[i++] = codeRefs[irFunction];
QQmlRefPointer<QV4::CompiledData::CompilationUnit> result;
- result.take(compilationUnit.take());
+ result.adopt(compilationUnit.take());
return result;
}
@@ -461,6 +461,29 @@ void InstructionSelection::callValue(IR::Expr *value, IR::ExprList *args, IR::Ex
addInstruction(call);
}
+void InstructionSelection::callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject) {
+ Instruction::CallScopeObjectProperty call;
+ call.base = getParam(base);
+ call.index = propertyIndex;
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
+ call.result = getResultParam(result);
+ addInstruction(call);
+ } else if (kind == IR::Member::MemberOfQmlContextObject) {
+ Instruction::CallContextObjectProperty call;
+ call.base = getParam(base);
+ call.index = propertyIndex;
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
+ call.result = getResultParam(result);
+ addInstruction(call);
+ } else {
+ Q_ASSERT(false);
+ }
+}
+
void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
IR::Expr *result)
{
@@ -565,9 +588,9 @@ void InstructionSelection::loadThisObject(IR::Expr *e)
addInstruction(load);
}
-void InstructionSelection::loadQmlIdArray(IR::Expr *e)
+void InstructionSelection::loadQmlContext(IR::Expr *e)
{
- Instruction::LoadQmlIdArray load;
+ Instruction::LoadQmlContext load;
load.result = getResultParam(e);
addInstruction(load);
}
@@ -579,20 +602,6 @@ void InstructionSelection::loadQmlImportedScripts(IR::Expr *e)
addInstruction(load);
}
-void InstructionSelection::loadQmlContextObject(IR::Expr *e)
-{
- Instruction::LoadQmlContextObject load;
- load.result = getResultParam(e);
- addInstruction(load);
-}
-
-void InstructionSelection::loadQmlScopeObject(IR::Expr *e)
-{
- Instruction::LoadQmlScopeObject load;
- load.result = getResultParam(e);
- addInstruction(load);
-}
-
void InstructionSelection::loadQmlSingleton(const QString &name, IR::Expr *e)
{
Instruction::LoadQmlSingleton load;
@@ -694,6 +703,25 @@ void InstructionSelection::setProperty(IR::Expr *source, IR::Expr *targetBase,
addInstruction(store);
}
+void InstructionSelection::setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject) {
+ Instruction::StoreScopeObjectProperty store;
+ store.base = getParam(targetBase);
+ store.propertyIndex = propertyIndex;
+ store.source = getParam(source);
+ addInstruction(store);
+ } else if (kind == IR::Member::MemberOfQmlContextObject) {
+ Instruction::StoreContextObjectProperty store;
+ store.base = getParam(targetBase);
+ store.propertyIndex = propertyIndex;
+ store.source = getParam(source);
+ addInstruction(store);
+ } else {
+ Q_ASSERT(false);
+ }
+}
+
void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex)
{
Instruction::StoreQObjectProperty store;
@@ -703,6 +731,31 @@ void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *target
addInstruction(store);
}
+void InstructionSelection::getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject) {
+ Instruction::LoadScopeObjectProperty load;
+ load.base = getParam(source);
+ load.propertyIndex = index;
+ load.result = getResultParam(target);
+ addInstruction(load);
+ } else if (kind == IR::Member::MemberOfQmlContextObject) {
+ Instruction::LoadContextObjectProperty load;
+ load.base = getParam(source);
+ load.propertyIndex = index;
+ load.result = getResultParam(target);
+ addInstruction(load);
+ } else if (kind == IR::Member::MemberOfIdObjectsArray) {
+ Instruction::LoadIdObject load;
+ load.base = getParam(source);
+ load.index = index;
+ load.result = getResultParam(target);
+ addInstruction(load);
+ } else {
+ Q_ASSERT(false);
+ }
+}
+
void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target)
{
if (attachedPropertiesId != 0) {
@@ -1124,6 +1177,25 @@ void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args
addInstruction(call);
}
+void InstructionSelection::callBuiltinTypeofQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::Expr *result)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject) {
+ Instruction::CallBuiltinTypeofScopeObjectProperty call;
+ call.base = getParam(base);
+ call.index = propertyIndex;
+ call.result = getResultParam(result);
+ addInstruction(call);
+ } else if (kind == IR::Member::MemberOfQmlContextObject) {
+ Instruction::CallBuiltinTypeofContextObjectProperty call;
+ call.base = getParam(base);
+ call.index = propertyIndex;
+ call.result = getResultParam(result);
+ addInstruction(call);
+ } else {
+ Q_UNREACHABLE();
+ }
+}
+
void InstructionSelection::callBuiltinTypeofMember(IR::Expr *base, const QString &name,
IR::Expr *result)
{
@@ -1444,7 +1516,7 @@ ptrdiff_t InstructionSelection::addInstructionHelper(Instr::Type type, Instr &in
void InstructionSelection::patchJumpAddresses()
{
typedef QHash<IR::BasicBlock *, QVector<ptrdiff_t> >::ConstIterator PatchIt;
- for (PatchIt i = _patches.begin(), ei = _patches.end(); i != ei; ++i) {
+ for (PatchIt i = _patches.cbegin(), ei = _patches.cend(); i != ei; ++i) {
Q_ASSERT(_addrs.contains(i.key()));
ptrdiff_t target = _addrs.value(i.key());
diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h
index 4ea0f1d07f..e2385aad6d 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -34,6 +34,17 @@
#ifndef QV4ISEL_MOTH_P_H
#define QV4ISEL_MOTH_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qv4global_p.h>
#include <private/qv4isel_p.h>
#include <private/qv4isel_util_p.h>
@@ -73,6 +84,7 @@ protected:
virtual void visitRet(IR::Ret *);
virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result);
+ virtual void callBuiltinTypeofQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::Expr *result);
virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Expr *result);
virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result);
virtual void callBuiltinTypeofName(const QString &name, IR::Expr *result);
@@ -95,6 +107,7 @@ protected:
virtual void callBuiltinSetupArgumentObject(IR::Expr *result);
virtual void callBuiltinConvertThisToObject();
virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result);
+ virtual void callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result);
virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result);
virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result);
virtual void convertType(IR::Expr *source, IR::Expr *target);
@@ -102,10 +115,8 @@ protected:
virtual void constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result);
virtual void constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result);
virtual void loadThisObject(IR::Expr *e);
- virtual void loadQmlIdArray(IR::Expr *e);
+ virtual void loadQmlContext(IR::Expr *e);
virtual void loadQmlImportedScripts(IR::Expr *e);
- virtual void loadQmlContextObject(IR::Expr *e);
- virtual void loadQmlScopeObject(IR::Expr *e);
virtual void loadQmlSingleton(const QString &name, IR::Expr *e);
virtual void loadConst(IR::Const *sourceConst, IR::Expr *e);
virtual void loadString(const QString &str, IR::Expr *target);
@@ -115,7 +126,9 @@ protected:
virtual void initClosure(IR::Closure *closure, IR::Expr *target);
virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target);
virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName);
+ virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex);
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex);
+ virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target);
virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target);
virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target);
virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex);
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index 54b184b4eb..184cff43e6 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -36,7 +36,7 @@
#include "qv4jsir_p.h"
#include "qv4isel_p.h"
#include "qv4isel_util_p.h"
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#ifndef V4_BOOTSTRAP
#include <private/qqmlpropertycache_p.h>
#endif
@@ -91,12 +91,8 @@ void IRDecoder::visitMove(IR::Move *s)
if (IR::Name *n = s->source->asName()) {
if (n->id && *n->id == QStringLiteral("this")) // TODO: `this' should be a builtin.
loadThisObject(s->target);
- else if (n->builtin == IR::Name::builtin_qml_id_array)
- loadQmlIdArray(s->target);
- else if (n->builtin == IR::Name::builtin_qml_context_object)
- loadQmlContextObject(s->target);
- else if (n->builtin == IR::Name::builtin_qml_scope_object)
- loadQmlScopeObject(s->target);
+ else if (n->builtin == IR::Name::builtin_qml_context)
+ loadQmlContext(s->target);
else if (n->builtin == IR::Name::builtin_qml_imported_scripts_object)
loadQmlImportedScripts(s->target);
else if (n->qmlSingleton)
@@ -140,8 +136,8 @@ void IRDecoder::visitMove(IR::Move *s)
#else
bool captureRequired = true;
- Q_ASSERT(m->kind != IR::Member::MemberOfEnum);
- const int attachedPropertiesId = m->attachedPropertiesIdOrEnumValue;
+ Q_ASSERT(m->kind != IR::Member::MemberOfEnum && m->kind != IR::Member::MemberOfIdObjectsArray);
+ const int attachedPropertiesId = m->attachedPropertiesId;
const bool isSingletonProperty = m->kind == IR::Member::MemberOfSingletonObject;
if (_function && attachedPropertiesId == 0 && !m->property->isConstant()) {
@@ -153,9 +149,16 @@ void IRDecoder::visitMove(IR::Move *s)
captureRequired = false;
}
}
+ if (m->kind == IR::Member::MemberOfQmlScopeObject || m->kind == IR::Member::MemberOfQmlContextObject) {
+ getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->property->coreIndex, s->target);
+ return;
+ }
getQObjectProperty(m->base, m->property->coreIndex, captureRequired, isSingletonProperty, attachedPropertiesId, s->target);
#endif // V4_BOOTSTRAP
return;
+ } else if (m->kind == IR::Member::MemberOfIdObjectsArray) {
+ getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->idIndex, s->target);
+ return;
} else if (m->base->asTemp() || m->base->asConst() || m->base->asArgLocal()) {
getProperty(m->base, *m->name, s->target);
return;
@@ -174,6 +177,13 @@ void IRDecoder::visitMove(IR::Move *s)
callBuiltin(c, s->target);
return;
} else if (Member *member = c->base->asMember()) {
+#ifndef V4_BOOTSTRAP
+ Q_ASSERT(member->kind != IR::Member::MemberOfIdObjectsArray);
+ if (member->kind == IR::Member::MemberOfQmlScopeObject || member->kind == IR::Member::MemberOfQmlContextObject) {
+ callQmlContextProperty(member->base, (IR::Member::MemberKind)member->kind, member->property->coreIndex, c->args, s->target);
+ return;
+ }
+#endif
callProperty(member->base, *member->name, c->args, s->target);
return;
} else if (Subscript *ss = c->base->asSubscript()) {
@@ -192,11 +202,16 @@ void IRDecoder::visitMove(IR::Move *s)
if (m->base->asTemp() || m->base->asConst() || m->base->asArgLocal()) {
if (s->source->asTemp() || s->source->asConst() || s->source->asArgLocal()) {
Q_ASSERT(m->kind != IR::Member::MemberOfEnum);
- const int attachedPropertiesId = m->attachedPropertiesIdOrEnumValue;
+ Q_ASSERT(m->kind != IR::Member::MemberOfIdObjectsArray);
+ const int attachedPropertiesId = m->attachedPropertiesId;
if (m->property && attachedPropertiesId == 0) {
#ifdef V4_BOOTSTRAP
Q_UNIMPLEMENTED();
#else
+ if (m->kind == IR::Member::MemberOfQmlScopeObject || m->kind == IR::Member::MemberOfQmlContextObject) {
+ setQmlContextProperty(s->source, m->base, (IR::Member::MemberKind)m->kind, m->property->coreIndex);
+ return;
+ }
setQObjectProperty(s->source, m->base, m->property->coreIndex);
#endif
return;
@@ -238,6 +253,13 @@ void IRDecoder::visitExp(IR::Exp *s)
callValue(c->base, c->args, 0);
} else if (Member *member = c->base->asMember()) {
Q_ASSERT(member->base->asTemp() || member->base->asArgLocal());
+#ifndef V4_BOOTSTRAP
+ Q_ASSERT(member->kind != IR::Member::MemberOfIdObjectsArray);
+ if (member->kind == IR::Member::MemberOfQmlScopeObject || member->kind == IR::Member::MemberOfQmlContextObject) {
+ callQmlContextProperty(member->base, (IR::Member::MemberKind)member->kind, member->property->coreIndex, c->args, 0);
+ return;
+ }
+#endif
callProperty(member->base, *member->name, c->args, 0);
} else if (Subscript *s = c->base->asSubscript()) {
callSubscript(s->base, s->index, c->args, 0);
@@ -260,8 +282,17 @@ void IRDecoder::callBuiltin(IR::Call *call, Expr *result)
return;
case IR::Name::builtin_typeof: {
- if (IR::Member *m = call->args->expr->asMember()) {
- callBuiltinTypeofMember(m->base, *m->name, result);
+ if (IR::Member *member = call->args->expr->asMember()) {
+#ifndef V4_BOOTSTRAP
+ Q_ASSERT(member->kind != IR::Member::MemberOfIdObjectsArray);
+ if (member->kind == IR::Member::MemberOfQmlScopeObject || member->kind == IR::Member::MemberOfQmlContextObject) {
+ callBuiltinTypeofQmlContextProperty(member->base,
+ IR::Member::MemberKind(member->kind),
+ member->property->coreIndex, result);
+ return;
+ }
+#endif
+ callBuiltinTypeofMember(member->base, *member->name, result);
return;
} else if (IR::Subscript *ss = call->args->expr->asSubscript()) {
callBuiltinTypeofSubscript(ss->base, ss->index, result);
diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h
index 1e273df93e..b78d323e7d 100644
--- a/src/qml/compiler/qv4isel_p.h
+++ b/src/qml/compiler/qv4isel_p.h
@@ -34,6 +34,17 @@
#ifndef QV4ISEL_P_H
#define QV4ISEL_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "private/qv4global_p.h"
#include "qv4jsir_p.h"
#include <private/qv4compileddata_p.h>
@@ -107,6 +118,7 @@ public: // visitor methods for StmtVisitor:
public: // to implement by subclasses:
virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void callBuiltinTypeofQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::Expr *result) = 0;
virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Expr *result) = 0;
virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result) = 0;
virtual void callBuiltinTypeofName(const QString &name, IR::Expr *result) = 0;
@@ -129,6 +141,7 @@ public: // to implement by subclasses:
virtual void callBuiltinSetupArgumentObject(IR::Expr *result) = 0;
virtual void callBuiltinConvertThisToObject() = 0;
virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result) = 0;
virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result) = 0;
virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result) = 0;
virtual void convertType(IR::Expr *source, IR::Expr *target) = 0;
@@ -136,10 +149,8 @@ public: // to implement by subclasses:
virtual void constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result) = 0;
virtual void constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result) = 0;
virtual void loadThisObject(IR::Expr *target) = 0;
- virtual void loadQmlIdArray(IR::Expr *target) = 0;
+ virtual void loadQmlContext(IR::Expr *target) = 0;
virtual void loadQmlImportedScripts(IR::Expr *target) = 0;
- virtual void loadQmlContextObject(IR::Expr *target) = 0;
- virtual void loadQmlScopeObject(IR::Expr *target) = 0;
virtual void loadQmlSingleton(const QString &name, IR::Expr *target) = 0;
virtual void loadConst(IR::Const *sourceConst, IR::Expr *target) = 0;
virtual void loadString(const QString &str, IR::Expr *target) = 0;
@@ -149,7 +160,9 @@ public: // to implement by subclasses:
virtual void initClosure(IR::Closure *closure, IR::Expr *target) = 0;
virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target) = 0;
virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target) = 0;
+ virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target) = 0;
virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName) = 0;
+ virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex) = 0;
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex) = 0;
virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target) = 0;
virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex) = 0;
diff --git a/src/qml/compiler/qv4isel_util_p.h b/src/qml/compiler/qv4isel_util_p.h
index 521c345228..9c4ab63ba6 100644
--- a/src/qml/compiler/qv4isel_util_p.h
+++ b/src/qml/compiler/qv4isel_util_p.h
@@ -34,6 +34,17 @@
#ifndef QV4ISEL_UTIL_P_H
#define QV4ISEL_UTIL_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "private/qv4value_p.h"
#include "qv4jsir_p.h"
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index 5c9cc98ade..685825e8ea 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -175,8 +175,8 @@ struct RemoveSharedExpressions: IR::StmtVisitor, IR::ExprVisitor
}
}
- template <typename _Expr>
- _Expr *cleanup(_Expr *expr)
+ template <typename Expr_>
+ Expr_ *cleanup(Expr_ *expr)
{
std::vector<Expr *>::iterator it = std::lower_bound(subexpressions.begin(), subexpressions.end(), expr);
if (it == subexpressions.end() || *it != expr) {
@@ -185,7 +185,7 @@ struct RemoveSharedExpressions: IR::StmtVisitor, IR::ExprVisitor
qSwap(uniqueExpr, e);
expr->accept(this);
qSwap(uniqueExpr, e);
- return static_cast<_Expr *>(e);
+ return static_cast<Expr_ *>(e);
}
// the cloned expression is unique by definition
@@ -341,14 +341,10 @@ const char *builtin_to_string(Name::Builtin b)
return "builtin_setup_argument_object";
case IR::Name::builtin_convert_this_to_object:
return "builtin_convert_this_to_object";
- case IR::Name::builtin_qml_id_array:
- return "builtin_qml_id_array";
+ case IR::Name::builtin_qml_context:
+ return "builtin_qml_context";
case IR::Name::builtin_qml_imported_scripts_object:
return "builtin_qml_imported_scripts_object";
- case IR::Name::builtin_qml_scope_object:
- return "builtin_qml_scope_object";
- case IR::Name::builtin_qml_context_object:
- return "builtin_qml_context_object";
}
return "builtin_(###FIXME)";
};
@@ -935,7 +931,7 @@ void CloneExpr::visitSubscript(Subscript *e)
void CloneExpr::visitMember(Member *e)
{
Expr *clonedBase = clone(e->base);
- cloned = block->MEMBER(clonedBase, e->name, e->property, e->kind, e->attachedPropertiesIdOrEnumValue);
+ cloned = block->MEMBER(clonedBase, e->name, e->property, e->kind, e->idIndex);
}
IRPrinter::IRPrinter(QTextStream *out)
@@ -1239,9 +1235,9 @@ void IRPrinter::visitSubscript(Subscript *e)
void IRPrinter::visitMember(Member *e)
{
- if (e->kind != Member::MemberOfEnum
- && e->attachedPropertiesIdOrEnumValue != 0 && !e->base->asTemp())
- *out << "[[attached property from " << e->attachedPropertiesIdOrEnumValue << "]]";
+ if (e->kind != Member::MemberOfEnum && e->kind != Member::MemberOfIdObjectsArray
+ && e->attachedPropertiesId != 0 && !e->base->asTemp())
+ *out << "[[attached property from " << e->attachedPropertiesId << "]]";
else
e->base->accept(this);
*out << '.' << *e->name;
@@ -1250,6 +1246,8 @@ void IRPrinter::visitMember(Member *e)
*out << " (meta-property " << e->property->coreIndex
<< " <" << QMetaType::typeName(e->property->propType)
<< ">)";
+ else if (e->kind == Member::MemberOfIdObjectsArray)
+ *out << "(id object " << e->idIndex << ")";
#endif
}
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 8daad97e8b..80869dd3e3 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -53,6 +53,7 @@
#include <QtCore/QString>
#include <QtCore/QBitArray>
#include <QtCore/qurl.h>
+#include <QtCore/QVarLengthArray>
#include <qglobal.h>
#if defined(CONST) && defined(Q_OS_WIN)
@@ -114,6 +115,23 @@ struct CJump;
struct Ret;
struct Phi;
+template<class T, int Prealloc>
+class VarLengthArray: public QVarLengthArray<T, Prealloc>
+{
+public:
+ bool removeOne(const T &element)
+ {
+ for (int i = 0; i < this->size(); ++i) {
+ if (this->at(i) == element) {
+ this->remove(i);
+ return true;
+ }
+ }
+
+ return false;
+ }
+};
+
// Flag pointer:
// * The first flag indicates whether the meta object is final.
// If final, then none of its properties themselves need to
@@ -337,10 +355,8 @@ struct Name: Expr {
builtin_define_object_literal,
builtin_setup_argument_object,
builtin_convert_this_to_object,
- builtin_qml_id_array,
- builtin_qml_imported_scripts_object,
- builtin_qml_context_object,
- builtin_qml_scope_object
+ builtin_qml_context,
+ builtin_qml_imported_scripts_object
};
const QString *id;
@@ -368,18 +384,18 @@ struct Q_AUTOTEST_EXPORT Temp: Expr {
StackSlot
};
- // Used when temp is used as base in member expression
- MemberExpressionResolver *memberResolver;
-
unsigned index : 28;
unsigned isReadOnly : 1;
unsigned kind : 3;
+ // Used when temp is used as base in member expression
+ MemberExpressionResolver *memberResolver;
+
Temp()
- : memberResolver(0)
- , index((1 << 28) - 1)
+ : index((1 << 28) - 1)
, isReadOnly(0)
, kind(Invalid)
+ , memberResolver(0)
{}
void init(unsigned kind, unsigned index)
@@ -558,13 +574,18 @@ struct Member: Expr {
MemberOfEnum,
MemberOfQmlScopeObject,
MemberOfQmlContextObject,
- MemberOfSingletonObject
+ MemberOfIdObjectsArray,
+ MemberOfSingletonObject,
};
Expr *base;
const QString *name;
QQmlPropertyData *property;
- int attachedPropertiesIdOrEnumValue; // depending on kind
+ union { // depending on kind
+ int attachedPropertiesId;
+ int enumValue;
+ int idIndex;
+ };
uchar freeOfSideEffects : 1;
// This is set for example for for QObject properties. All sorts of extra behavior
@@ -577,20 +598,20 @@ struct Member: Expr {
void setEnumValue(int value) {
kind = MemberOfEnum;
- attachedPropertiesIdOrEnumValue = value;
+ enumValue = value;
}
void setAttachedPropertiesId(int id) {
- Q_ASSERT(kind != MemberOfEnum);
- attachedPropertiesIdOrEnumValue = id;
+ Q_ASSERT(kind != MemberOfEnum && kind != MemberOfIdObjectsArray);
+ attachedPropertiesId = id;
}
- void init(Expr *base, const QString *name, QQmlPropertyData *property = 0, uchar kind = UnspecifiedMember, int attachedPropertiesIdOrEnumValue = 0)
+ void init(Expr *base, const QString *name, QQmlPropertyData *property = 0, uchar kind = UnspecifiedMember, int index = 0)
{
this->base = base;
this->name = name;
this->property = property;
- this->attachedPropertiesIdOrEnumValue = attachedPropertiesIdOrEnumValue;
+ this->idIndex = index;
this->freeOfSideEffects = false;
this->inhibitTypeConversionOnWrite = property != 0;
this->kind = kind;
@@ -768,10 +789,13 @@ private:
Q_DISABLE_COPY(BasicBlock)
public:
+ typedef VarLengthArray<BasicBlock *, 4> IncomingEdges;
+ typedef VarLengthArray<BasicBlock *, 2> OutgoingEdges;
+
Function *function;
BasicBlock *catchBlock;
- QVector<BasicBlock *> in;
- QVector<BasicBlock *> out;
+ IncomingEdges in;
+ OutgoingEdges out;
QQmlJS::AST::SourceLocation nextLocation;
BasicBlock(Function *function, BasicBlock *catcher)
@@ -782,10 +806,7 @@ public:
, _isExceptionHandler(false)
, _groupStart(false)
, _isRemoved(false)
- {
- in.reserve(2);
- out.reserve(2);
- }
+ {}
~BasicBlock();
const QVector<Stmt *> &statements() const
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index c0669d3e47..f20dbbf4fe 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -69,7 +69,7 @@ enum { DoVerification = 1 };
static void showMeTheCode(IR::Function *function, const char *marker)
{
- static bool showCode = !qgetenv("QV4_SHOW_IR").isNull();
+ static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_IR");
if (showCode) {
qDebug() << marker;
QBuffer buf;
@@ -477,7 +477,7 @@ class DominatorTree
d->vertex[d->N] = n;
d->parent[n] = todo.parent;
++d->N;
- const QVector<BasicBlock *> &out = function->basicBlock(n)->out;
+ const BasicBlock::OutgoingEdges &out = function->basicBlock(n)->out;
for (int i = out.size() - 1; i > 0; --i)
worklist.push_back(DFSTodo(out[i]->index(), n));
@@ -2028,32 +2028,16 @@ private:
}
};
-class EliminateDeadCode: public ExprVisitor {
- DefUses &_defUses;
- StatementWorklist &_worklist;
+class SideEffectsChecker: public ExprVisitor
+{
bool _sideEffect;
- QVector<Temp *> _collectedTemps;
public:
- EliminateDeadCode(DefUses &defUses, StatementWorklist &worklist)
- : _defUses(defUses)
- , _worklist(worklist)
- {
- _collectedTemps.reserve(8);
- }
-
- void run(Expr *&expr, Stmt *stmt) {
- if (!checkForSideEffects(expr)) {
- expr = 0;
- foreach (Temp *t, _collectedTemps) {
- _defUses.removeUse(stmt, *t);
- _worklist += _defUses.defStmt(*t);
- }
- }
- }
+ SideEffectsChecker()
+ : _sideEffect(false)
+ {}
-private:
- bool checkForSideEffects(Expr *expr)
+ bool hasSideEffects(Expr *expr)
{
bool sideEffect = false;
qSwap(_sideEffect, sideEffect);
@@ -2062,19 +2046,20 @@ private:
return sideEffect;
}
+protected:
void markAsSideEffect()
{
_sideEffect = true;
- _collectedTemps.clear();
}
+ bool seenSideEffects() const { return _sideEffect; }
+
protected:
- virtual void visitConst(Const *) {}
- virtual void visitString(IR::String *) {}
- virtual void visitRegExp(IR::RegExp *) {}
+ void visitConst(Const *) Q_DECL_OVERRIDE {}
+ void visitString(IR::String *) Q_DECL_OVERRIDE {}
+ void visitRegExp(IR::RegExp *) Q_DECL_OVERRIDE {}
- virtual void visitName(Name *e)
- {
+ void visitName(Name *e) Q_DECL_OVERRIDE {
if (e->freeOfSideEffects)
return;
// TODO: maybe we can distinguish between built-ins of which we know that they do not have
@@ -2083,19 +2068,14 @@ protected:
markAsSideEffect();
}
- virtual void visitTemp(Temp *e)
- {
- _collectedTemps.append(e);
- }
-
- virtual void visitArgLocal(ArgLocal *) {}
+ void visitTemp(Temp *) Q_DECL_OVERRIDE {}
+ void visitArgLocal(ArgLocal *) Q_DECL_OVERRIDE {}
- virtual void visitClosure(Closure *)
- {
+ void visitClosure(Closure *) Q_DECL_OVERRIDE {
markAsSideEffect();
}
- virtual void visitConvert(Convert *e) {
+ void visitConvert(Convert *e) Q_DECL_OVERRIDE {
e->expr->accept(this);
switch (e->expr->type) {
@@ -2109,7 +2089,7 @@ protected:
}
}
- virtual void visitUnop(Unop *e) {
+ void visitUnop(Unop *e) Q_DECL_OVERRIDE {
e->expr->accept(this);
switch (e->op) {
@@ -2127,39 +2107,39 @@ protected:
}
}
- virtual void visitBinop(Binop *e) {
+ void visitBinop(Binop *e) Q_DECL_OVERRIDE {
// TODO: prune parts that don't have a side-effect. For example, in:
// function f(x) { +x+1; return 0; }
// we can prune the binop and leave the unop/conversion.
- _sideEffect = checkForSideEffects(e->left);
- _sideEffect |= checkForSideEffects(e->right);
+ _sideEffect = hasSideEffects(e->left);
+ _sideEffect |= hasSideEffects(e->right);
if (e->left->type == VarType || e->left->type == StringType || e->left->type == QObjectType
|| e->right->type == VarType || e->right->type == StringType || e->right->type == QObjectType)
markAsSideEffect();
}
- virtual void visitSubscript(Subscript *e) {
+ void visitSubscript(Subscript *e) Q_DECL_OVERRIDE {
e->base->accept(this);
e->index->accept(this);
markAsSideEffect();
}
- virtual void visitMember(Member *e) {
+ void visitMember(Member *e) Q_DECL_OVERRIDE {
e->base->accept(this);
if (e->freeOfSideEffects)
return;
markAsSideEffect();
}
- virtual void visitCall(Call *e) {
+ void visitCall(Call *e) Q_DECL_OVERRIDE {
e->base->accept(this);
for (ExprList *args = e->args; args; args = args->next)
args->expr->accept(this);
markAsSideEffect(); // TODO: there are built-in functions that have no side effect.
}
- virtual void visitNew(New *e) {
+ void visitNew(New *e) Q_DECL_OVERRIDE {
e->base->accept(this);
for (ExprList *args = e->args; args; args = args->next)
args->expr->accept(this);
@@ -2167,6 +2147,38 @@ protected:
}
};
+class EliminateDeadCode: public SideEffectsChecker
+{
+ DefUses &_defUses;
+ StatementWorklist &_worklist;
+ QVector<Temp *> _collectedTemps;
+
+public:
+ EliminateDeadCode(DefUses &defUses, StatementWorklist &worklist)
+ : _defUses(defUses)
+ , _worklist(worklist)
+ {
+ _collectedTemps.reserve(8);
+ }
+
+ void run(Expr *&expr, Stmt *stmt) {
+ _collectedTemps.clear();
+ if (!hasSideEffects(expr)) {
+ expr = 0;
+ foreach (Temp *t, _collectedTemps) {
+ _defUses.removeUse(stmt, *t);
+ _worklist += _defUses.defStmt(*t);
+ }
+ }
+ }
+
+protected:
+ void visitTemp(Temp *e) Q_DECL_OVERRIDE
+ {
+ _collectedTemps.append(e);
+ }
+};
+
struct DiscoveredType {
int type;
MemberExpressionResolver *memberResolver;
@@ -3504,7 +3516,7 @@ void checkCriticalEdges(QVector<BasicBlock *> basicBlocks) {
}
#endif
-void cleanupBasicBlocks(IR::Function *function)
+static void cleanupBasicBlocks(IR::Function *function)
{
showMeTheCode(function, "Before basic block cleanup");
@@ -3887,7 +3899,7 @@ bool tryOptimizingComparison(Expr *&expr)
void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops = QVector<LoopDetection::LoopInfo *>())
{
- static bool showCode = !qgetenv("QV4_SHOW_IR").isNull();
+ static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_IR");
if (!showCode)
return;
@@ -3912,7 +3924,7 @@ void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops =
QString name;
if (f->name) name = *f->name;
- else name = QString::fromLatin1("%1").arg((unsigned long long)f);
+ else name = QStringLiteral("%1").arg((unsigned long long)f);
qout << "digraph \"" << name << "\" { ordering=out;\n";
foreach (LoopDetection::LoopInfo *l, loops) {
@@ -4020,14 +4032,14 @@ void optimizeSSA(StatementWorklist &W, DefUses &defUses, DominatorTree &df)
if (Member *member = m->source->asMember()) {
if (member->kind == Member::MemberOfEnum) {
Const *c = function->New<Const>();
- const int enumValue = member->attachedPropertiesIdOrEnumValue;
+ const int enumValue = member->enumValue;
c->init(SInt32Type, enumValue);
replaceUses(targetTemp, c, W);
defUses.removeDef(*targetTemp);
W.remove(s);
defUses.removeUse(s, *member->base->asTemp());
continue;
- } else if (member->attachedPropertiesIdOrEnumValue != 0 && member->property && member->base->asTemp()) {
+ } else if (member->kind != IR::Member::MemberOfIdObjectsArray && member->attachedPropertiesId != 0 && member->property && member->base->asTemp()) {
// Attached properties have no dependency on their base. Isel doesn't
// need it and we can eliminate the temp used to initialize it.
defUses.removeUse(s, *member->base->asTemp());
@@ -4927,6 +4939,39 @@ static void verifyNoPointerSharing(IR::Function *function)
V(function);
}
+class RemoveLineNumbers: public SideEffectsChecker, public StmtVisitor
+{
+public:
+ static void run(IR::Function *function)
+ {
+ foreach (BasicBlock *bb, function->basicBlocks()) {
+ if (bb->isRemoved())
+ continue;
+
+ foreach (Stmt *s, bb->statements()) {
+ if (!hasSideEffects(s)) {
+ s->location = QQmlJS::AST::SourceLocation();
+ }
+ }
+ }
+ }
+
+private:
+ static bool hasSideEffects(Stmt *stmt)
+ {
+ RemoveLineNumbers checker;
+ stmt->accept(&checker);
+ return checker.seenSideEffects();
+ }
+
+ void visitExp(Exp *s) Q_DECL_OVERRIDE { s->expr->accept(this); }
+ void visitMove(Move *s) Q_DECL_OVERRIDE { s->source->accept(this); s->target->accept(this); }
+ void visitJump(Jump *) Q_DECL_OVERRIDE {}
+ void visitCJump(CJump *s) Q_DECL_OVERRIDE { s->cond->accept(this); }
+ void visitRet(Ret *s) Q_DECL_OVERRIDE { s->expr->accept(this); }
+ void visitPhi(Phi *) Q_DECL_OVERRIDE {}
+};
+
} // anonymous namespace
void LifeTimeInterval::setFrom(int from) {
@@ -5150,12 +5195,15 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
cleanupBasicBlocks(function);
function->removeSharedExpressions();
-
+ int statementCount = 0;
+ foreach (BasicBlock *bb, function->basicBlocks())
+ if (!bb->isRemoved())
+ statementCount += bb->statementCount();
// showMeTheCode(function);
- static bool doSSA = qgetenv("QV4_NO_SSA").isEmpty();
+ static bool doSSA = qEnvironmentVariableIsEmpty("QV4_NO_SSA");
- if (!function->hasTry && !function->hasWith && !function->module->debugMode && doSSA) {
+ if (!function->hasTry && !function->hasWith && !function->module->debugMode && doSSA && statementCount <= 300) {
// qout << "SSA for " << (function->name ? qPrintable(*function->name) : "<anonymous>") << endl;
ConvertArgLocals(function).toTemps();
@@ -5221,7 +5269,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
verifyNoPointerSharing(function);
}
- static bool doOpt = qgetenv("QV4_NO_OPT").isEmpty();
+ static const bool doOpt = qEnvironmentVariableIsEmpty("QV4_NO_OPT");
if (doOpt) {
// qout << "Running SSA optimization..." << endl;
worklist.reset();
@@ -5259,6 +5307,11 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
checkCriticalEdges(function->basicBlocks());
#endif
+ if (!function->module->debugMode) {
+ RemoveLineNumbers::run(function);
+ showMeTheCode(function, "After line number removal");
+ }
+
// qout << "Finished SSA." << endl;
inSSA = true;
} else {
diff --git a/src/qml/compiler/qv4ssa_p.h b/src/qml/compiler/qv4ssa_p.h
index 3cfacaee27..d06774e803 100644
--- a/src/qml/compiler/qv4ssa_p.h
+++ b/src/qml/compiler/qv4ssa_p.h
@@ -34,6 +34,17 @@
#ifndef QV4SSA_P_H
#define QV4SSA_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4jsir_p.h"
#include <QtCore/QSharedPointer>
diff --git a/src/qml/debugger/debugger.pri b/src/qml/debugger/debugger.pri
index 77a3ba6490..30a44eedd1 100644
--- a/src/qml/debugger/debugger.pri
+++ b/src/qml/debugger/debugger.pri
@@ -1,36 +1,23 @@
+contains(QT_CONFIG, no-qml-debug):DEFINES += QT_NO_QML_DEBUGGER
+
SOURCES += \
+ $$PWD/qqmldebug.cpp \
+ $$PWD/qqmldebugconnector.cpp \
$$PWD/qqmldebugservice.cpp \
- $$PWD/qqmlprofilerservice.cpp \
- $$PWD/qqmldebugserver.cpp \
- $$PWD/qqmlinspectorservice.cpp \
- $$PWD/qqmlenginedebugservice.cpp \
- $$PWD/qdebugmessageservice.cpp \
- $$PWD/qv4debugservice.cpp \
- $$PWD/qqmlconfigurabledebugservice.cpp \
- $$PWD/qqmlenginecontrolservice.cpp \
+ $$PWD/qqmldebugserviceinterfaces.cpp \
$$PWD/qqmlabstractprofileradapter.cpp \
- $$PWD/qv4profileradapter.cpp \
$$PWD/qqmlprofiler.cpp
HEADERS += \
+ $$PWD/qqmldebugconnector_p.h \
+ $$PWD/qqmldebugpluginmanager_p.h \
$$PWD/qqmldebugservice_p.h \
- $$PWD/qqmldebugservice_p_p.h \
- $$PWD/qqmlprofilerservice_p.h \
- $$PWD/qqmldebugserver_p.h \
- $$PWD/qqmldebugserverconnection_p.h \
+ $$PWD/qqmldebugservicefactory_p.h \
+ $$PWD/qqmldebugserviceinterfaces_p.h \
$$PWD/qqmldebugstatesdelegate_p.h \
- $$PWD/qqmlinspectorservice_p.h \
- $$PWD/qqmlinspectorinterface_p.h \
- $$PWD/qqmlenginedebugservice_p.h \
$$PWD/qqmldebug.h \
- $$PWD/qdebugmessageservice_p.h \
- $$PWD/qv4debugservice_p.h \
- $$PWD/qqmlconfigurabledebugservice_p.h \
- $$PWD/qqmlconfigurabledebugservice_p_p.h \
- $$PWD/qqmlenginecontrolservice_p.h \
$$PWD/qqmlprofilerdefinitions_p.h \
$$PWD/qqmlabstractprofileradapter_p.h \
- $$PWD/qv4profileradapter_p.h \
$$PWD/qqmlprofiler_p.h
INCLUDEPATH += $$PWD
diff --git a/src/qml/debugger/qqmlconfigurabledebugservice.cpp b/src/qml/debugger/qqmlconfigurabledebugservice.cpp
deleted file mode 100644
index e3693e00a4..0000000000
--- a/src/qml/debugger/qqmlconfigurabledebugservice.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlconfigurabledebugservice_p.h"
-#include "qqmlconfigurabledebugservice_p_p.h"
-
-QT_BEGIN_NAMESPACE
-
-QQmlConfigurableDebugService::QQmlConfigurableDebugService(const QString &name, float version,
- QObject *parent) :
- QQmlDebugService((*new QQmlConfigurableDebugServicePrivate), name, version, parent) { init(); }
-
-QQmlConfigurableDebugService::QQmlConfigurableDebugService(QQmlDebugServicePrivate &dd,
- const QString &name, float version,
- QObject *parent) :
- QQmlDebugService(dd, name, version, parent) { init(); }
-
-QMutex *QQmlConfigurableDebugService::configMutex()
-{
- Q_D(QQmlConfigurableDebugService);
- return &d->configMutex;
-}
-
-void QQmlConfigurableDebugService::init()
-{
- Q_D(QQmlConfigurableDebugService);
- QMutexLocker lock(&d->configMutex);
- // If we're not enabled or not blocking, don't wait for configuration
- d->waitingForConfiguration = (registerService() == Enabled && blockingMode());
-}
-
-void QQmlConfigurableDebugService::stopWaiting()
-{
- Q_D(QQmlConfigurableDebugService);
- QMutexLocker lock(&d->configMutex);
- d->waitingForConfiguration = false;
- foreach (QQmlEngine *engine, d->waitingEngines)
- emit attachedToEngine(engine);
- d->waitingEngines.clear();
-}
-
-void QQmlConfigurableDebugService::stateChanged(QQmlDebugService::State newState)
-{
- if (newState != Enabled)
- stopWaiting();
-}
-
-void QQmlConfigurableDebugService::engineAboutToBeAdded(QQmlEngine *engine)
-{
- Q_D(QQmlConfigurableDebugService);
- QMutexLocker lock(&d->configMutex);
- if (d->waitingForConfiguration)
- d->waitingEngines.append(engine);
- else
- emit attachedToEngine(engine);
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmldebug.cpp b/src/qml/debugger/qqmldebug.cpp
new file mode 100644
index 0000000000..35dc110e9a
--- /dev/null
+++ b/src/qml/debugger/qqmldebug.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmldebug.h"
+#include "qqmldebugconnector_p.h"
+
+#include <private/qqmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
+{
+#ifndef QQML_NO_DEBUG_PROTOCOL
+ if (!QQmlEnginePrivate::qml_debugging_enabled
+ && printWarning) {
+ qDebug("QML debugging is enabled. Only use this in a safe environment.");
+ }
+ QQmlEnginePrivate::qml_debugging_enabled = true;
+#else
+ Q_UNUSED(printWarning);
+#endif
+}
+
+/*!
+ * \enum QQmlDebuggingEnabler::StartMode
+ *
+ * Defines the debug server's start behavior. You can interrupt QML engines starting while a debug
+ * client is connecting, in order to set breakpoints in or profile startup code.
+ *
+ * \value DoNotWaitForClient Run any QML engines as usual while the debug services are connecting.
+ * \value WaitForClient If a QML engine starts while the debug services are connecting,
+ * interrupt it until they are done.
+ */
+
+/*!
+ * Enables debugging for QML engines created after calling this function. The debug server will
+ * listen on \a port at \a hostName and block the QML engine until it receives a connection if
+ * \a mode is \c WaitForClient. If \a mode is not specified it won't block and if \a hostName is not
+ * specified it will listen on all available interfaces. You can only start one debug server at a
+ * time. A debug server may have already been started if the -qmljsdebugger= command line argument
+ * was given. This method returns \c true if a new debug server was successfully started, or
+ * \c false otherwise.
+ */
+bool QQmlDebuggingEnabler::startTcpDebugServer(int port, StartMode mode, const QString &hostName)
+{
+#ifndef QQML_NO_DEBUG_PROTOCOL
+ QQmlDebugConnector::setPluginKey(QLatin1String("QQmlDebugServer"));
+ QQmlDebugConnector *connector = QQmlDebugConnector::instance();
+ if (connector) {
+ QVariantHash configuration;
+ configuration[QLatin1String("portFrom")] = configuration[QLatin1String("portTo")] = port;
+ configuration[QLatin1String("block")] = (mode == WaitForClient);
+ configuration[QLatin1String("hostAddress")] = hostName;
+ return connector->open(configuration);
+ }
+#else
+ Q_UNUSED(port);
+ Q_UNUSED(block);
+ Q_UNUSED(hostName);
+#endif
+ return false;
+}
+
+/*!
+ * \since 5.6
+ *
+ * Enables debugging for QML engines created after calling this function. The debug server will
+ * connect to a debugger waiting on a local socket at the given \a socketFileName and block the QML
+ * engine until the connection is established if \a mode is \c WaitForClient. If \a mode is not
+ * specified it will not block. You can only start one debug server at a time. A debug server may
+ * have already been started if the -qmljsdebugger= command line argument was given. This method
+ * returns \c true if a new debug server was successfully started, or \c false otherwise.
+ */
+bool QQmlDebuggingEnabler::connectToLocalDebugger(const QString &socketFileName, StartMode mode)
+{
+#ifndef QQML_NO_DEBUG_PROTOCOL
+ QQmlDebugConnector::setPluginKey(QLatin1String("QQmlDebugServer"));
+ QQmlDebugConnector *connector = QQmlDebugConnector::instance();
+ if (connector) {
+ QVariantHash configuration;
+ configuration[QLatin1String("fileName")] = socketFileName;
+ configuration[QLatin1String("block")] = (mode == WaitForClient);
+ return connector->open(configuration);
+ }
+#else
+ Q_UNUSED(fileName);
+ Q_UNUSED(block);
+#endif
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmldebug.h b/src/qml/debugger/qqmldebug.h
index 559c492dfd..5d65982a49 100644
--- a/src/qml/debugger/qqmldebug.h
+++ b/src/qml/debugger/qqmldebug.h
@@ -50,6 +50,8 @@ struct Q_QML_EXPORT QQmlDebuggingEnabler
QQmlDebuggingEnabler(bool printWarning = true);
static bool startTcpDebugServer(int port, StartMode mode = DoNotWaitForClient,
const QString &hostName = QString());
+ static bool connectToLocalDebugger(const QString &socketFileName,
+ StartMode mode = DoNotWaitForClient);
};
// Execute code in constructor before first QQmlEngine is instantiated
diff --git a/src/qml/debugger/qqmldebugconnector.cpp b/src/qml/debugger/qqmldebugconnector.cpp
new file mode 100644
index 0000000000..64a8a49bb9
--- /dev/null
+++ b/src/qml/debugger/qqmldebugconnector.cpp
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmldebugpluginmanager_p.h"
+#include "qqmldebugconnector_p.h"
+#include "qqmldebugservicefactory_p.h"
+#include <QtCore/QPluginLoader>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+#include <QtCore/QJsonArray>
+
+#include <private/qcoreapplication_p.h>
+#include <private/qqmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// Connectors. We could add more plugins here, and distinguish by arguments to instance()
+Q_QML_DEBUG_PLUGIN_LOADER(QQmlDebugConnector)
+Q_QML_IMPORT_DEBUG_PLUGIN(QQmlDebugServerFactory)
+Q_QML_IMPORT_DEBUG_PLUGIN(QQmlNativeDebugConnectorFactory)
+
+// Services
+Q_QML_DEBUG_PLUGIN_LOADER(QQmlDebugService)
+Q_QML_IMPORT_DEBUG_PLUGIN(QQmlInspectorServiceFactory)
+Q_QML_IMPORT_DEBUG_PLUGIN(QQmlProfilerServiceFactory)
+Q_QML_IMPORT_DEBUG_PLUGIN(QQmlDebuggerServiceFactory)
+
+struct QQmlDebugConnectorParams {
+ QString pluginKey;
+ QStringList services;
+ QString arguments;
+ QQmlDebugConnector *instance;
+
+ QQmlDebugConnectorParams() : instance(0)
+ {
+ if (qApp) {
+ QCoreApplicationPrivate *appD =
+ static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
+ if (appD)
+ arguments = appD->qmljsDebugArgumentsString();
+ }
+ }
+};
+
+Q_GLOBAL_STATIC(QQmlDebugConnectorParams, qmlDebugConnectorParams)
+
+void QQmlDebugConnector::setPluginKey(const QString &key)
+{
+ QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
+ if (params) {
+ if (params->instance)
+ qWarning() << "QML debugger: Cannot set plugin key after loading the plugin.";
+ else
+ params->pluginKey = key;
+ }
+}
+
+void QQmlDebugConnector::setServices(const QStringList &services)
+{
+ QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
+ if (params)
+ params->services = services;
+}
+
+QString QQmlDebugConnector::commandLineArguments()
+{
+ QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
+ if (!params)
+ return QString();
+ return params->arguments;
+}
+
+QQmlDebugConnector *QQmlDebugConnector::instance()
+{
+ QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
+ if (!params)
+ return 0;
+
+ if (!QQmlEnginePrivate::qml_debugging_enabled) {
+ if (!params->arguments.isEmpty()) {
+ qWarning().noquote() << QString::fromLatin1(
+ "QML Debugger: Ignoring \"-qmljsdebugger=%1\". Debugging "
+ "has not been enabled.").arg(params->arguments);
+ params->arguments.clear();
+ }
+ return 0;
+ }
+
+ if (!params->instance) {
+ const QString serverConnector = QStringLiteral("QQmlDebugServer");
+ const QString nativeConnector = QStringLiteral("QQmlNativeDebugConnector");
+ const bool isNative = params->arguments.startsWith(QStringLiteral("native"));
+ if (!params->pluginKey.isEmpty()) {
+ if (params->pluginKey == serverConnector || params->pluginKey == nativeConnector)
+ params->instance = loadQQmlDebugConnector(params->pluginKey);
+ else
+ return 0; // We cannot load anything else, yet
+ } else if (params->arguments.isEmpty()) {
+ return 0; // no explicit class name given and no command line arguments
+ } else {
+ params->instance = loadQQmlDebugConnector(isNative ? nativeConnector : serverConnector);
+ }
+
+ if (params->instance) {
+ foreach (const QJsonObject &object, metaDataForQQmlDebugService()) {
+ foreach (const QJsonValue &key, object.value(QLatin1String("MetaData")).toObject()
+ .value(QLatin1String("Keys")).toArray()) {
+ QString keyString = key.toString();
+ if (params->services.isEmpty() || params->services.contains(keyString))
+ loadQQmlDebugService(keyString);
+ }
+ }
+ }
+ }
+
+ return params->instance;
+}
+
+QQmlDebugConnectorFactory::~QQmlDebugConnectorFactory()
+{
+ // This is triggered when the plugin is unloaded.
+ QQmlDebugConnectorParams *params = qmlDebugConnectorParams();
+ if (params && params->instance) {
+ delete params->instance;
+ params->instance = 0;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmldebugconnector_p.h b/src/qml/debugger/qqmldebugconnector_p.h
new file mode 100644
index 0000000000..f5f5a87b56
--- /dev/null
+++ b/src/qml/debugger/qqmldebugconnector_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLDEBUGCONNECTOR_H
+#define QQMLDEBUGCONNECTOR_H
+
+#include <QtQml/qtqmlglobal.h>
+#include <QtCore/QVariantList>
+
+#include <private/qqmldebugservice_p.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlDebugService;
+class Q_QML_PRIVATE_EXPORT QQmlDebugConnector : public QObject
+{
+ Q_OBJECT
+public:
+ static void setPluginKey(const QString &key);
+ static void setServices(const QStringList &services);
+ static QQmlDebugConnector *instance();
+
+ virtual bool blockingMode() const = 0;
+
+ virtual QQmlDebugService *service(const QString &name) const = 0;
+
+ virtual void addEngine(QQmlEngine *engine) = 0;
+ virtual void removeEngine(QQmlEngine *engine) = 0;
+
+ virtual bool addService(const QString &name, QQmlDebugService *service) = 0;
+ virtual bool removeService(const QString &name) = 0;
+
+ virtual bool open(const QVariantHash &configuration = QVariantHash()) = 0;
+
+ template<class Service>
+ static Service *service()
+ {
+ QQmlDebugConnector *inst = instance();
+ return inst ? static_cast<Service *>(inst->service(Service::s_key)) : 0;
+ }
+
+protected:
+ static QString commandLineArguments();
+};
+
+class Q_QML_PRIVATE_EXPORT QQmlDebugConnectorFactory : public QObject {
+ Q_OBJECT
+public:
+ virtual QQmlDebugConnector *create(const QString &key) = 0;
+ ~QQmlDebugConnectorFactory();
+};
+
+#define QQmlDebugConnectorFactory_iid "org.qt-project.Qt.QQmlDebugConnectorFactory"
+
+QT_END_NAMESPACE
+
+#endif // QQMLDEBUGCONNECTOR_H
diff --git a/src/qml/debugger/qqmldebugpluginmanager_p.h b/src/qml/debugger/qqmldebugpluginmanager_p.h
new file mode 100644
index 0000000000..6fffa67d7b
--- /dev/null
+++ b/src/qml/debugger/qqmldebugpluginmanager_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLDEBUGPLUGINMANAGER_P_H
+#define QQMLDEBUGPLUGINMANAGER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QDebug>
+#include <private/qtqmlglobal_p.h>
+#include <private/qfactoryloader_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#if defined(QT_NO_QML_DEBUGGER)
+
+#define Q_QML_DEBUG_PLUGIN_LOADER(interfaceName)\
+ interfaceName *load##interfaceName(const QString &key)\
+ {\
+ qWarning() << "Qml Debugger: QtQml is not configured for debugging. Ignoring request for"\
+ << "debug plugin" << key;\
+ return 0;\
+ }\
+ QList<QJsonObject> metaDataFor##interfaceName()\
+ {\
+ return QList<QJsonObject>();\
+ }
+#define Q_QML_IMPORT_DEBUG_PLUGIN(className)
+
+#else // QT_NO_QML_DEBUGGER
+
+#ifdef QT_STATIC
+#define Q_QML_IMPORT_DEBUG_PLUGIN(className)\
+ QT_END_NAMESPACE\
+ Q_IMPORT_PLUGIN(className)\
+ QT_BEGIN_NAMESPACE
+#else
+#define Q_QML_IMPORT_DEBUG_PLUGIN(className)
+#endif // QT_STATIC
+
+#define Q_QML_DEBUG_PLUGIN_LOADER(interfaceName)\
+ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, interfaceName##Loader,\
+ (interfaceName##Factory_iid, QLatin1String("/qmltooling")))\
+ interfaceName *load##interfaceName(const QString &key)\
+ {\
+ return qLoadPlugin<interfaceName, interfaceName##Factory>(interfaceName##Loader(), key);\
+ }\
+ QList<QJsonObject> metaDataFor##interfaceName()\
+ {\
+ return interfaceName##Loader()->metaData();\
+ }
+
+#endif // QT_NO_QML_DEBUGGER
+
+QT_END_NAMESPACE
+#endif // QQMLDEBUGPLUGINMANAGER_P_H
diff --git a/src/qml/debugger/qqmldebugserver.cpp b/src/qml/debugger/qqmldebugserver.cpp
deleted file mode 100644
index b0302181ee..0000000000
--- a/src/qml/debugger/qqmldebugserver.cpp
+++ /dev/null
@@ -1,787 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmldebugserver_p.h"
-#include "qqmldebugservice_p.h"
-#include "qqmldebugservice_p_p.h"
-#include "qqmlenginedebugservice_p.h"
-#include "qv4debugservice_p.h"
-#include "qdebugmessageservice_p.h"
-#include "qqmlprofilerservice_p.h"
-
-#include <private/qqmlengine_p.h>
-#include <private/qqmlglobal_p.h>
-
-#include <QtCore/QAtomicInt>
-#include <QtCore/QDir>
-#include <QtCore/QPluginLoader>
-#include <QtCore/QStringList>
-#include <QtCore/qwaitcondition.h>
-
-#include <private/qobject_p.h>
-#include <private/qcoreapplication_p.h>
-
-#if defined(QT_STATIC) && ! defined(QT_NO_QML_DEBUGGER)
-#include "../../plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h"
-#endif
-
-QT_BEGIN_NAMESPACE
-
-// We can't friend the Q_GLOBAL_STATIC to have the constructor available so we need a little
-// workaround here. Using this wrapper we can also make QQmlEnginePrivate's cleanup() available to
-// qAddPostRoutine(). We can't do the cleanup in the destructor because we need a QApplication to
-// be available when stopping the plugins.
-struct QQmlDebugServerInstanceWrapper {
- QQmlDebugServer m_instance;
- void cleanup();
-};
-
-Q_GLOBAL_STATIC(QQmlDebugServerInstanceWrapper, debugServerInstance)
-
-/*
- QQmlDebug Protocol (Version 1):
-
- handshake:
- 1. Client sends
- "QDeclarativeDebugServer" 0 version pluginNames [QDataStream version]
- version: an int representing the highest protocol version the client knows
- pluginNames: plugins available on client side
- 2. Server sends
- "QDeclarativeDebugClient" 0 version pluginNames pluginVersions [QDataStream version]
- version: an int representing the highest protocol version the client & server know
- pluginNames: plugins available on server side. plugins both in the client and server message are enabled.
- client plugin advertisement
- 1. Client sends
- "QDeclarativeDebugServer" 1 pluginNames
- server plugin advertisement
- 1. Server sends
- "QDeclarativeDebugClient" 1 pluginNames pluginVersions
- plugin communication:
- Everything send with a header different to "QDeclarativeDebugServer" is sent to the appropriate plugin.
- */
-
-const int protocolVersion = 1;
-int QQmlDebugServer::s_dataStreamVersion = QDataStream::Qt_4_7;
-
-// print detailed information about loading of plugins
-DEFINE_BOOL_CONFIG_OPTION(qmlDebugVerbose, QML_DEBUGGER_VERBOSE)
-
-class QQmlDebugServerThread;
-
-class QQmlDebugServerPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QQmlDebugServer)
-public:
- QQmlDebugServerPrivate();
-
- bool start(int portFrom, int portTo, bool block, const QString &hostAddress,
- const QString &pluginName);
- void advertisePlugins();
- void cleanup();
- QQmlDebugServerConnection *loadConnectionPlugin(const QString &pluginName);
-
- QQmlDebugServerConnection *connection;
- QHash<QString, QQmlDebugService *> plugins;
- mutable QReadWriteLock pluginsLock;
- QStringList clientPlugins;
- bool gotHello;
- bool blockingMode;
-
- class EngineCondition {
- public:
- EngineCondition() : numServices(0), condition(new QWaitCondition) {}
-
- bool waitForServices(QReadWriteLock *locked, int numEngines);
-
- void wake();
- private:
- int numServices;
-
- // shared pointer to allow for QHash-inflicted copying.
- QSharedPointer<QWaitCondition> condition;
- };
-
- QHash<QQmlEngine *, EngineCondition> engineConditions;
-
- QMutex helloMutex;
- QWaitCondition helloCondition;
- QQmlDebugServerThread *thread;
- QPluginLoader loader;
- QAtomicInt changeServiceStateCalls;
-
-private:
- // private slots
- void _q_changeServiceState(const QString &serviceName,
- QQmlDebugService::State newState);
- void _q_sendMessages(const QList<QByteArray> &messages);
- void _q_removeThread();
-};
-
-void QQmlDebugServerInstanceWrapper::cleanup()
-{ m_instance.d_func()->cleanup(); }
-
-class QQmlDebugServerThread : public QThread
-{
-public:
- void setPluginName(const QString &pluginName) {
- m_pluginName = pluginName;
- }
-
- void setPortRange(int portFrom, int portTo, bool block, const QString &hostAddress) {
- m_portFrom = portFrom;
- m_portTo = portTo;
- m_block = block;
- m_hostAddress = hostAddress;
- }
-
- void run();
-
-private:
- QString m_pluginName;
- int m_portFrom;
- int m_portTo;
- bool m_block;
- QString m_hostAddress;
-};
-
-QQmlDebugServerPrivate::QQmlDebugServerPrivate() :
- connection(0),
- pluginsLock(QReadWriteLock::Recursive),
- gotHello(false),
- blockingMode(false),
- thread(0)
-{
- // used in _q_sendMessages
- qRegisterMetaType<QList<QByteArray> >("QList<QByteArray>");
- // used in _q_changeServiceState
- qRegisterMetaType<QQmlDebugService::State>("QQmlDebugService::State");
-}
-
-void QQmlDebugServerPrivate::advertisePlugins()
-{
- Q_Q(QQmlDebugServer);
-
- if (!gotHello)
- return;
-
- QByteArray message;
- {
- QQmlDebugStream out(&message, QIODevice::WriteOnly);
- QStringList pluginNames;
- QList<float> pluginVersions;
- foreach (QQmlDebugService *service, plugins.values()) {
- pluginNames << service->name();
- pluginVersions << service->version();
- }
- out << QString(QStringLiteral("QDeclarativeDebugClient")) << 1 << pluginNames << pluginVersions;
- }
-
- QMetaObject::invokeMethod(q, "_q_sendMessages", Qt::QueuedConnection, Q_ARG(QList<QByteArray>, QList<QByteArray>() << message));
-}
-
-void QQmlDebugServerPrivate::cleanup()
-{
- Q_Q(QQmlDebugServer);
- {
- QReadLocker lock(&pluginsLock);
- foreach (QQmlDebugService *service, plugins.values()) {
- changeServiceStateCalls.ref();
- QMetaObject::invokeMethod(q, "_q_changeServiceState", Qt::QueuedConnection,
- Q_ARG(QString, service->name()),
- Q_ARG(QQmlDebugService::State, QQmlDebugService::NotConnected));
- }
- }
-
- // Wait for changeServiceState calls to finish
- // (while running an event loop because some services
- // might again use slots to execute stuff in the GUI thread)
- QEventLoop loop;
- while (!changeServiceStateCalls.testAndSetOrdered(0, 0))
- loop.processEvents();
-
- // Stop the thread while the application is still there. Copy here as the thread will set itself
- // to 0 when it stops. It will also do deleteLater, but as long as we don't allow the GUI
- // thread's event loop to run we're safe from that.
- QThread *threadCopy = thread;
- if (threadCopy) {
- threadCopy->exit();
- threadCopy->wait();
- }
-}
-
-QQmlDebugServerConnection *QQmlDebugServerPrivate::loadConnectionPlugin(
- const QString &pluginName)
-{
-#ifndef QT_NO_LIBRARY
- QStringList pluginCandidates;
- const QStringList paths = QCoreApplication::libraryPaths();
- foreach (const QString &libPath, paths) {
- const QDir dir(libPath + QLatin1String("/qmltooling"));
- if (dir.exists()) {
- QStringList plugins(dir.entryList(QDir::Files));
- foreach (const QString &pluginPath, plugins) {
- if (QFileInfo(pluginPath).fileName().contains(pluginName))
- pluginCandidates << dir.absoluteFilePath(pluginPath);
- }
- }
- }
-
- QQmlDebugServerConnection *loadedConnection = 0;
- foreach (const QString &pluginPath, pluginCandidates) {
- if (qmlDebugVerbose())
- qDebug() << "QML Debugger: Trying to load plugin " << pluginPath << "...";
-
- loader.setFileName(pluginPath);
- if (!loader.load()) {
- if (qmlDebugVerbose())
- qDebug() << "QML Debugger: Error while loading: " << loader.errorString();
- continue;
- }
- if (QObject *instance = loader.instance())
- loadedConnection = qobject_cast<QQmlDebugServerConnection*>(instance);
-
- if (loadedConnection) {
- if (qmlDebugVerbose())
- qDebug() << "QML Debugger: Plugin successfully loaded.";
-
- return loadedConnection;
- }
-
- if (qmlDebugVerbose())
- qDebug() << "QML Debugger: Plugin does not implement interface QQmlDebugServerConnection.";
-
- loader.unload();
- }
-#endif
- return 0;
-}
-
-void QQmlDebugServerThread::run()
-{
- QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
- Q_ASSERT_X(wrapper != 0, Q_FUNC_INFO, "There should always be a debug server available here.");
- QQmlDebugServer *server = &wrapper->m_instance;
-#if defined(QT_STATIC) && ! defined(QT_NO_QML_DEBUGGER)
- QQmlDebugServerConnection *connection
- = new QTcpServerConnection;
-#else
- QQmlDebugServerConnection *connection
- = server->d_func()->loadConnectionPlugin(m_pluginName);
-#endif
- if (connection) {
- connection->setServer(server);
- if (!connection->setPortRange(m_portFrom, m_portTo, m_block, m_hostAddress)) {
- delete connection;
- return;
- }
- server->d_func()->connection = connection;
- if (m_block)
- connection->waitForConnection();
- } else {
- qWarning() << "QML Debugger: Couldn't load plugin" << m_pluginName;
- return;
- }
-
- exec();
-
- // make sure events still waiting are processed
- QEventLoop eventLoop;
- eventLoop.processEvents(QEventLoop::AllEvents);
-}
-
-bool QQmlDebugServer::hasDebuggingClient() const
-{
- Q_D(const QQmlDebugServer);
- return d->connection
- && d->connection->isConnected()
- && d->gotHello;
-}
-
-bool QQmlDebugServer::hasThread() const
-{
- Q_D(const QQmlDebugServer);
- return d->thread != 0;
-}
-
-bool QQmlDebugServer::hasConnection() const
-{
- Q_D(const QQmlDebugServer);
- return d->connection != 0;
-}
-
-bool QQmlDebugServer::blockingMode() const
-{
- Q_D(const QQmlDebugServer);
- return d->blockingMode;
-}
-
-QQmlDebugServer *QQmlDebugServer::instance()
-{
- QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
- if (wrapper && wrapper->m_instance.d_func()->thread) {
- QQmlDebugServer *ret = &(wrapper->m_instance);
- QQmlDebugServerPrivate *d = ret->d_func();
- QMutexLocker locker(&d->helloMutex);
- if (d->blockingMode && !d->gotHello)
- d->helloCondition.wait(&d->helloMutex);
- return ret;
- } else {
- return 0;
- }
-}
-
-static void cleanupOnShutdown()
-{
- QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
- if (wrapper)
- wrapper->cleanup();
-}
-
-bool QQmlDebugServerPrivate::start(int portFrom, int portTo, bool block, const QString &hostAddress,
- const QString &pluginName)
-{
- if (!QQmlEnginePrivate::qml_debugging_enabled)
- return false;
- if (thread)
- return false;
- static bool postRoutineAdded = false;
- if (!postRoutineAdded) {
- qAddPostRoutine(cleanupOnShutdown);
- postRoutineAdded = true;
- }
- Q_Q(QQmlDebugServer);
- thread = new QQmlDebugServerThread;
- q->moveToThread(thread);
-
- // Remove the thread immmediately when it finishes, so that we don't have to wait for the event
- // loop to signal that.
- QObject::connect(thread, SIGNAL(finished()), q, SLOT(_q_removeThread()), Qt::DirectConnection);
-
- thread->setObjectName(QStringLiteral("QQmlDebugServerThread"));
- thread->setPluginName(pluginName);
- thread->setPortRange(portFrom, portTo == -1 ? portFrom : portTo, block, hostAddress);
- blockingMode = block;
- thread->start();
- return true;
-}
-
-QQmlDebugServer::QQmlDebugServer()
- : QObject(*(new QQmlDebugServerPrivate))
-{
- if (qApp == 0)
- return;
- QCoreApplicationPrivate *appD = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
-#ifndef QT_NO_QML_DEBUGGER
- // ### remove port definition when protocol is changed
- int portFrom = 0;
- int portTo = 0;
- bool block = false;
- bool ok = false;
- QString hostAddress;
-
- // format: qmljsdebugger=port:<port_from>[,port_to],host:<ip address>][,block]
- if (!appD->qmljsDebugArgumentsString().isEmpty()) {
- if (!QQmlEnginePrivate::qml_debugging_enabled) {
- qWarning() << QString(QLatin1String(
- "QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
- "Debugging has not been enabled.")).arg(
- appD->qmljsDebugArgumentsString());
- return;
- }
-
- QString pluginName;
- QStringList lstjsDebugArguments = appD->qmljsDebugArgumentsString()
- .split(QLatin1Char(','));
- QStringList::const_iterator argsItEnd = lstjsDebugArguments.end();
- QStringList::const_iterator argsIt = lstjsDebugArguments.begin();
- for (; argsIt != argsItEnd; ++argsIt) {
- const QString strArgument = *argsIt;
- if (strArgument.startsWith(QLatin1String("port:"))) {
- pluginName = QLatin1String("qmldbg_tcp");
- portFrom = strArgument.mid(5).toInt(&ok);
- portTo = portFrom;
- QStringList::const_iterator argsNext = argsIt + 1;
- if (argsNext == argsItEnd)
- break;
- const QString nextArgument = *argsNext;
- if (ok && nextArgument.contains(QRegExp(QStringLiteral("^\\s*\\d+\\s*$")))) {
- portTo = nextArgument.toInt(&ok);
- ++argsIt;
- }
- } else if (strArgument.startsWith(QLatin1String("host:"))) {
- hostAddress = strArgument.mid(5);
- } else if (strArgument == QLatin1String("block")) {
- block = true;
- } else {
- qWarning() << QString::fromLatin1("QML Debugger: Invalid argument '%1' "
- "detected. Ignoring the same.")
- .arg(strArgument);
- }
- }
-
- if (ok) {
- Q_D(QQmlDebugServer);
- d->start(portFrom, portTo, block, hostAddress, pluginName);
- } else {
- qWarning() << QString(QLatin1String(
- "QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
- "Format is qmljsdebugger=port:<port_from>[,port_to],host:"
- "<ip address>][,block]")).arg(appD->qmljsDebugArgumentsString());
- }
- }
-#else
- if (!appD->qmljsDebugArgumentsString().isEmpty()) {
- qWarning() << QString(QLatin1String(
- "QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
- "QtQml is not configured for debugging.")).arg(
- appD->qmljsDebugArgumentsString());
- }
-#endif
-}
-
-void QQmlDebugServer::receiveMessage(const QByteArray &message)
-{
- typedef QHash<QString, QQmlDebugService*>::const_iterator DebugServiceConstIt;
-
- // to be executed in debugger thread
- Q_ASSERT(QThread::currentThread() == thread());
-
- Q_D(QQmlDebugServer);
-
- QQmlDebugStream in(message);
-
- QString name;
-
- in >> name;
- if (name == QLatin1String("QDeclarativeDebugServer")) {
- int op = -1;
- in >> op;
- if (op == 0) {
- QWriteLocker lock(&d->pluginsLock);
- int version;
- in >> version >> d->clientPlugins;
-
- //Get the supported QDataStream version
- if (!in.atEnd()) {
- in >> s_dataStreamVersion;
- if (s_dataStreamVersion > QDataStream().version())
- s_dataStreamVersion = QDataStream().version();
- }
-
- // Send the hello answer immediately, since it needs to arrive before
- // the plugins below start sending messages.
-
- QByteArray helloAnswer;
- QQmlDebugStream out(&helloAnswer, QIODevice::WriteOnly);
- QStringList pluginNames;
- QList<float> pluginVersions;
- foreach (QQmlDebugService *service, d->plugins.values()) {
- pluginNames << service->name();
- pluginVersions << service->version();
- }
-
- out << QString(QStringLiteral("QDeclarativeDebugClient")) << 0 << protocolVersion
- << pluginNames << pluginVersions << s_dataStreamVersion;
-
- d->connection->send(QList<QByteArray>() << helloAnswer);
-
- QMutexLocker helloLock(&d->helloMutex);
- d->gotHello = true;
-
- for (DebugServiceConstIt iter = d->plugins.constBegin(), cend = d->plugins.constEnd(); iter != cend; ++iter) {
- QQmlDebugService::State newState = QQmlDebugService::Unavailable;
- if (d->clientPlugins.contains(iter.key()))
- newState = QQmlDebugService::Enabled;
- d->changeServiceStateCalls.ref();
- d->_q_changeServiceState(iter.value()->name(), newState);
- }
-
- d->helloCondition.wakeAll();
-
- } else if (op == 1) {
- QWriteLocker lock(&d->pluginsLock);
-
- // Service Discovery
- QStringList oldClientPlugins = d->clientPlugins;
- in >> d->clientPlugins;
-
- for (DebugServiceConstIt iter = d->plugins.constBegin(), cend = d->plugins.constEnd(); iter != cend; ++iter) {
- const QString pluginName = iter.key();
- QQmlDebugService::State newState = QQmlDebugService::Unavailable;
- if (d->clientPlugins.contains(pluginName))
- newState = QQmlDebugService::Enabled;
-
- if (oldClientPlugins.contains(pluginName)
- != d->clientPlugins.contains(pluginName)) {
- d->changeServiceStateCalls.ref();
- d->_q_changeServiceState(iter.value()->name(), newState);
- }
- }
-
- } else {
- qWarning("QML Debugger: Invalid control message %d.", op);
- d->connection->disconnect();
- return;
- }
-
- } else {
- if (d->gotHello) {
- QByteArray message;
- in >> message;
-
- QReadLocker lock(&d->pluginsLock);
- QHash<QString, QQmlDebugService *>::Iterator iter = d->plugins.find(name);
- if (iter == d->plugins.end()) {
- qWarning() << "QML Debugger: Message received for missing plugin" << name << '.';
- } else {
- (*iter)->messageReceived(message);
- }
- } else {
- qWarning("QML Debugger: Invalid hello message.");
- }
-
- }
-}
-
-void QQmlDebugServerPrivate::_q_changeServiceState(const QString &serviceName,
- QQmlDebugService::State newState)
-{
- // to be executed in debugger thread
- Q_ASSERT(QThread::currentThread() == q_func()->thread());
-
- QQmlDebugService *service = 0;
- {
- // Write lock here, because this can be called from receiveMessage which already has a write
- // lock. We cannot downgrade it. We also don't want to give up the write lock and later get
- // a read lock as that technique has great potential for deadlocks.
- QWriteLocker lock(&pluginsLock);
- service = plugins.value(serviceName);
- }
-
- if (service && (service->d_func()->state != newState)) {
- service->stateAboutToBeChanged(newState);
- service->d_func()->state = newState;
- service->stateChanged(newState);
- }
-
- changeServiceStateCalls.deref();
-}
-
-void QQmlDebugServerPrivate::_q_sendMessages(const QList<QByteArray> &messages)
-{
- // to be executed in debugger thread
- Q_ASSERT(QThread::currentThread() == q_func()->thread());
-
- if (connection)
- connection->send(messages);
-}
-
-void QQmlDebugServerPrivate::_q_removeThread()
-{
- Q_ASSERT(thread->isFinished());
- Q_ASSERT(QThread::currentThread() == thread);
-
- QThread *parentThread = thread->thread();
-
- // We cannot delete it right away as it will access its data after the finished() signal.
- thread->deleteLater();
- thread = 0;
-
- delete connection;
- connection = 0;
-
- // Move it back to the parent thread so that we can potentially restart it on a new thread.
- q_func()->moveToThread(parentThread);
-}
-
-QList<QQmlDebugService*> QQmlDebugServer::services() const
-{
- Q_D(const QQmlDebugServer);
- QReadLocker lock(&d->pluginsLock);
- return d->plugins.values();
-}
-
-QStringList QQmlDebugServer::serviceNames() const
-{
- Q_D(const QQmlDebugServer);
- QReadLocker lock(&d->pluginsLock);
- return d->plugins.keys();
-}
-
-void QQmlDebugServer::addEngine(QQmlEngine *engine)
-{
- Q_D(QQmlDebugServer);
- QWriteLocker lock(&d->pluginsLock);
-
- foreach (QQmlDebugService *service, d->plugins)
- service->engineAboutToBeAdded(engine);
-
- d->engineConditions[engine].waitForServices(&d->pluginsLock, d->plugins.count());
-
- foreach (QQmlDebugService *service, d->plugins)
- service->engineAdded(engine);
-}
-
-void QQmlDebugServer::removeEngine(QQmlEngine *engine)
-{
- Q_D(QQmlDebugServer);
- QWriteLocker lock(&d->pluginsLock);
-
- foreach (QQmlDebugService *service, d->plugins)
- service->engineAboutToBeRemoved(engine);
-
- d->engineConditions[engine].waitForServices(&d->pluginsLock, d->plugins.count());
-
- foreach (QQmlDebugService *service, d->plugins)
- service->engineRemoved(engine);
-}
-
-bool QQmlDebugServer::addService(QQmlDebugService *service)
-{
- Q_D(QQmlDebugServer);
-
- // to be executed outside of debugger thread
- Q_ASSERT(QThread::currentThread() != thread());
-
- connect(service, SIGNAL(attachedToEngine(QQmlEngine*)),
- this, SLOT(wakeEngine(QQmlEngine*)), Qt::QueuedConnection);
- connect(service, SIGNAL(detachedFromEngine(QQmlEngine*)),
- this, SLOT(wakeEngine(QQmlEngine*)), Qt::QueuedConnection);
-
-
- QWriteLocker lock(&d->pluginsLock);
- if (!service || d->plugins.contains(service->name()))
- return false;
- d->plugins.insert(service->name(), service);
- d->advertisePlugins();
- QQmlDebugService::State newState = QQmlDebugService::Unavailable;
- if (d->clientPlugins.contains(service->name()))
- newState = QQmlDebugService::Enabled;
- service->d_func()->state = newState;
- return true;
-}
-
-bool QQmlDebugServer::removeService(QQmlDebugService *service)
-{
- Q_D(QQmlDebugServer);
-
- // to be executed outside of debugger thread
- Q_ASSERT(QThread::currentThread() != thread());
-
- QWriteLocker lock(&d->pluginsLock);
- QQmlDebugService::State newState = QQmlDebugService::NotConnected;
-
- d->changeServiceStateCalls.ref();
- QMetaObject::invokeMethod(this, "_q_changeServiceState", Qt::QueuedConnection,
- Q_ARG(QString, service->name()),
- Q_ARG(QQmlDebugService::State, newState));
-
- if (!service || !d->plugins.contains(service->name()))
- return false;
- d->plugins.remove(service->name());
-
- d->advertisePlugins();
-
- return true;
-}
-
-void QQmlDebugServer::sendMessages(QQmlDebugService *service,
- const QList<QByteArray> &messages)
-{
- QList<QByteArray> prefixedMessages;
- foreach (const QByteArray &message, messages) {
- QByteArray prefixed;
- QQmlDebugStream out(&prefixed, QIODevice::WriteOnly);
- out << service->name() << message;
- prefixedMessages << prefixed;
- }
-
- QMetaObject::invokeMethod(this, "_q_sendMessages", Qt::QueuedConnection,
- Q_ARG(QList<QByteArray>, prefixedMessages));
-}
-
-bool QQmlDebugServer::enable(int portFrom, int portTo, bool block, const QString &hostAddress)
-{
-#ifndef QT_NO_QML_DEBUGGER
- QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
- if (!wrapper)
- return false;
- QQmlDebugServerPrivate *d = wrapper->m_instance.d_func();
- if (d->thread)
- return false;
- if (!d->start(portFrom, portTo, block, hostAddress, QLatin1String("qmldbg_tcp")))
- return false;
- while (!wrapper->m_instance.hasConnection()) {
- if (!wrapper->m_instance.hasThread())
- return false;
- }
- return true;
-#else
- Q_UNUSED(portFrom);
- Q_UNUSED(portTo);
- Q_UNUSED(block);
- Q_UNUSED(hostAddress);
- return false;
-#endif
-}
-
-void QQmlDebugServer::wakeEngine(QQmlEngine *engine)
-{
- // to be executed in debugger thread
- Q_ASSERT(QThread::currentThread() == thread());
-
- Q_D(QQmlDebugServer);
- QWriteLocker lock(&d->pluginsLock);
- d->engineConditions[engine].wake();
-}
-
-bool QQmlDebugServerPrivate::EngineCondition::waitForServices(QReadWriteLock *locked, int num)
-{
- // to be executed outside of debugger thread
- Q_ASSERT(QThread::currentThread() != QQmlDebugServer::instance()->thread());
-
- Q_ASSERT_X(numServices == 0, Q_FUNC_INFO, "Request to wait again before previous wait finished");
- numServices = num;
- return condition->wait(locked);
-}
-
-void QQmlDebugServerPrivate::EngineCondition::wake()
-{
- if (--numServices == 0)
- condition->wakeAll();
- Q_ASSERT_X(numServices >=0, Q_FUNC_INFO, "Woken more often than #services.");
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qqmldebugserver_p.cpp"
diff --git a/src/qml/debugger/qqmldebugserver_p.h b/src/qml/debugger/qqmldebugserver_p.h
deleted file mode 100644
index b2bd0b2463..0000000000
--- a/src/qml/debugger/qqmldebugserver_p.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLDEBUGSERVER_H
-#define QQMLDEBUGSERVER_H
-
-#include <QtQml/qtqmlglobal.h>
-#include <private/qqmldebugserverconnection_p.h>
-#include <private/qqmldebugservice_p.h>
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-QT_BEGIN_NAMESPACE
-
-
-class QQmlDebugServerPrivate;
-class Q_QML_PRIVATE_EXPORT QQmlDebugServer : public QObject
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQmlDebugServer)
- Q_DISABLE_COPY(QQmlDebugServer)
-public:
-
- static QQmlDebugServer *instance();
-
- bool hasThread() const;
- bool hasConnection() const;
- bool hasDebuggingClient() const;
- bool blockingMode() const;
-
- QList<QQmlDebugService*> services() const;
- QStringList serviceNames() const;
-
- void addEngine(QQmlEngine *engine);
- void removeEngine(QQmlEngine *engine);
-
- bool addService(QQmlDebugService *service);
- bool removeService(QQmlDebugService *service);
-
- void receiveMessage(const QByteArray &message);
-
- void sendMessages(QQmlDebugService *service, const QList<QByteArray> &messages);
- static bool enable(int portFrom, int portTo, bool block, const QString &hostAddress);
-
-private slots:
- void wakeEngine(QQmlEngine *engine);
-
-private:
- friend class QQmlDebugService;
- friend class QQmlDebugServicePrivate;
- friend class QQmlDebugServerThread;
- friend struct QQmlDebugServerInstanceWrapper;
- QQmlDebugServer();
- Q_PRIVATE_SLOT(d_func(), void _q_changeServiceState(const QString &serviceName,
- QQmlDebugService::State state))
- Q_PRIVATE_SLOT(d_func(), void _q_sendMessages(QList<QByteArray>))
- Q_PRIVATE_SLOT(d_func(), void _q_removeThread())
-
-public:
- static int s_dataStreamVersion;
-};
-
-QT_END_NAMESPACE
-
-#endif // QQMLDEBUGSERVICE_H
diff --git a/src/qml/debugger/qqmldebugservice.cpp b/src/qml/debugger/qqmldebugservice.cpp
index b37a7335a0..0b07f320ec 100644
--- a/src/qml/debugger/qqmldebugservice.cpp
+++ b/src/qml/debugger/qqmldebugservice.cpp
@@ -32,8 +32,7 @@
****************************************************************************/
#include "qqmldebugservice_p.h"
-#include "qqmldebugservice_p_p.h"
-#include "qqmldebugserver_p.h"
+#include "qqmldebugconnector_p.h"
#include <private/qqmldata_p.h>
#include <private/qqmlcontext_p.h>
@@ -43,58 +42,55 @@
QT_BEGIN_NAMESPACE
-QQmlDebugServicePrivate::QQmlDebugServicePrivate()
-{
-}
+class QQmlDebugServer;
-QQmlDebugService::QQmlDebugService(const QString &name, float version, QObject *parent)
- : QObject(*(new QQmlDebugServicePrivate), parent)
+class QQmlDebugServicePrivate : public QObjectPrivate
{
- QQmlDebugServer::instance(); // create it when it isn't there yet.
+ Q_DECLARE_PUBLIC(QQmlDebugService)
+public:
+ QQmlDebugServicePrivate(const QString &name, float version);
- Q_D(QQmlDebugService);
- d->name = name;
- d->version = version;
- d->state = QQmlDebugService::NotConnected;
-}
+ const QString name;
+ const float version;
+ QQmlDebugService::State state;
+};
-QQmlDebugService::QQmlDebugService(QQmlDebugServicePrivate &dd,
- const QString &name, float version, QObject *parent)
- : QObject(dd, parent)
+QQmlDebugServicePrivate::QQmlDebugServicePrivate(const QString &name, float version) :
+ name(name), version(version), state(QQmlDebugService::NotConnected)
{
- Q_D(QQmlDebugService);
- d->name = name;
- d->version = version;
- d->state = QQmlDebugService::NotConnected;
}
-/**
- Registers the service. This should be called in the constructor of the inherited class. From
- then on the service might get asynchronous calls to messageReceived().
- */
-QQmlDebugService::State QQmlDebugService::registerService()
+QQmlDebugService::QQmlDebugService(const QString &name, float version, QObject *parent)
+ : QObject(*(new QQmlDebugServicePrivate(name, version)), parent)
{
Q_D(QQmlDebugService);
- QQmlDebugServer *server = QQmlDebugServer::instance();
+ QQmlDebugConnector *server = QQmlDebugConnector::instance();
if (!server)
- return NotConnected;
+ return;
- if (server->serviceNames().contains(d->name)) {
+ if (server->service(d->name)) {
qWarning() << "QQmlDebugService: Conflicting plugin name" << d->name;
} else {
- server->addService(this);
+ server->addService(d->name, this);
}
- return state();
}
QQmlDebugService::~QQmlDebugService()
{
- if (QQmlDebugServer *inst = QQmlDebugServer::instance())
- inst->removeService(this);
+ Q_D(QQmlDebugService);
+ QQmlDebugConnector *server = QQmlDebugConnector::instance();
+
+ if (!server)
+ return;
+
+ if (server->service(d->name) != this)
+ qWarning() << "QQmlDebugService: Plugin" << d->name << "is not registered.";
+ else
+ server->removeService(d->name);
}
-QString QQmlDebugService::name() const
+const QString &QQmlDebugService::name() const
{
Q_D(const QQmlDebugService);
return d->name;
@@ -112,27 +108,38 @@ QQmlDebugService::State QQmlDebugService::state() const
return d->state;
}
-namespace {
-
-struct ObjectReference
+void QQmlDebugService::setState(QQmlDebugService::State newState)
{
- QPointer<QObject> object;
- int id;
-};
+ Q_D(QQmlDebugService);
+ d->state = newState;
+}
-struct ObjectReferenceHash
+namespace {
+class ObjectReferenceHash : public QObject
{
+ Q_OBJECT
+public:
ObjectReferenceHash() : nextId(0) {}
- QHash<QObject *, ObjectReference> objects;
+ QHash<QObject *, int> objects;
QHash<int, QObject *> ids;
int nextId;
-};
+private slots:
+ void remove(QObject *obj);
+};
}
Q_GLOBAL_STATIC(ObjectReferenceHash, objectReferenceHash)
+void ObjectReferenceHash::remove(QObject *obj)
+{
+ QHash<QObject *, int>::Iterator iter = objects.find(obj);
+ if (iter != objects.end()) {
+ ids.remove(iter.value());
+ objects.erase(iter);
+ }
+}
/*!
Returns a unique id for \a object. Calling this method multiple times
@@ -144,158 +151,23 @@ int QQmlDebugService::idForObject(QObject *object)
return -1;
ObjectReferenceHash *hash = objectReferenceHash();
- QHash<QObject *, ObjectReference>::Iterator iter =
- hash->objects.find(object);
+ QHash<QObject *, int>::Iterator iter = hash->objects.find(object);
if (iter == hash->objects.end()) {
int id = hash->nextId++;
-
- hash->ids.insert(id, object);
- iter = hash->objects.insert(object, ObjectReference());
- iter->object = object;
- iter->id = id;
- } else if (iter->object != object) {
- int id = hash->nextId++;
-
- hash->ids.remove(iter->id);
-
hash->ids.insert(id, object);
- iter->object = object;
- iter->id = id;
- }
- return iter->id;
-}
-
-/*!
- Returns the object for unique \a id. If the object has not previously been
- assigned an id, through idForObject(), then 0 is returned. If the object
- has been destroyed, 0 is returned.
-*/
-QObject *QQmlDebugService::objectForId(int id)
-{
- ObjectReferenceHash *hash = objectReferenceHash();
-
- QHash<int, QObject *>::Iterator iter = hash->ids.find(id);
- if (iter == hash->ids.end())
- return 0;
-
-
- QHash<QObject *, ObjectReference>::Iterator objIter =
- hash->objects.find(*iter);
- Q_ASSERT(objIter != hash->objects.end());
-
- if (objIter->object == 0) {
- hash->ids.erase(iter);
- hash->objects.erase(objIter);
- // run a loop to remove other invalid objects
- removeInvalidObjectsFromHash();
- return 0;
- } else {
- return *iter;
+ iter = hash->objects.insert(object, id);
+ connect(object, SIGNAL(destroyed(QObject*)), hash, SLOT(remove(QObject*)));
}
+ return iter.value();
}
/*!
- Returns a list of objects matching the given filename, line and column.
+ Returns the mapping of objects to unique \a ids, created through calls to idForObject().
*/
-QList<QObject*> QQmlDebugService::objectForLocationInfo(const QString &filename,
- int lineNumber, int columnNumber)
-{
- ObjectReferenceHash *hash = objectReferenceHash();
- QList<QObject*> objects;
- QHash<int, QObject *>::Iterator iter = hash->ids.begin();
- while (iter != hash->ids.end()) {
- QHash<QObject *, ObjectReference>::Iterator objIter =
- hash->objects.find(*iter);
- Q_ASSERT(objIter != hash->objects.end());
-
- if (objIter->object == 0) {
- iter = hash->ids.erase(iter);
- hash->objects.erase(objIter);
- } else {
- QQmlData *ddata = QQmlData::get(iter.value());
- if (ddata && ddata->outerContext) {
- if (QFileInfo(ddata->outerContext->urlString()).fileName() == filename &&
- ddata->lineNumber == lineNumber &&
- ddata->columnNumber >= columnNumber) {
- objects << *iter;
- }
- }
- ++iter;
- }
- }
- return objects;
-}
-
-void QQmlDebugService::removeInvalidObjectsFromHash()
-{
- ObjectReferenceHash *hash = objectReferenceHash();
- QHash<int, QObject *>::Iterator iter = hash->ids.begin();
- while (iter != hash->ids.end()) {
- QHash<QObject *, ObjectReference>::Iterator objIter =
- hash->objects.find(*iter);
- Q_ASSERT(objIter != hash->objects.end());
-
- if (objIter->object == 0) {
- iter = hash->ids.erase(iter);
- hash->objects.erase(objIter);
- } else {
- ++iter;
- }
- }
-}
-
-void QQmlDebugService::clearObjectsFromHash()
-{
- ObjectReferenceHash *hash = objectReferenceHash();
- hash->ids.clear();
- hash->objects.clear();
-}
-
-bool QQmlDebugService::isDebuggingEnabled()
-{
- return QQmlDebugServer::instance() != 0;
-}
-
-bool QQmlDebugService::hasDebuggingClient()
+const QHash<int, QObject *> &QQmlDebugService::objectsForIds()
{
- return QQmlDebugServer::instance() != 0
- && QQmlDebugServer::instance()->hasDebuggingClient();
-}
-
-bool QQmlDebugService::blockingMode()
-{
- return QQmlDebugServer::instance() != 0
- && QQmlDebugServer::instance()->blockingMode();
-}
-
-QString QQmlDebugService::objectToString(QObject *obj)
-{
- if(!obj)
- return QStringLiteral("NULL");
-
- QString objectName = obj->objectName();
- if(objectName.isEmpty())
- objectName = QStringLiteral("<unnamed>");
-
- QString rv = QString::fromUtf8(obj->metaObject()->className()) +
- QLatin1String(": ") + objectName;
-
- return rv;
-}
-
-void QQmlDebugService::sendMessage(const QByteArray &message)
-{
- sendMessages(QList<QByteArray>() << message);
-}
-
-void QQmlDebugService::sendMessages(const QList<QByteArray> &messages)
-{
- if (state() != Enabled)
- return;
-
- if (QQmlDebugServer *inst = QQmlDebugServer::instance())
- inst->sendMessages(this, messages);
+ return objectReferenceHash()->ids;
}
void QQmlDebugService::stateAboutToBeChanged(State)
@@ -328,28 +200,32 @@ void QQmlDebugService::engineRemoved(QQmlEngine *)
{
}
+int QQmlDebugStream::s_dataStreamVersion = QDataStream::Qt_4_7;
+
QQmlDebugStream::QQmlDebugStream()
: QDataStream()
{
- setVersion(QQmlDebugServer::s_dataStreamVersion);
+ setVersion(s_dataStreamVersion);
}
QQmlDebugStream::QQmlDebugStream(QIODevice *d)
: QDataStream(d)
{
- setVersion(QQmlDebugServer::s_dataStreamVersion);
+ setVersion(s_dataStreamVersion);
}
QQmlDebugStream::QQmlDebugStream(QByteArray *ba, QIODevice::OpenMode flags)
: QDataStream(ba, flags)
{
- setVersion(QQmlDebugServer::s_dataStreamVersion);
+ setVersion(s_dataStreamVersion);
}
QQmlDebugStream::QQmlDebugStream(const QByteArray &ba)
: QDataStream(ba)
{
- setVersion(QQmlDebugServer::s_dataStreamVersion);
+ setVersion(s_dataStreamVersion);
}
QT_END_NAMESPACE
+
+#include "qqmldebugservice.moc"
diff --git a/src/qml/debugger/qqmldebugservice_p.h b/src/qml/debugger/qqmldebugservice_p.h
index 9cdfc34ff1..3d692133cc 100644
--- a/src/qml/debugger/qqmldebugservice_p.h
+++ b/src/qml/debugger/qqmldebugservice_p.h
@@ -35,7 +35,8 @@
#define QQMLDEBUGSERVICE_H
#include <QtCore/qobject.h>
-#include <QtCore/QDataStream>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qhash.h>
#include <private/qtqmlglobal_p.h>
@@ -62,35 +63,14 @@ class Q_QML_PRIVATE_EXPORT QQmlDebugService : public QObject
Q_DISABLE_COPY(QQmlDebugService)
public:
- explicit QQmlDebugService(const QString &, float version, QObject *parent = 0);
~QQmlDebugService();
- QString name() const;
+ const QString &name() const;
float version() const;
enum State { NotConnected, Unavailable, Enabled };
State state() const;
-
- void sendMessage(const QByteArray &);
- void sendMessages(const QList<QByteArray> &);
-
- static int idForObject(QObject *);
- static QObject *objectForId(int);
- static QList<QObject*> objectForLocationInfo(const QString &filename,
- int lineNumber, int columnNumber);
- static void removeInvalidObjectsFromHash();
- static void clearObjectsFromHash();
-
- static QString objectToString(QObject *obj);
-
- static bool isDebuggingEnabled();
- static bool hasDebuggingClient();
- static bool blockingMode();
-
-protected:
- QQmlDebugService(QQmlDebugServicePrivate &dd, const QString &name, float version, QObject *parent = 0);
-
- State registerService();
+ void setState(State newState);
virtual void stateAboutToBeChanged(State);
virtual void stateChanged(State);
@@ -101,18 +81,26 @@ protected:
virtual void engineAdded(QQmlEngine *);
virtual void engineRemoved(QQmlEngine *);
+ static const QHash<int, QObject *> &objectsForIds();
+ static int idForObject(QObject *);
+ static QObject *objectForId(int id) { return objectsForIds().value(id); }
+
+protected:
+ explicit QQmlDebugService(const QString &, float version, QObject *parent = 0);
+
signals:
void attachedToEngine(QQmlEngine *);
void detachedFromEngine(QQmlEngine *);
-private:
- friend class QQmlDebugServer;
- friend class QQmlDebugServerPrivate;
+ void messageToClient(const QString &name, const QByteArray &message);
+ void messagesToClient(const QString &name, const QList<QByteArray> &messages);
};
class Q_QML_PRIVATE_EXPORT QQmlDebugStream : public QDataStream
{
public:
+ static int s_dataStreamVersion;
+
QQmlDebugStream();
explicit QQmlDebugStream(QIODevice *d);
QQmlDebugStream(QByteArray *ba, QIODevice::OpenMode flags);
diff --git a/src/qml/debugger/qqmldebugservice_p_p.h b/src/qml/debugger/qqmldebugservicefactory_p.h
index 7d60739f3a..af50cd4635 100644
--- a/src/qml/debugger/qqmldebugservice_p_p.h
+++ b/src/qml/debugger/qqmldebugservicefactory_p.h
@@ -31,8 +31,8 @@
**
****************************************************************************/
-#ifndef QQMLDEBUGSERVICE_P_H
-#define QQMLDEBUGSERVICE_P_H
+#ifndef QQMLDEBUGSERVICEFACTORY_P_H
+#define QQMLDEBUGSERVICEFACTORY_P_H
//
// W A R N I N G
@@ -45,25 +45,19 @@
// We mean it.
//
-#include <QtCore/qglobal.h>
-#include <private/qobject_p.h>
+#include "qqmldebugservice_p.h"
QT_BEGIN_NAMESPACE
-
-class QQmlDebugServer;
-
-class QQmlDebugServicePrivate : public QObjectPrivate
+class Q_QML_PRIVATE_EXPORT QQmlDebugServiceFactory : public QObject
{
- Q_DECLARE_PUBLIC(QQmlDebugService)
+ Q_OBJECT
public:
- QQmlDebugServicePrivate();
-
- QString name;
- float version;
- QQmlDebugService::State state;
+ virtual QQmlDebugService *create(const QString &key) = 0;
};
+#define QQmlDebugServiceFactory_iid "org.qt-project.Qt.QQmlDebugServiceFactory"
+
QT_END_NAMESPACE
-#endif // QQMLDEBUGSERVICE_P_H
+#endif // QQMLDEBUGSERVICEFACTORY_P_H
diff --git a/src/qml/debugger/qqmldebugserviceinterfaces.cpp b/src/qml/debugger/qqmldebugserviceinterfaces.cpp
new file mode 100644
index 0000000000..199c682748
--- /dev/null
+++ b/src/qml/debugger/qqmldebugserviceinterfaces.cpp
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmldebugserviceinterfaces_p.h"
+
+QT_BEGIN_NAMESPACE
+
+const QString QV4DebugService::s_key = QStringLiteral("V8Debugger");
+const QString QQmlEngineDebugService::s_key = QStringLiteral("QmlDebugger");
+const QString QQmlInspectorService::s_key = QStringLiteral("QmlInspector");
+const QString QQmlProfilerService::s_key = QStringLiteral("CanvasFrameRate");
+const QString QQmlNativeDebugService::s_key = QStringLiteral("NativeQmlDebugger");
+
+QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmldebugserviceinterfaces_p.h b/src/qml/debugger/qqmldebugserviceinterfaces_p.h
new file mode 100644
index 0000000000..6391bc6218
--- /dev/null
+++ b/src/qml/debugger/qqmldebugserviceinterfaces_p.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLDEBUGSERVICEINTERFACES_P_H
+#define QQMLDEBUGSERVICEINTERFACES_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qstring.h>
+#include <private/qtqmlglobal_p.h>
+#include <private/qqmldebugservice_p.h>
+#include <private/qqmldebugstatesdelegate_p.h>
+#include <private/qqmlabstractprofileradapter_p.h>
+#include <private/qqmlboundsignal_p.h>
+
+#include <limits>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QML_PRIVATE_EXPORT QV4DebugService : protected QQmlDebugService
+{
+ Q_OBJECT
+public:
+ virtual void signalEmitted(const QString &signal) = 0;
+
+protected:
+ friend class QQmlDebugConnector;
+
+ QV4DebugService(float version, QObject *parent = 0) :
+ QQmlDebugService(s_key, version, parent) {}
+
+ static const QString s_key;
+};
+
+class Q_QML_PRIVATE_EXPORT QQmlProfilerService : protected QQmlDebugService
+{
+ Q_OBJECT
+public:
+ virtual void addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler) = 0;
+ virtual void removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler) = 0;
+
+ virtual void startProfiling(QQmlEngine *engine,
+ quint64 features = std::numeric_limits<quint64>::max()) = 0;
+ virtual void stopProfiling(QQmlEngine *engine) = 0;
+
+ virtual void dataReady(QQmlAbstractProfilerAdapter *profiler) = 0;
+
+protected:
+ friend class QQmlDebugConnector;
+
+ QQmlProfilerService(float version, QObject *parent = 0) :
+ QQmlDebugService(s_key, version, parent) {}
+
+ static const QString s_key;
+};
+
+class Q_QML_PRIVATE_EXPORT QQmlEngineDebugService : protected QQmlDebugService
+{
+ Q_OBJECT
+public:
+ virtual void objectCreated(QQmlEngine *engine, QObject *object) = 0;
+ virtual void setStatesDelegate(QQmlDebugStatesDelegate *) = 0;
+
+protected:
+ friend class QQmlDebugConnector;
+
+ QQmlEngineDebugService(float version, QObject *parent = 0) :
+ QQmlDebugService(s_key, version, parent) {}
+
+ QQmlBoundSignal *nextSignal(QQmlBoundSignal *prev) { return prev->m_nextSignal; }
+
+ static const QString s_key;
+};
+
+class Q_QML_PRIVATE_EXPORT QQmlInspectorService : protected QQmlDebugService
+{
+ Q_OBJECT
+public:
+ virtual void addView(QObject *) = 0;
+ virtual void removeView(QObject *) = 0;
+
+protected:
+ friend class QQmlDebugConnector;
+
+ QQmlInspectorService(float version, QObject *parent = 0) :
+ QQmlDebugService(s_key, version, parent) {}
+
+ static const QString s_key;
+};
+
+class Q_QML_PRIVATE_EXPORT QQmlNativeDebugService : protected QQmlDebugService
+{
+ Q_OBJECT
+
+protected:
+ friend class QQmlDebugConnector;
+
+ QQmlNativeDebugService(float version, QObject *parent = 0)
+ : QQmlDebugService(s_key, version, parent) {}
+
+ static const QString s_key;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLDEBUGSERVICEINTERFACES_P_H
+
diff --git a/src/qml/debugger/qqmlinspectorservice.cpp b/src/qml/debugger/qqmlinspectorservice.cpp
deleted file mode 100644
index 5a8c4487d9..0000000000
--- a/src/qml/debugger/qqmlinspectorservice.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlinspectorservice_p.h"
-#include "qqmlinspectorinterface_p.h"
-#include "qqmldebugserver_p.h"
-
-#include <private/qqmlglobal_p.h>
-
-#include <QtCore/QCoreApplication>
-#include <QtCore/QDebug>
-#include <QtCore/QDir>
-#include <QtCore/QPluginLoader>
-
-// print detailed information about loading of plugins
-DEFINE_BOOL_CONFIG_OPTION(qmlDebugVerbose, QML_DEBUGGER_VERBOSE)
-
-QT_BEGIN_NAMESPACE
-
-Q_GLOBAL_STATIC(QQmlInspectorService, serviceInstance)
-
-QQmlInspectorService::QQmlInspectorService()
- : QQmlDebugService(QStringLiteral("QmlInspector"), 1)
- , m_currentInspectorPlugin(0)
-{
- registerService();
-}
-
-QQmlInspectorService *QQmlInspectorService::instance()
-{
- return serviceInstance();
-}
-
-void QQmlInspectorService::addView(QObject *view)
-{
- m_views.append(view);
- updateState();
-}
-
-void QQmlInspectorService::removeView(QObject *view)
-{
- m_views.removeAll(view);
- updateState();
-}
-
-void QQmlInspectorService::sendMessage(const QByteArray &message)
-{
- if (state() != Enabled)
- return;
-
- QQmlDebugService::sendMessage(message);
-}
-
-void QQmlInspectorService::stateChanged(State /*state*/)
-{
- QMetaObject::invokeMethod(this, "updateState", Qt::QueuedConnection);
-}
-
-void QQmlInspectorService::updateState()
-{
- if (m_views.isEmpty()) {
- if (m_currentInspectorPlugin) {
- m_currentInspectorPlugin->deactivate();
- m_currentInspectorPlugin = 0;
- }
- return;
- }
-
- if (state() == Enabled) {
- if (m_inspectorPlugins.isEmpty())
- loadInspectorPlugins();
-
- if (m_inspectorPlugins.isEmpty()) {
- qWarning() << "QQmlInspector: No plugins found.";
- QQmlDebugServer::instance()->removeService(this);
- return;
- }
-
- m_currentInspectorPlugin = 0;
- foreach (QQmlInspectorInterface *inspector, m_inspectorPlugins) {
- if (inspector->canHandleView(m_views.first())) {
- m_currentInspectorPlugin = inspector;
- break;
- }
- }
-
- if (!m_currentInspectorPlugin) {
- qWarning() << "QQmlInspector: No plugin available for view '" << m_views.first()->metaObject()->className() << "'.";
- return;
- }
- m_currentInspectorPlugin->activate(m_views.first());
- } else {
- if (m_currentInspectorPlugin) {
- m_currentInspectorPlugin->deactivate();
- m_currentInspectorPlugin = 0;
- }
- }
-}
-
-void QQmlInspectorService::messageReceived(const QByteArray &message)
-{
- QMetaObject::invokeMethod(this, "processMessage", Qt::QueuedConnection, Q_ARG(QByteArray, message));
-}
-
-void QQmlInspectorService::processMessage(const QByteArray &message)
-{
- if (m_currentInspectorPlugin)
- m_currentInspectorPlugin->clientMessage(message);
-}
-
-void QQmlInspectorService::loadInspectorPlugins()
-{
- QStringList pluginCandidates;
- const QStringList paths = QCoreApplication::libraryPaths();
- foreach (const QString &libPath, paths) {
- const QDir dir(libPath + QLatin1String("/qmltooling"));
- if (dir.exists())
- foreach (const QString &pluginPath, dir.entryList(QDir::Files))
- pluginCandidates << dir.absoluteFilePath(pluginPath);
- }
-
- foreach (const QString &pluginPath, pluginCandidates) {
- if (pluginPath.contains(QLatin1String("qmldbg_tcp")))
- continue;
- if (qmlDebugVerbose())
- qDebug() << "QQmlInspector: Trying to load plugin " << pluginPath << "...";
-
- QPluginLoader loader(pluginPath);
- if (!loader.load()) {
- if (qmlDebugVerbose())
- qDebug() << "QQmlInspector: Error while loading: " << loader.errorString();
-
- continue;
- }
-
- QQmlInspectorInterface *inspector =
- qobject_cast<QQmlInspectorInterface*>(loader.instance());
- if (inspector) {
- if (qmlDebugVerbose())
- qDebug() << "QQmlInspector: Plugin successfully loaded.";
- m_inspectorPlugins << inspector;
- } else {
- if (qmlDebugVerbose())
- qDebug() << "QQmlInspector: Plugin does not implement interface QQmlInspectorInterface.";
-
- loader.unload();
- }
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlprofiler.cpp b/src/qml/debugger/qqmlprofiler.cpp
index b35da8a714..a6423d769a 100644
--- a/src/qml/debugger/qqmlprofiler.cpp
+++ b/src/qml/debugger/qqmlprofiler.cpp
@@ -32,88 +32,13 @@
****************************************************************************/
#include "qqmlprofiler_p.h"
-#include "qqmlprofilerservice_p.h"
#include "qqmldebugservice_p.h"
QT_BEGIN_NAMESPACE
-// convert to QByteArrays that can be sent to the debug client
-// use of QDataStream can skew results
-// (see tst_qqmldebugtrace::trace() benchmark)
-void QQmlProfilerData::toByteArrays(QList<QByteArray> &messages) const
-{
- QByteArray data;
- Q_ASSERT_X(((messageType | detailType) & (1 << 31)) == 0, Q_FUNC_INFO, "You can use at most 31 message types and 31 detail types.");
- for (uint decodedMessageType = 0; (messageType >> decodedMessageType) != 0; ++decodedMessageType) {
- if ((messageType & (1 << decodedMessageType)) == 0)
- continue;
-
- for (uint decodedDetailType = 0; (detailType >> decodedDetailType) != 0; ++decodedDetailType) {
- if ((detailType & (1 << decodedDetailType)) == 0)
- continue;
-
- //### using QDataStream is relatively expensive
- QQmlDebugStream ds(&data, QIODevice::WriteOnly);
- ds << time << decodedMessageType << decodedDetailType;
-
- switch (decodedMessageType) {
- case QQmlProfilerDefinitions::RangeStart:
- if (decodedDetailType == (int)QQmlProfilerDefinitions::Binding)
- ds << QQmlProfilerDefinitions::QmlBinding;
- break;
- case QQmlProfilerDefinitions::RangeData:
- ds << detailString;
- break;
- case QQmlProfilerDefinitions::RangeLocation:
- ds << (detailUrl.isEmpty() ? detailString : detailUrl.toString()) << x << y;
- break;
- case QQmlProfilerDefinitions::RangeEnd: break;
- default:
- Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
- break;
- }
- messages << data;
- data.clear();
- }
- }
-}
-
-QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine) :
- QQmlAbstractProfilerAdapter(service)
-{
- engine->enableProfiler();
- connect(this, SIGNAL(profilingEnabled(quint64)), engine->profiler, SLOT(startProfiling(quint64)));
- connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
- engine->profiler, SLOT(startProfiling(quint64)), Qt::DirectConnection);
- connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
- connect(this, SIGNAL(profilingDisabledWhileWaiting()),
- engine->profiler, SLOT(stopProfiling()), Qt::DirectConnection);
- connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
- connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
- engine->profiler, SLOT(setTimer(QElapsedTimer)));
- connect(engine->profiler, SIGNAL(dataReady(QList<QQmlProfilerData>)),
- this, SLOT(receiveData(QList<QQmlProfilerData>)));
-}
-
-qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
-{
- while (!data.empty() && data.front().time <= until) {
- data.front().toByteArrays(messages);
- data.pop_front();
- }
- return data.empty() ? -1 : data.front().time;
-}
-
-void QQmlProfilerAdapter::receiveData(const QList<QQmlProfilerData> &new_data)
-{
- data = new_data;
- service->dataReady(this);
-}
-
-
QQmlProfiler::QQmlProfiler() : featuresEnabled(0)
{
- static int metatype = qRegisterMetaType<QList<QQmlProfilerData> >();
+ static int metatype = qRegisterMetaType<QVector<QQmlProfilerData> >();
Q_UNUSED(metatype);
m_timer.start();
}
@@ -127,16 +52,12 @@ void QQmlProfiler::stopProfiling()
{
featuresEnabled = false;
reportData();
- m_data.clear();
}
void QQmlProfiler::reportData()
{
- QList<QQmlProfilerData> result;
- result.reserve(m_data.size());
- for (int i = 0; i < m_data.size(); ++i)
- result.append(m_data[i]);
- emit dataReady(result);
+ emit dataReady(m_data);
+ m_data.clear();
}
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
index 5c994b112f..7e29c3ede6 100644
--- a/src/qml/debugger/qqmlprofiler_p.h
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -68,8 +68,9 @@ QT_BEGIN_NAMESPACE
// This struct is somewhat dangerous to use:
// The messageType is a bit field. You can pack multiple messages into
// one object, e.g. RangeStart and RangeLocation. Each one will be read
-// independently by toByteArrays. Thus you can only pack messages if their data
-// doesn't overlap. It's up to you to figure that out.
+// independently when converting to QByteArrays. Thus you can only pack
+// messages if their data doesn't overlap. It's up to you to figure that
+// out.
struct Q_AUTOTEST_EXPORT QQmlProfilerData
{
QQmlProfilerData() {}
@@ -98,13 +99,12 @@ struct Q_AUTOTEST_EXPORT QQmlProfilerData
int messageType; //bit field of QQmlProfilerService::Message
int detailType;
+ // RangeData prefers detailString; RangeLocation prefers detailUrl.
QString detailString; //used by RangeData and possibly by RangeLocation
- QUrl detailUrl; //used by RangeLocation, overrides detailString
+ QUrl detailUrl; //used by RangeLocation and possibly by RangeData
int x; //used by RangeLocation
int y; //used by RangeLocation
-
- void toByteArrays(QList<QByteArray> &messages) const;
};
Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
@@ -121,11 +121,11 @@ public:
// Have toByteArrays() construct another RangeData event from the same QString later.
// This is somewhat pointless but important for backwards compatibility.
- void startCompiling(const QString &name)
+ void startCompiling(const QUrl &url)
{
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
(1 << RangeStart | 1 << RangeLocation | 1 << RangeData),
- 1 << Compiling, name, 1, 1));
+ 1 << Compiling, url, 1, 1));
}
void startHandlingSignal(const QQmlSourceLocation &location)
@@ -171,24 +171,11 @@ public slots:
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
signals:
- void dataReady(const QList<QQmlProfilerData> &);
+ void dataReady(const QVector<QQmlProfilerData> &);
protected:
QElapsedTimer m_timer;
- QVarLengthArray<QQmlProfilerData> m_data;
-};
-
-class QQmlProfilerAdapter : public QQmlAbstractProfilerAdapter {
- Q_OBJECT
-public:
- QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine);
- qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
-
-public slots:
- void receiveData(const QList<QQmlProfilerData> &new_data);
-
-private:
- QList<QQmlProfilerData> data;
+ QVector<QQmlProfilerData> m_data;
};
//
@@ -231,10 +218,10 @@ struct QQmlHandlingSignalProfiler : public QQmlProfilerHelper {
};
struct QQmlCompilingProfiler : public QQmlProfilerHelper {
- QQmlCompilingProfiler(QQmlProfiler *profiler, const QString &name) :
+ QQmlCompilingProfiler(QQmlProfiler *profiler, const QUrl &url) :
QQmlProfilerHelper(profiler)
{
- Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCompiling, profiler, startCompiling(name));
+ Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCompiling, profiler, startCompiling(url));
}
~QQmlCompilingProfiler()
@@ -332,6 +319,6 @@ private:
};
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QList<QQmlProfilerData>)
+Q_DECLARE_METATYPE(QVector<QQmlProfilerData>)
#endif // QQMLPROFILER_P_H
diff --git a/src/qml/debugger/qv4debugservice.cpp b/src/qml/debugger/qv4debugservice.cpp
deleted file mode 100644
index cefb29e031..0000000000
--- a/src/qml/debugger/qv4debugservice.cpp
+++ /dev/null
@@ -1,1265 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qv4debugservice_p.h"
-#include "qqmlconfigurabledebugservice_p_p.h"
-#include "qqmlengine.h"
-#include "qv4debugging_p.h"
-#include "qv4engine_p.h"
-#include "qv4function_p.h"
-#include "qqmldebugserver_p.h"
-
-#include <private/qv8engine_p.h>
-
-#include <QtCore/QJsonArray>
-#include <QtCore/QJsonDocument>
-#include <QtCore/QJsonObject>
-#include <QtCore/QJsonValue>
-
-const char *V4_CONNECT = "connect";
-const char *V4_DISCONNECT = "disconnect";
-const char *V4_BREAK_ON_SIGNAL = "breakonsignal";
-const char *V4_ADD_BREAKPOINT = "addBreakpoint";
-const char *V4_REMOVE_BREAKPOINT = "removeBreakpoint";
-const char *V4_PAUSE = "interrupt";
-const char *V4_ALL = "all";
-const char *V4_BREAK = "break";
-
-const char *V4_FILENAME = "filename";
-const char *V4_LINENUMBER = "linenumber";
-
-#define NO_PROTOCOL_TRACING
-#ifdef NO_PROTOCOL_TRACING
-# define TRACE_PROTOCOL(x)
-#else
-#include <QtCore/QDebug>
-# define TRACE_PROTOCOL(x) x
-#endif
-
-QT_BEGIN_NAMESPACE
-
-Q_GLOBAL_STATIC(QV4DebugService, v4ServiceInstance)
-
-class QV4DebugServicePrivate;
-
-class QV4DebuggerAgent : public QV4::Debugging::DebuggerAgent
-{
-public:
- QV4DebuggerAgent(QV4DebugServicePrivate *debugServicePrivate)
- : debugServicePrivate(debugServicePrivate)
- {}
-
- QV4::Debugging::Debugger *firstDebugger() const
- {
- // Currently only 1 single engine is supported, so:
- if (m_debuggers.isEmpty())
- return 0;
- else
- return m_debuggers.first();
- }
-
- bool isRunning() const
- {
- // Currently only 1 single engine is supported, so:
- if (QV4::Debugging::Debugger *debugger = firstDebugger())
- return debugger->state() == QV4::Debugging::Debugger::Running;
- else
- return false;
- }
-
-public slots:
- virtual void debuggerPaused(QV4::Debugging::Debugger *debugger, QV4::Debugging::PauseReason reason);
- virtual void sourcesCollected(QV4::Debugging::Debugger *debugger, QStringList sources, int requestSequenceNr);
-
-private:
- QV4DebugServicePrivate *debugServicePrivate;
-};
-
-class V8CommandHandler;
-class UnknownV8CommandHandler;
-
-class VariableCollector: public QV4::Debugging::Debugger::Collector
-{
-public:
- VariableCollector(QV4::ExecutionEngine *engine)
- : Collector(engine)
- , destination(0)
- {}
-
- virtual ~VariableCollector() {}
-
- void collectScope(QJsonArray *dest, QV4::Debugging::Debugger *debugger, int frameNr, int scopeNr)
- {
- qSwap(destination, dest);
- bool oldIsProp = isProperty();
- setIsProperty(true);
- debugger->collectArgumentsInContext(this, frameNr, scopeNr);
- debugger->collectLocalsInContext(this, frameNr, scopeNr);
- setIsProperty(oldIsProp);
- qSwap(destination, dest);
- }
-
- void setDestination(QJsonArray *dest)
- { destination = dest; }
-
- QJsonArray retrieveRefsToInclude()
- {
- QJsonArray result;
- qSwap(refsToInclude, result);
- return result;
- }
-
- QJsonValue lookup(int handle, bool addRefs = true)
- {
- if (handle < 0)
- handle = -handle;
-
- if (addRefs)
- foreach (int ref, refsByHandle[handle])
- refsToInclude.append(lookup(ref, false));
- return refs[handle];
- }
-
- QJsonObject makeRef(int refId)
- {
- QJsonObject ref;
- ref[QLatin1String("ref")] = refId;
- return ref;
- }
-
- QJsonObject addFunctionRef(const QString &name)
- {
- const int refId = newRefId();
-
- QJsonObject func;
- func[QLatin1String("handle")] = refId;
- func[QLatin1String("type")] = QStringLiteral("function");
- func[QLatin1String("className")] = QStringLiteral("Function");
- func[QLatin1String("name")] = name;
- insertRef(func, refId);
-
- return makeRef(refId);
- }
-
- QJsonObject addScriptRef(const QString &name)
- {
- const int refId = newRefId();
-
- QJsonObject func;
- func[QLatin1String("handle")] = refId;
- func[QLatin1String("type")] = QStringLiteral("script");
- func[QLatin1String("name")] = name;
- insertRef(func, refId);
-
- return makeRef(refId);
- }
-
- QJsonObject addObjectRef(QJsonObject obj, bool anonymous)
- {
- int ref = newRefId();
-
- if (anonymous)
- ref = -ref;
- obj[QLatin1String("handle")] = ref;
- obj[QLatin1String("type")] = QStringLiteral("object");
- insertRef(obj, ref);
- QSet<int> used;
- qSwap(usedRefs, used);
- refsByHandle.insert(ref, used);
-
- return makeRef(ref);
- }
-
-protected:
- virtual void addUndefined(const QString &name)
- {
- QJsonObject o;
- addHandle(name, o, QStringLiteral("undefined"));
- }
-
- virtual void addNull(const QString &name)
- {
- QJsonObject o;
- addHandle(name, o, QStringLiteral("null"));
- }
-
- virtual void addBoolean(const QString &name, bool value)
- {
- QJsonObject o;
- o[QLatin1String("value")] = value;
- addHandle(name, o, QStringLiteral("boolean"));
- }
-
- virtual void addString(const QString &name, const QString &value)
- {
- QJsonObject o;
- o[QLatin1String("value")] = value;
- addHandle(name, o, QStringLiteral("string"));
- }
-
- virtual void addObject(const QString &name, const QV4::Value &value)
- {
- QV4::Scope scope(engine());
- QV4::ScopedObject obj(scope, value.asObject());
-
- int ref = cachedObjectRef(obj);
- if (ref != -1) {
- addNameRefPair(name, ref);
- } else {
- int ref = newRefId();
- cacheObjectRef(obj, ref);
-
- QJsonArray properties, *prev = &properties;
- QSet<int> used;
- qSwap(usedRefs, used);
- qSwap(destination, prev);
- collect(obj);
- qSwap(destination, prev);
- qSwap(usedRefs, used);
-
- QJsonObject o;
- o[QLatin1String("properties")] = properties;
- addHandle(name, o, QStringLiteral("object"), ref);
- refsByHandle.insert(ref, used);
- }
- }
-
- virtual void addInteger(const QString &name, int value)
- {
- QJsonObject o;
- o[QLatin1String("value")] = value;
- addHandle(name, o, QStringLiteral("number"));
- }
-
- virtual void addDouble(const QString &name, double value)
- {
- QJsonObject o;
- o[QLatin1String("value")] = value;
- addHandle(name, o, QStringLiteral("number"));
- }
-
-private:
- int addHandle(const QString &name, QJsonObject object, const QString &type, int suppliedRef = -1)
- {
- Q_ASSERT(destination);
-
- object[QLatin1String("type")] = type;
-
- QJsonDocument tmp;
- tmp.setObject(object);
- QByteArray key = tmp.toJson(QJsonDocument::Compact);
-
- int ref;
- if (suppliedRef == -1) {
- ref = refCache.value(key, -1);
- if (ref == -1) {
- ref = newRefId();
- object[QLatin1String("handle")] = ref;
- insertRef(object, ref);
- refCache.insert(key, ref);
- }
- } else {
- ref = suppliedRef;
- object[QLatin1String("handle")] = ref;
- insertRef(object, ref);
- refCache.insert(key, ref);
- }
-
- addNameRefPair(name, ref);
- return ref;
- }
-
- void addNameRefPair(const QString &name, int ref)
- {
- QJsonObject nameValuePair;
- nameValuePair[QLatin1String("name")] = name;
- if (isProperty()) {
- nameValuePair[QLatin1String("ref")] = ref;
- } else {
- QJsonObject refObj;
- refObj[QLatin1String("ref")] = ref;
- nameValuePair[QLatin1String("value")] = refObj;
- }
- destination->append(nameValuePair);
- usedRefs.insert(ref);
- }
-
- int newRefId()
- {
- int ref = refs.count();
- refs.insert(ref, QJsonValue());
- return ref;
- }
-
- void insertRef(const QJsonValue &value, int refId)
- {
- if (refId < 0)
- refId = -refId;
-
- refs.insert(refId, value);
- refsToInclude.append(value);
- }
-
- void cacheObjectRef(QV4::Value obj, int ref)
- {
- objectRefs.insert(obj.val, ref);
- }
-
- int cachedObjectRef(QV4::Value obj) const
- {
- return objectRefs.value(obj.val, -1);
- }
-
-private:
- QJsonArray refsToInclude;
- QHash<int, QJsonValue> refs;
- QHash<QByteArray, int> refCache;
- QJsonArray *destination;
- QSet<int> usedRefs;
- QHash<int, QSet<int> > refsByHandle;
- QHash<quint64, int> objectRefs;
-};
-
-class QV4DebugServicePrivate : public QQmlConfigurableDebugServicePrivate
-{
- Q_DECLARE_PUBLIC(QV4DebugService)
-
-public:
- QV4DebugServicePrivate();
- ~QV4DebugServicePrivate() { qDeleteAll(handlers.values()); }
-
- static QByteArray packMessage(const QByteArray &command, const QByteArray &message = QByteArray())
- {
- QByteArray reply;
- QQmlDebugStream rs(&reply, QIODevice::WriteOnly);
- static const QByteArray cmd("V8DEBUG");
- rs << cmd << command << message;
- return reply;
- }
-
- void send(QJsonObject v8Payload)
- {
- v8Payload[QLatin1String("seq")] = sequence++;
- QJsonDocument doc;
- doc.setObject(v8Payload);
-#ifdef NO_PROTOCOL_TRACING
- QByteArray responseData = doc.toJson(QJsonDocument::Compact);
-#else
- QByteArray responseData = doc.toJson(QJsonDocument::Indented);
-#endif
-
- TRACE_PROTOCOL(qDebug() << "sending response for:" << responseData << endl);
-
- q_func()->sendMessage(packMessage("v8message", responseData));
- }
-
- void processCommand(const QByteArray &command, const QByteArray &data);
-
- QV4DebuggerAgent debuggerAgent;
-
- QStringList breakOnSignals;
- QMap<int, QV4::Debugging::Debugger *> debuggerMap;
- static int debuggerIndex;
- static int sequence;
- const int version;
-
- V8CommandHandler *v8CommandHandler(const QString &command) const;
-
- void clearHandles(QV4::ExecutionEngine *engine)
- {
- theCollector.reset(new VariableCollector(engine));
- }
-
- QJsonObject buildFrame(const QV4::StackFrame &stackFrame, int frameNr,
- QV4::Debugging::Debugger *debugger)
- {
- QJsonObject frame;
- frame[QLatin1String("index")] = frameNr;
- frame[QLatin1String("debuggerFrame")] = false;
- frame[QLatin1String("func")] = theCollector->addFunctionRef(stackFrame.function);
- frame[QLatin1String("script")] = theCollector->addScriptRef(stackFrame.source);
- frame[QLatin1String("line")] = stackFrame.line - 1;
- if (stackFrame.column >= 0)
- frame[QLatin1String("column")] = stackFrame.column;
-
- QJsonArray properties;
- theCollector->setDestination(&properties);
- if (debugger->collectThisInContext(theCollector.data(), frameNr)) {
- QJsonObject obj;
- obj[QLatin1String("properties")] = properties;
- frame[QLatin1String("receiver")] = theCollector->addObjectRef(obj, false);
- }
-
- QJsonArray scopes;
- // Only type and index are used by Qt Creator, so we keep it easy:
- QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes = debugger->getScopeTypes(frameNr);
- for (int i = 0, ei = scopeTypes.count(); i != ei; ++i) {
- int type = encodeScopeType(scopeTypes[i]);
- if (type == -1)
- continue;
-
- QJsonObject scope;
- scope[QLatin1String("index")] = i;
- scope[QLatin1String("type")] = type;
- scopes.push_back(scope);
- }
- frame[QLatin1String("scopes")] = scopes;
-
- return frame;
- }
-
- int encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType)
- {
- switch (scopeType) {
- case QV4::Heap::ExecutionContext::Type_GlobalContext:
- return 0;
- break;
- case QV4::Heap::ExecutionContext::Type_CatchContext:
- return 4;
- break;
- case QV4::Heap::ExecutionContext::Type_WithContext:
- return 2;
- break;
- case QV4::Heap::ExecutionContext::Type_SimpleCallContext:
- case QV4::Heap::ExecutionContext::Type_CallContext:
- return 1;
- break;
- case QV4::Heap::ExecutionContext::Type_QmlContext:
- default:
- return -1;
- }
- }
-
- QJsonObject buildScope(int frameNr, int scopeNr, QV4::Debugging::Debugger *debugger)
- {
- QJsonObject scope;
-
- QJsonArray properties;
- theCollector->collectScope(&properties, debugger, frameNr, scopeNr);
-
- QJsonObject anonymous;
- anonymous[QLatin1String("properties")] = properties;
-
- QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes = debugger->getScopeTypes(frameNr);
- scope[QLatin1String("type")] = encodeScopeType(scopeTypes[scopeNr]);
- scope[QLatin1String("index")] = scopeNr;
- scope[QLatin1String("frameIndex")] = frameNr;
- scope[QLatin1String("object")] = theCollector->addObjectRef(anonymous, true);
-
- return scope;
- }
-
- QJsonValue lookup(int refId) const { return theCollector->lookup(refId); }
-
- QJsonArray buildRefs()
- {
- return theCollector->retrieveRefsToInclude();
- }
-
- VariableCollector *collector() const
- {
- return theCollector.data();
- }
-
- void selectFrame(int frameNr)
- { theSelectedFrame = frameNr; }
-
- int selectedFrame() const
- { return theSelectedFrame; }
-
-private:
- QScopedPointer<VariableCollector> theCollector;
- int theSelectedFrame;
-
- void addHandler(V8CommandHandler* handler);
- QHash<QString, V8CommandHandler*> handlers;
- QScopedPointer<UnknownV8CommandHandler> unknownV8CommandHandler;
-};
-
-int QV4DebugServicePrivate::debuggerIndex = 0;
-int QV4DebugServicePrivate::sequence = 0;
-
-class V8CommandHandler
-{
-public:
- V8CommandHandler(const QString &command)
- : cmd(command)
- {}
-
- virtual ~V8CommandHandler()
- {}
-
- QString command() const { return cmd; }
-
- void handle(const QJsonObject &request, QQmlDebugService *s, QV4DebugServicePrivate *p)
- {
- TRACE_PROTOCOL(qDebug() << "handling command" << command() << "...");
-
- req = request;
- seq = req.value(QStringLiteral("seq"));
- debugService = s;
- debugServicePrivate = p;
-
- handleRequest();
- if (!response.isEmpty()) {
- response[QLatin1String("type")] = QStringLiteral("response");
- debugServicePrivate->send(response);
- }
-
- debugServicePrivate = 0;
- debugService = 0;
- seq = QJsonValue();
- req = QJsonObject();
- response = QJsonObject();
- }
-
- virtual void handleRequest() = 0;
-
-protected:
- void addCommand() { response.insert(QStringLiteral("command"), cmd); }
- void addRequestSequence() { response.insert(QStringLiteral("request_seq"), seq); }
- void addSuccess(bool success) { response.insert(QStringLiteral("success"), success); }
- void addBody(const QJsonObject &body)
- {
- response.insert(QStringLiteral("body"), body);
- }
-
- void addRunning()
- {
- response.insert(QStringLiteral("running"), debugServicePrivate->debuggerAgent.isRunning());
- }
-
- void addRefs()
- {
- response.insert(QStringLiteral("refs"), debugServicePrivate->buildRefs());
- }
-
- void createErrorResponse(const QString &msg)
- {
- QJsonValue command = req.value(QStringLiteral("command"));
- response.insert(QStringLiteral("command"), command);
- addRequestSequence();
- addSuccess(false);
- addRunning();
- response.insert(QStringLiteral("message"), msg);
- }
-
- int requestSequenceNr() const
- { return seq.toInt(-1); }
-
-protected:
- QString cmd;
- QJsonObject req;
- QJsonValue seq;
- QQmlDebugService *debugService;
- QV4DebugServicePrivate *debugServicePrivate;
- QJsonObject response;
-};
-
-class UnknownV8CommandHandler: public V8CommandHandler
-{
-public:
- UnknownV8CommandHandler(): V8CommandHandler(QString()) {}
-
- virtual void handleRequest()
- {
- QString msg = QStringLiteral("unimplemented command \"");
- msg += req.value(QStringLiteral("command")).toString();
- msg += QStringLiteral("\"");
- createErrorResponse(msg);
- }
-};
-
-namespace {
-class V8VersionRequest: public V8CommandHandler
-{
-public:
- V8VersionRequest(): V8CommandHandler(QStringLiteral("version")) {}
-
- virtual void handleRequest()
- {
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- QJsonObject body;
- body.insert(QStringLiteral("V8Version"),
- QLatin1String("this is not V8, this is V4 in Qt " QT_VERSION_STR));
- addBody(body);
- }
-};
-
-class V8SetBreakPointRequest: public V8CommandHandler
-{
-public:
- V8SetBreakPointRequest(): V8CommandHandler(QStringLiteral("setbreakpoint")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject args = req.value(QStringLiteral("arguments")).toObject();
- if (args.isEmpty())
- return;
-
- QString type = args.value(QStringLiteral("type")).toString();
- if (type != QStringLiteral("scriptRegExp")) {
- createErrorResponse(QStringLiteral("breakpoint type \"%1\" is not implemented").arg(type));
- return;
- }
-
- QString fileName = args.value(QStringLiteral("target")).toString();
- if (fileName.isEmpty()) {
- createErrorResponse(QStringLiteral("breakpoint has no file name"));
- return;
- }
-
- int line = args.value(QStringLiteral("line")).toInt(-1);
- if (line < 0) {
- createErrorResponse(QStringLiteral("breakpoint has an invalid line number"));
- return;
- }
-
- bool enabled = args.value(QStringLiteral("enabled")).toBool(true);
- QString condition = args.value(QStringLiteral("condition")).toString();
-
- // set the break point:
- int id = debugServicePrivate->debuggerAgent.addBreakPoint(fileName, line + 1, enabled, condition);
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- QJsonObject body;
- body.insert(QStringLiteral("type"), type);
- body.insert(QStringLiteral("breakpoint"), id);
- // It's undocumented, but V8 sends back an actual_locations array too. However, our
- // Debugger currently doesn't tell us when it resolved a breakpoint, so we'll leave them
- // pending until the breakpoint is hit for the first time.
- addBody(body);
- }
-};
-
-class V8ClearBreakPointRequest: public V8CommandHandler
-{
-public:
- V8ClearBreakPointRequest(): V8CommandHandler(QStringLiteral("clearbreakpoint")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject args = req.value(QStringLiteral("arguments")).toObject();
- if (args.isEmpty())
- return;
-
- int id = args.value(QStringLiteral("breakpoint")).toInt(-1);
- if (id < 0) {
- createErrorResponse(QStringLiteral("breakpoint has an invalid number"));
- return;
- }
-
- // remove the break point:
- debugServicePrivate->debuggerAgent.removeBreakPoint(id);
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- QJsonObject body;
- body.insert(QStringLiteral("type"), QStringLiteral("scriptRegExp"));
- body.insert(QStringLiteral("breakpoint"), id);
- addBody(body);
- }
-};
-
-class V8BacktraceRequest: public V8CommandHandler
-{
-public:
- V8BacktraceRequest(): V8CommandHandler(QStringLiteral("backtrace")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
-
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- int fromFrame = arguments.value(QStringLiteral("fromFrame")).toInt(0);
- int toFrame = arguments.value(QStringLiteral("toFrame")).toInt(fromFrame + 10);
- // no idea what the bottom property is for, so we'll ignore it.
-
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
-
- QJsonArray frameArray;
- QVector<QV4::StackFrame> frames = debugger->stackTrace(toFrame);
- for (int i = fromFrame; i < toFrame && i < frames.size(); ++i)
- frameArray.push_back(debugServicePrivate->buildFrame(frames[i], i, debugger));
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- QJsonObject body;
- if (frameArray.isEmpty()) {
- body.insert(QStringLiteral("totalFrames"), 0);
- } else {
- body.insert(QStringLiteral("fromFrame"), fromFrame);
- body.insert(QStringLiteral("toFrame"), fromFrame + frameArray.size());
- body.insert(QStringLiteral("frames"), frameArray);
- }
- addBody(body);
- addRefs();
- }
-};
-
-class V8FrameRequest: public V8CommandHandler
-{
-public:
- V8FrameRequest(): V8CommandHandler(QStringLiteral("frame")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- const int frameNr = arguments.value(QStringLiteral("number")).toInt(debugServicePrivate->selectedFrame());
-
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
- QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1);
- if (frameNr < 0 || frameNr >= frames.size()) {
- createErrorResponse(QStringLiteral("frame command has invalid frame number"));
- return;
- }
-
- debugServicePrivate->selectFrame(frameNr);
- QJsonObject frame = debugServicePrivate->buildFrame(frames[frameNr], frameNr, debugger);
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- addBody(frame);
- addRefs();
- }
-};
-
-class V8ScopeRequest: public V8CommandHandler
-{
-public:
- V8ScopeRequest(): V8CommandHandler(QStringLiteral("scope")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- const int frameNr = arguments.value(QStringLiteral("frameNumber")).toInt(debugServicePrivate->selectedFrame());
- const int scopeNr = arguments.value(QStringLiteral("number")).toInt(0);
-
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
- QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1);
- if (frameNr < 0 || frameNr >= frames.size()) {
- createErrorResponse(QStringLiteral("scope command has invalid frame number"));
- return;
- }
- if (scopeNr < 0) {
- createErrorResponse(QStringLiteral("scope command has invalid scope number"));
- return;
- }
-
- QJsonObject scope = debugServicePrivate->buildScope(frameNr, scopeNr, debugger);
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- addBody(scope);
- addRefs();
- }
-};
-
-class V8LookupRequest: public V8CommandHandler
-{
-public:
- V8LookupRequest(): V8CommandHandler(QStringLiteral("lookup")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- QJsonArray handles = arguments.value(QStringLiteral("handles")).toArray();
-
- QJsonObject body;
- foreach (QJsonValue handle, handles)
- body[QString::number(handle.toInt())] = debugServicePrivate->lookup(handle.toInt());
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- addBody(body);
- addRefs();
- }
-};
-
-class V8ContinueRequest: public V8CommandHandler
-{
-public:
- V8ContinueRequest(): V8CommandHandler(QStringLiteral("continue")) {}
-
- virtual void handleRequest()
- {
- // decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
-
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
-
- if (arguments.empty()) {
- debugger->resume(QV4::Debugging::Debugger::FullThrottle);
- } else {
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- QString stepAction = arguments.value(QStringLiteral("stepaction")).toString();
- const int stepcount = arguments.value(QStringLiteral("stepcount")).toInt(1);
- if (stepcount != 1)
- qWarning() << "Step count other than 1 is not supported.";
-
- if (stepAction == QStringLiteral("in")) {
- debugger->resume(QV4::Debugging::Debugger::StepIn);
- } else if (stepAction == QStringLiteral("out")) {
- debugger->resume(QV4::Debugging::Debugger::StepOut);
- } else if (stepAction == QStringLiteral("next")) {
- debugger->resume(QV4::Debugging::Debugger::StepOver);
- } else {
- createErrorResponse(QStringLiteral("continue command has invalid stepaction"));
- return;
- }
- }
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- }
-};
-
-class V8DisconnectRequest: public V8CommandHandler
-{
-public:
- V8DisconnectRequest(): V8CommandHandler(QStringLiteral("disconnect")) {}
-
- virtual void handleRequest()
- {
- debugServicePrivate->debuggerAgent.removeAllBreakPoints();
- debugServicePrivate->debuggerAgent.resumeAll();
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- }
-};
-
-class V8SetExceptionBreakRequest: public V8CommandHandler
-{
-public:
- V8SetExceptionBreakRequest(): V8CommandHandler(QStringLiteral("setexceptionbreak")) {}
-
- virtual void handleRequest()
- {
- bool wasEnabled = debugServicePrivate->debuggerAgent.breakOnThrow();
-
- //decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- QString type = arguments.value(QStringLiteral("type")).toString();
- bool enabled = arguments.value(QStringLiteral("number")).toBool(!wasEnabled);
-
- if (type == QStringLiteral("all")) {
- // that's fine
- } else if (type == QStringLiteral("uncaught")) {
- createErrorResponse(QStringLiteral("breaking only on uncaught exceptions is not supported yet"));
- return;
- } else {
- createErrorResponse(QStringLiteral("invalid type for break on exception"));
- return;
- }
-
- // do it:
- debugServicePrivate->debuggerAgent.setBreakOnThrow(enabled);
-
- QJsonObject body;
- body[QLatin1String("type")] = type;
- body[QLatin1String("enabled")] = debugServicePrivate->debuggerAgent.breakOnThrow();
-
- // response:
- addBody(body);
- addRunning();
- addSuccess(true);
- addRequestSequence();
- addCommand();
- }
-};
-
-class V8ScriptsRequest: public V8CommandHandler
-{
-public:
- V8ScriptsRequest(): V8CommandHandler(QStringLiteral("scripts")) {}
-
- virtual void handleRequest()
- {
- //decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- int types = arguments.value(QStringLiteral("types")).toInt(-1);
- if (types < 0 || types > 7) {
- createErrorResponse(QStringLiteral("invalid types value in scripts command"));
- return;
- } else if (types != 4) {
- createErrorResponse(QStringLiteral("unsupported types value in scripts command"));
- return;
- }
-
- // do it:
- debugServicePrivate->debuggerAgent.firstDebugger()->gatherSources(requestSequenceNr());
-
- // response will be send by
- }
-};
-
-// Request:
-// {
-// "seq": 4,
-// "type": "request",
-// "command": "evaluate",
-// "arguments": {
-// "expression": "a",
-// "frame": 0
-// }
-// }
-//
-// Response:
-// {
-// "body": {
-// "handle": 3,
-// "type": "number",
-// "value": 1
-// },
-// "command": "evaluate",
-// "refs": [],
-// "request_seq": 4,
-// "running": false,
-// "seq": 5,
-// "success": true,
-// "type": "response"
-// }
-//
-// The "value" key in "body" is the result of evaluating the expression in the request.
-class V8EvaluateRequest: public V8CommandHandler
-{
-public:
- V8EvaluateRequest(): V8CommandHandler(QStringLiteral("evaluate")) {}
-
- virtual void handleRequest()
- {
- //decypher the payload:
- QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject();
- QString expression = arguments.value(QStringLiteral("expression")).toString();
- const int frame = arguments.value(QStringLiteral("frame")).toInt(0);
-
- QV4::Debugging::Debugger *debugger = debugServicePrivate->debuggerAgent.firstDebugger();
- Q_ASSERT(debugger->state() == QV4::Debugging::Debugger::Paused);
-
- VariableCollector *collector = debugServicePrivate->collector();
- QJsonArray dest;
- collector->setDestination(&dest);
- debugger->evaluateExpression(frame, expression, collector);
-
- const int ref = dest.at(0).toObject().value(QStringLiteral("value")).toObject()
- .value(QStringLiteral("ref")).toInt();
-
- // response:
- addCommand();
- addRequestSequence();
- addSuccess(true);
- addRunning();
- addBody(collector->lookup(ref).toObject());
- addRefs();
- }
-};
-} // anonymous namespace
-
-QV4DebugServicePrivate::QV4DebugServicePrivate()
- : debuggerAgent(this)
- , version(1)
- , theSelectedFrame(0)
- , unknownV8CommandHandler(new UnknownV8CommandHandler)
-{
- addHandler(new V8VersionRequest);
- addHandler(new V8SetBreakPointRequest);
- addHandler(new V8ClearBreakPointRequest);
- addHandler(new V8BacktraceRequest);
- addHandler(new V8FrameRequest);
- addHandler(new V8ScopeRequest);
- addHandler(new V8LookupRequest);
- addHandler(new V8ContinueRequest);
- addHandler(new V8DisconnectRequest);
- addHandler(new V8SetExceptionBreakRequest);
- addHandler(new V8ScriptsRequest);
- addHandler(new V8EvaluateRequest);
-}
-
-void QV4DebugServicePrivate::addHandler(V8CommandHandler* handler)
-{
- handlers[handler->command()] = handler;
-}
-
-V8CommandHandler *QV4DebugServicePrivate::v8CommandHandler(const QString &command) const
-{
- V8CommandHandler *handler = handlers.value(command, 0);
- if (handler)
- return handler;
- else
- return unknownV8CommandHandler.data();
-}
-
-QV4DebugService::QV4DebugService(QObject *parent)
- : QQmlConfigurableDebugService(*(new QV4DebugServicePrivate()),
- QStringLiteral("V8Debugger"), 1, parent)
-{}
-
-QV4DebugService::~QV4DebugService()
-{
-}
-
-QV4DebugService *QV4DebugService::instance()
-{
- return v4ServiceInstance();
-}
-
-void QV4DebugService::engineAboutToBeAdded(QQmlEngine *engine)
-{
- Q_D(QV4DebugService);
- QMutexLocker lock(configMutex());
- if (engine) {
- QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
- if (QQmlDebugServer *server = QQmlDebugServer::instance()) {
- if (ee) {
- ee->enableDebugger();
- QV4::Debugging::Debugger *debugger = ee->debugger;
- d->debuggerMap.insert(d->debuggerIndex++, debugger);
- d->debuggerAgent.addDebugger(debugger);
- d->debuggerAgent.moveToThread(server->thread());
- moveToThread(server->thread());
- }
- }
- }
- QQmlConfigurableDebugService::engineAboutToBeAdded(engine);
-}
-
-void QV4DebugService::engineAboutToBeRemoved(QQmlEngine *engine)
-{
- Q_D(QV4DebugService);
- QMutexLocker lock(configMutex());
- if (engine){
- const QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
- if (ee) {
- QV4::Debugging::Debugger *debugger = ee->debugger;
- typedef QMap<int, QV4::Debugging::Debugger *>::const_iterator DebuggerMapIterator;
- const DebuggerMapIterator end = d->debuggerMap.constEnd();
- for (DebuggerMapIterator i = d->debuggerMap.constBegin(); i != end; ++i) {
- if (i.value() == debugger) {
- d->debuggerMap.remove(i.key());
- break;
- }
- }
- d->debuggerAgent.removeDebugger(debugger);
- }
- }
- QQmlConfigurableDebugService::engineAboutToBeRemoved(engine);
-}
-
-void QV4DebugService::signalEmitted(const QString &signal)
-{
- //This function is only called by QQmlBoundSignal
- //only if there is a slot connected to the signal. Hence, there
- //is no need for additional check.
- Q_D(QV4DebugService);
-
- //Parse just the name and remove the class info
- //Normalize to Lower case.
- QString signalName = signal.left(signal.indexOf(QLatin1Char('('))).toLower();
-
- foreach (const QString &signal, d->breakOnSignals) {
- if (signal == signalName) {
- // TODO: pause debugger
- break;
- }
- }
-}
-
-void QV4DebugService::messageReceived(const QByteArray &message)
-{
- Q_D(QV4DebugService);
- QMutexLocker lock(configMutex());
-
- QQmlDebugStream ms(message);
- QByteArray header;
- ms >> header;
-
- TRACE_PROTOCOL(qDebug() << "received message with header" << header);
-
- if (header == "V8DEBUG") {
- QByteArray type;
- QByteArray payload;
- ms >> type >> payload;
- TRACE_PROTOCOL(qDebug() << "... type:" << type);
-
- if (type == V4_CONNECT) {
- sendMessage(d->packMessage(type));
- stopWaiting();
- } else if (type == V4_PAUSE) {
- d->debuggerAgent.pauseAll();
- sendSomethingToSomebody(type);
- } else if (type == V4_BREAK_ON_SIGNAL) {
- QByteArray signal;
- bool enabled;
- ms >> signal >> enabled;
- //Normalize to lower case.
- QString signalName(QString::fromUtf8(signal).toLower());
- if (enabled)
- d->breakOnSignals.append(signalName);
- else
- d->breakOnSignals.removeOne(signalName);
- } else if (type == "v8request") {
- handleV8Request(payload);
- } else if (type == V4_DISCONNECT) {
- TRACE_PROTOCOL(qDebug() << "... payload:" << payload);
- handleV8Request(payload);
- } else {
- sendSomethingToSomebody(type, 0);
- }
- }
-}
-
-void QV4DebugService::sendSomethingToSomebody(const char *type, int magicNumber)
-{
- Q_D(QV4DebugService);
-
- QByteArray response;
- QQmlDebugStream rs(&response, QIODevice::WriteOnly);
- rs << QByteArray(type)
- << QByteArray::number(d->version) << QByteArray::number(magicNumber);
- sendMessage(d->packMessage(type, response));
-}
-
-void QV4DebuggerAgent::debuggerPaused(QV4::Debugging::Debugger *debugger, QV4::Debugging::PauseReason reason)
-{
- Q_UNUSED(reason);
-
- debugServicePrivate->clearHandles(debugger->engine());
-
- QJsonObject event, body, script;
- event.insert(QStringLiteral("type"), QStringLiteral("event"));
-
- switch (reason) {
- case QV4::Debugging::Step:
- case QV4::Debugging::PauseRequest:
- case QV4::Debugging::BreakPoint: {
- event.insert(QStringLiteral("event"), QStringLiteral("break"));
- QVector<QV4::StackFrame> frames = debugger->stackTrace(1);
- if (frames.isEmpty())
- break;
-
- const QV4::StackFrame &topFrame = frames.first();
- body.insert(QStringLiteral("invocationText"), topFrame.function);
- body.insert(QStringLiteral("sourceLine"), topFrame.line - 1);
- if (topFrame.column > 0)
- body.insert(QStringLiteral("sourceColumn"), topFrame.column);
- QJsonArray breakPoints;
- foreach (int breakPointId, breakPointIds(topFrame.source, topFrame.line))
- breakPoints.push_back(breakPointId);
- body.insert(QStringLiteral("breakpoints"), breakPoints);
- script.insert(QStringLiteral("name"), topFrame.source);
- } break;
- case QV4::Debugging::Throwing:
- // TODO: complete this!
- event.insert(QStringLiteral("event"), QStringLiteral("exception"));
- break;
- }
-
- if (!script.isEmpty())
- body.insert(QStringLiteral("script"), script);
- if (!body.isEmpty())
- event.insert(QStringLiteral("body"), body);
- debugServicePrivate->send(event);
-}
-
-void QV4DebuggerAgent::sourcesCollected(QV4::Debugging::Debugger *debugger, QStringList sources, int requestSequenceNr)
-{
- QJsonArray body;
- foreach (const QString source, sources) {
- QJsonObject src;
- src[QLatin1String("name")] = source;
- src[QLatin1String("scriptType")] = 4;
- body.append(src);
- }
-
- QJsonObject response;
- response[QLatin1String("success")] = true;
- response[QLatin1String("running")] = debugger->state() == QV4::Debugging::Debugger::Running;
- response[QLatin1String("body")] = body;
- response[QLatin1String("command")] = QStringLiteral("scripts");
- response[QLatin1String("request_seq")] = requestSequenceNr;
- response[QLatin1String("type")] = QStringLiteral("response");
- debugServicePrivate->send(response);
-}
-
-void QV4DebugService::handleV8Request(const QByteArray &payload)
-{
- Q_D(QV4DebugService);
-
- TRACE_PROTOCOL(qDebug() << "v8request, payload:" << payload);
-
- QJsonDocument request = QJsonDocument::fromJson(payload);
- QJsonObject o = request.object();
- QJsonValue type = o.value(QStringLiteral("type"));
- if (type.toString() == QStringLiteral("request")) {
- QJsonValue command = o.value(QStringLiteral("command"));
- V8CommandHandler *h = d->v8CommandHandler(command.toString());
- if (h)
- h->handle(o, this, d);
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/doc/qtqml.qdocconf b/src/qml/doc/qtqml.qdocconf
index 74b61fd6e1..500754ead4 100644
--- a/src/qml/doc/qtqml.qdocconf
+++ b/src/qml/doc/qtqml.qdocconf
@@ -4,7 +4,7 @@ project = QtQml
description = Qt QML Reference Documentation
version = $QT_VERSION
-examplesinstallpath = qml
+examplesinstallpath = qtdeclarative/qml
qhp.projects = QtQml
diff --git a/src/qml/doc/snippets/qml/qtBinding.2.qml b/src/qml/doc/snippets/qml/qtBinding.2.qml
index 6a9a2de750..6159b31748 100644
--- a/src/qml/doc/snippets/qml/qtBinding.2.qml
+++ b/src/qml/doc/snippets/qml/qtBinding.2.qml
@@ -52,7 +52,7 @@ Item {
root.dynamicText = "Modified root text"
var obj2 = c.createObject(root, { 'text': Qt.binding(function() { return this.dynamicText + ' extra text' }) })
- obj2.dynamicText = "Modified text element text"
+ obj2.dynamicText = "Modified dynamic text"
}
}
//![0]
diff --git a/src/qml/doc/src/cppintegration/definetypes.qdoc b/src/qml/doc/src/cppintegration/definetypes.qdoc
index 54ed3f1e6e..593feb49e7 100644
--- a/src/qml/doc/src/cppintegration/definetypes.qdoc
+++ b/src/qml/doc/src/cppintegration/definetypes.qdoc
@@ -195,6 +195,7 @@ be aware that properties of such a singleton type cannot be bound to.
See \l{qmlRegisterSingletonType()} for more information on how implement and
register a new singleton type, and how to use an existing singleton type.
+\note Enum values for registered types in QML should start with a capital.
\section2 Type Revisions and Versions
@@ -314,7 +315,7 @@ merged with the original target class when used from within QML. For example:
The \c leftMargin property is a new property added to an existing C++ type, \l
QLineEdit, without modifying its source code.
-The \l qmlRegisterExtendedType() function is for registering extended types.
+The \l {QQmlEngine::}{qmlRegisterExtendedType()} function is for registering extended types.
Note that it has two forms.
\code
diff --git a/src/qml/doc/src/cppintegration/exposecppattributes.qdoc b/src/qml/doc/src/cppintegration/exposecppattributes.qdoc
index e1db5c9d57..f4f688520a 100644
--- a/src/qml/doc/src/cppintegration/exposecppattributes.qdoc
+++ b/src/qml/doc/src/cppintegration/exposecppattributes.qdoc
@@ -328,11 +328,11 @@ public:
: QObject(parent), m_author(new MessageAuthor(this))
{
}
- Message *author() const {
+ MessageAuthor *author() const {
return m_author;
}
private:
- Message *m_author;
+ MessageAuthor *m_author;
};
\endcode
diff --git a/src/qml/doc/src/external-resources.qdoc b/src/qml/doc/src/external-resources.qdoc
index 202d1e4ae2..63f59bf3be 100644
--- a/src/qml/doc/src/external-resources.qdoc
+++ b/src/qml/doc/src/external-resources.qdoc
@@ -31,6 +31,11 @@
*/
/*!
+ \externalpage http://qmlbook.github.io/
+ \title Qt5 Cadaques
+*/
+
+/*!
\externalpage http://www.w3schools.com/jsref/default.asp
\title W3Schools JavaScript Reference
*/
@@ -38,4 +43,4 @@
/*!
\externalpage https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
\title Mozilla Developer Network Date Reference
-*/ \ No newline at end of file
+*/
diff --git a/src/qml/doc/src/javascript/hostenvironment.qdoc b/src/qml/doc/src/javascript/hostenvironment.qdoc
index 3b1763bd50..e613c4fcfb 100644
--- a/src/qml/doc/src/javascript/hostenvironment.qdoc
+++ b/src/qml/doc/src/javascript/hostenvironment.qdoc
@@ -71,7 +71,7 @@ Note that QML makes the following modifications to native objects:
\list
\li An \l {String::arg}{arg()} function is added to the \l String prototype.
-\li Locale-aware coversion functions are added to the \l Date and \l Number prototypes.
+\li Locale-aware conversion functions are added to the \l Date and \l Number prototypes.
\endlist
diff --git a/src/qml/doc/src/javascript/qmlglobalobject.qdoc b/src/qml/doc/src/javascript/qmlglobalobject.qdoc
index 50374f4583..b3d8a2b2a5 100644
--- a/src/qml/doc/src/javascript/qmlglobalobject.qdoc
+++ b/src/qml/doc/src/javascript/qmlglobalobject.qdoc
@@ -49,7 +49,7 @@ additional imports:
the global object of a \l QQmlEngine. For more information about this, see
\l {JavaScript Environment Restrictions}.
-\keyword XMLHttpRequest
+\target XMLHttpRequest
\section1 XMLHttpRequest
The XMLHttpRequest object, which can be used to asynchronously obtain
diff --git a/src/qml/doc/src/javascript/resources.qdoc b/src/qml/doc/src/javascript/resources.qdoc
index 51354e9bf0..b831e2ba70 100644
--- a/src/qml/doc/src/javascript/resources.qdoc
+++ b/src/qml/doc/src/javascript/resources.qdoc
@@ -57,7 +57,7 @@ parameters if they are required.
An example of a code-behind implementation resource follows:
-\qml
+\code
// MyButton.qml
import QtQuick 2.0
import "my_button_impl.js" as Logic // a new instance of this JavaScript resource is loaded for each instance of Button.qml
@@ -74,11 +74,11 @@ Rectangle {
onClicked: Logic.onClicked(rect)
}
}
-\endqml
+\endcode
-\qml
+\code
// my_button_impl.js
-var clickCount = 0; // this state is separate for each instance of MyButton
+property var clickCount = 0; // this state is separate for each instance of MyButton
function onClicked(btn) {
clickCount += 1;
if ((clickCount % 5) == 0) {
@@ -87,7 +87,7 @@ function onClicked(btn) {
obj.color = Qt.rgba(0,1,0,1);
}
}
-\endqml
+\endcode
In general, simple logic should be defined in-line in the QML file, but more
complex logic should be separated into code-behind implementation resources
@@ -138,7 +138,7 @@ within a QML document which never calls the factorial function.
For example:
-\qml
+\code
// Calculator.qml
import QtQuick 2.0
import "factorial.js" as FactorialCalculator // this JavaScript resource is only ever loaded once by the engine, even if multiple instances of Calculator.qml are created
@@ -149,7 +149,7 @@ Text {
property int input: 17
text: "The factorial of " + input + " is: " + FactorialCalculator.factorial(input)
}
-\endqml
+\endcode
As they are shared, .pragma library files cannot access QML component instance
objects or properties directly, although QML values can be passed as function
diff --git a/src/qml/doc/src/qmllanguageref/syntax/basics.qdoc b/src/qml/doc/src/qmllanguageref/syntax/basics.qdoc
index ddb307cf75..50767bfc8f 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/basics.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/basics.qdoc
@@ -73,7 +73,7 @@ Please see the \l{qtqml-syntax-imports.html}{QML Syntax - Import Statements}
documentation for in-depth information about QML imports.
-\keyword qml-object-declarations
+\target qml-object-declarations
\section1 Object Declarations
Syntactically, a block of QML code defines a tree of QML objects to be created. Objects are
diff --git a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
index a8177d29d8..c0b74c4fc6 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
@@ -564,8 +564,7 @@ list of \l {Item::children}{children}.
Default properties can be useful for reassigning the children of an item. See
the \l{TabWidget Example}, which uses a default property to
automatically reassign children of the TabWidget as children of an inner
-ListView.
-
+ListView. See also \l {Extending QML}.
\section3 Read-Only Properties
diff --git a/src/qml/doc/src/qmllanguageref/syntax/propertybinding.qdoc b/src/qml/doc/src/qmllanguageref/syntax/propertybinding.qdoc
index 3aa228c8eb..f28ff5082a 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/propertybinding.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/propertybinding.qdoc
@@ -130,7 +130,7 @@ and maintainability. It may be a good idea to redesign components that have
complex bindings, or at least factor the binding out into a separate function.
-\keyword qml-javascript-assignment
+\target qml-javascript-assignment
\section1 Creating Property Bindings from JavaScript
A property with a binding is automatically updated as necessary. However, if the
diff --git a/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc b/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc
index e7d75a89bc..602b202ed4 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc
@@ -42,7 +42,7 @@ and the signal is responded to through a \e {signal handler}. When a signal
is emitted, the corresponding signal handler is invoked. Placing logic such as scripts or other
operations in the handler allows the component to respond to the event.
-\keyword qml-signals-and-handlers
+\target qml-signals-and-handlers
\section1 Receiving Signals with Signal Handlers
To receive a notification when a particular signal is emitted for a particular object, the object definition should declare a signal handler named \e on<Signal> where \e <Signal> is the name of the signal, with the first letter capitalized. The signal handler should contain the JavaScript code to be executed when the signal handler is invoked.
@@ -208,7 +208,7 @@ SquareButton {
See \l {Signal Attributes} for more details on writing signals for custom QML types.
-\keyword qml-connect-signals-to-method
+\target qml-connect-signals-to-method
\section1 Connecting Signals to Methods and Signals
Signal objects have a \c connect() method to a connect a signal either to a
diff --git a/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc b/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc
index 780086cfc7..ffbf2282a6 100644
--- a/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc
+++ b/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc
@@ -80,7 +80,7 @@ must import that module in their QML documents.
\section1 Property Change Behavior for Basic Types
Some basic types have properties: for example, the \l font type has
-\c pixelSize, \c family and \c b properties. Unlike properties of
+\c pixelSize, \c family and \c bold properties. Unlike properties of
\l{qtqml-typesystem-topic.html#qml-object-types}{object types}, properties of
basic types do not provide their own property change signals. It is only possible
to create a property change signal handler for the basic type property itself:
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index 09e5b14c97..929726f4b7 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -241,16 +241,16 @@ void Assembler::enterStandardStackFrame(const RegisterInformation &regularRegist
subPtr(TrustedImm32(frameSize), StackPointerRegister);
Address slotAddr(StackFrameRegister, 0);
- for (int i = 0, ei = regularRegistersToSave.size(); i < ei; ++i) {
- Q_ASSERT(regularRegistersToSave.at(i).isRegularRegister());
- slotAddr.offset -= RegisterSize;
- storePtr(regularRegistersToSave.at(i).reg<RegisterID>(), slotAddr);
- }
for (int i = 0, ei = fpRegistersToSave.size(); i < ei; ++i) {
Q_ASSERT(fpRegistersToSave.at(i).isFloatingPoint());
slotAddr.offset -= sizeof(double);
JSC::MacroAssembler::storeDouble(fpRegistersToSave.at(i).reg<FPRegisterID>(), slotAddr);
}
+ for (int i = 0, ei = regularRegistersToSave.size(); i < ei; ++i) {
+ Q_ASSERT(regularRegistersToSave.at(i).isRegularRegister());
+ slotAddr.offset -= RegisterSize;
+ storePtr(regularRegistersToSave.at(i).reg<RegisterID>(), slotAddr);
+ }
}
void Assembler::leaveStandardStackFrame(const RegisterInformation &regularRegistersToSave,
@@ -259,16 +259,16 @@ void Assembler::leaveStandardStackFrame(const RegisterInformation &regularRegist
Address slotAddr(StackFrameRegister, -regularRegistersToSave.size() * RegisterSize - fpRegistersToSave.size() * sizeof(double));
// restore the callee saved registers
- for (int i = fpRegistersToSave.size() - 1; i >= 0; --i) {
- Q_ASSERT(fpRegistersToSave.at(i).isFloatingPoint());
- JSC::MacroAssembler::loadDouble(slotAddr, fpRegistersToSave.at(i).reg<FPRegisterID>());
- slotAddr.offset += sizeof(double);
- }
for (int i = regularRegistersToSave.size() - 1; i >= 0; --i) {
Q_ASSERT(regularRegistersToSave.at(i).isRegularRegister());
loadPtr(slotAddr, regularRegistersToSave.at(i).reg<RegisterID>());
slotAddr.offset += RegisterSize;
}
+ for (int i = fpRegistersToSave.size() - 1; i >= 0; --i) {
+ Q_ASSERT(fpRegistersToSave.at(i).isFloatingPoint());
+ JSC::MacroAssembler::loadDouble(slotAddr, fpRegistersToSave.at(i).reg<FPRegisterID>());
+ slotAddr.offset += sizeof(double);
+ }
Q_ASSERT(slotAddr.offset == 0);
@@ -327,13 +327,13 @@ Assembler::Jump Assembler::genTryDoubleConversion(IR::Expr *src, Assembler::FPRe
// check if it's an int32:
Assembler::Jump isNoInt = branch32(Assembler::NotEqual, Assembler::ScratchRegister,
- Assembler::TrustedImm32(Value::_Integer_Type));
+ Assembler::TrustedImm32(Value::Integer_Type_Internal));
convertInt32ToDouble(toInt32Register(src, Assembler::ScratchRegister), dest);
Assembler::Jump intDone = jump();
// not an int, check if it's a double:
isNoInt.link(this);
-#if QT_POINTER_SIZE == 8
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
and32(Assembler::TrustedImm32(Value::IsDouble_Mask), Assembler::ScratchRegister);
Assembler::Jump isNoDbl = branch32(Assembler::Equal, Assembler::ScratchRegister,
Assembler::TrustedImm32(0));
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index 3b65acb26c..532a3114f2 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -33,6 +33,17 @@
#ifndef QV4ASSEMBLER_P_H
#define QV4ASSEMBLER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "private/qv4global_p.h"
#include "private/qv4jsir_p.h"
#include "private/qv4isel_p.h"
@@ -478,7 +489,7 @@ public:
load64(addr, dest);
} else {
QV4::Value undefined = QV4::Primitive::undefinedValue();
- move(TrustedImm64(undefined.val), dest);
+ move(TrustedImm64(undefined.rawValue()), dest);
}
}
@@ -491,7 +502,7 @@ public:
load64(addr, dest);
} else {
QV4::Value undefined = QV4::Primitive::undefinedValue();
- move(TrustedImm64(undefined.val), dest);
+ move(TrustedImm64(undefined.rawValue()), dest);
}
}
@@ -500,7 +511,7 @@ public:
Q_UNUSED(argumentNumber);
QV4::Value v = convertToValue(c);
- move(TrustedImm64(v.val), dest);
+ move(TrustedImm64(v.rawValue()), dest);
}
void loadArgumentInRegister(IR::Expr* expr, RegisterID dest, int argumentNumber)
@@ -509,7 +520,7 @@ public:
if (!expr) {
QV4::Value undefined = QV4::Primitive::undefinedValue();
- move(TrustedImm64(undefined.val), dest);
+ move(TrustedImm64(undefined.rawValue()), dest);
} else if (IR::Temp *t = expr->asTemp()){
loadArgumentInRegister(t, dest, argumentNumber);
} else if (IR::ArgLocal *al = expr->asArgLocal()) {
@@ -565,6 +576,8 @@ public:
moveIntsToDouble(JSC::ARMRegisters::r0, JSC::ARMRegisters::r1, dest, FPGpr0);
#elif defined(Q_PROCESSOR_X86)
moveIntsToDouble(JSC::X86Registers::eax, JSC::X86Registers::edx, dest, FPGpr0);
+#elif defined(Q_PROCESSOR_MIPS)
+ moveIntsToDouble(JSC::MIPSRegisters::v0, JSC::MIPSRegisters::v1, dest, FPGpr0);
#else
subPtr(TrustedImm32(sizeof(QV4::Value)), StackPointerRegister);
Pointer tmp(StackPointerRegister, 0);
@@ -595,6 +608,14 @@ public:
destination.offset += 4;
store32(JSC::ARMRegisters::r1, destination);
}
+#elif defined(Q_PROCESSOR_MIPS)
+ void storeReturnValue(const Pointer &dest)
+ {
+ Pointer destination = dest;
+ store32(JSC::MIPSRegisters::v0, destination);
+ destination.offset += 4;
+ store32(JSC::MIPSRegisters::v1, destination);
+ }
#endif
void storeReturnValue(IR::Expr *target)
@@ -724,7 +745,7 @@ public:
moveDouble(source, (FPRegisterID) targetTemp->index);
return;
}
-#if QT_POINTER_SIZE == 8
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
moveDoubleTo64(source, ReturnValueRegister);
move(TrustedImm64(QV4::Value::NaNEncodeMask), ScratchRegister);
xor64(ScratchRegister, ReturnValueRegister);
@@ -735,7 +756,7 @@ public:
storeDouble(source, ptr);
#endif
}
-#if QT_POINTER_SIZE == 8
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
// We need to (de)mangle the double
void loadDouble(Address addr, FPRegisterID dest)
{
@@ -781,11 +802,11 @@ public:
void storeValue(QV4::Primitive value, Address destination)
{
#ifdef VALUE_FITS_IN_REGISTER
- store64(TrustedImm64(value.val), destination);
+ store64(TrustedImm64(value.rawValue()), destination);
#else
- store32(TrustedImm32(value.int_32), destination);
+ store32(TrustedImm32(value.int_32()), destination);
destination.offset += 4;
- store32(TrustedImm32(value.tag), destination);
+ store32(TrustedImm32(value.tag()), destination);
#endif
}
@@ -820,6 +841,8 @@ public:
else
#if OS(WINDOWS) && CPU(X86_64)
loadArgumentOnStack<argumentNumber>(value, argumentNumber);
+#elif CPU(MIPS) // Stack space for 4 arguments needs to be allocated for MIPS platforms.
+ loadArgumentOnStack<argumentNumber>(value, argumentNumber + 4);
#else // Sanity:
loadArgumentOnStack<argumentNumber - RegisterArgumentCount>(value, argumentNumber);
#endif
@@ -846,7 +869,7 @@ public:
template <int ArgumentIndex, typename Parameter>
struct SizeOnStack
{
- enum { Size = Select<ArgumentIndex >= RegisterArgumentCount, QT_POINTER_SIZE, 0>::Chosen };
+ enum { Size = Select<ArgumentIndex >= RegisterArgumentCount, sizeof(void*), 0>::Chosen };
};
template <int ArgumentIndex>
@@ -945,8 +968,8 @@ public:
tagAddr.offset += 4;
QV4::Primitive v = convertToValue(c);
- store32(TrustedImm32(v.int_32), addr);
- store32(TrustedImm32(v.tag), tagAddr);
+ store32(TrustedImm32(v.int_32()), addr);
+ store32(TrustedImm32(v.tag()), tagAddr);
return Pointer(addr);
}
@@ -961,7 +984,7 @@ public:
{
store32(reg, addr);
addr.offset += 4;
- store32(TrustedImm32(QV4::Primitive::fromBoolean(0).tag), addr);
+ store32(TrustedImm32(QV4::Primitive::fromBoolean(0).tag()), addr);
}
void storeBool(RegisterID src, RegisterID dest)
@@ -1005,7 +1028,7 @@ public:
{
store32(reg, addr);
addr.offset += 4;
- store32(TrustedImm32(QV4::Primitive::fromInt32(0).tag), addr);
+ store32(TrustedImm32(QV4::Primitive::fromInt32(0).tag()), addr);
}
void storeInt32(RegisterID reg, IR::Expr *target)
@@ -1054,7 +1077,7 @@ public:
FPRegisterID toDoubleRegister(IR::Expr *e, FPRegisterID target = FPGpr0)
{
if (IR::Const *c = e->asConst()) {
-#if QT_POINTER_SIZE == 8
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
union {
double d;
int64_t i;
@@ -1084,7 +1107,7 @@ public:
RegisterID toInt32Register(IR::Expr *e, RegisterID scratchReg)
{
if (IR::Const *c = e->asConst()) {
- move(TrustedImm32(convertToValue(c).int_32), scratchReg);
+ move(TrustedImm32(convertToValue(c).int_32()), scratchReg);
return scratchReg;
}
@@ -1123,7 +1146,7 @@ public:
Pointer tagAddr = addr;
tagAddr.offset += 4;
load32(tagAddr, scratchReg);
- Jump inIntRange = branch32(Equal, scratchReg, TrustedImm32(QV4::Value::_Integer_Type));
+ Jump inIntRange = branch32(Equal, scratchReg, TrustedImm32(QV4::Value::Integer_Type_Internal));
// it's not in signed int range, so load it as a double, and truncate it down
loadDouble(addr, FPGpr0);
diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp
index c6c8023cd7..8b051fcb3d 100644
--- a/src/qml/jit/qv4binop.cpp
+++ b/src/qml/jit/qv4binop.cpp
@@ -352,7 +352,9 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
}
}
- if (op == IR::OpSub) {
+ // Special cases:
+ switch (op) {
+ case IR::OpSub:
if (rightSource->asTemp() && rightSource->asTemp()->kind == IR::Temp::PhysicalRegister
&& targetTemp
&& targetTemp->kind == IR::Temp::PhysicalRegister
@@ -368,11 +370,27 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
}
as->storeInt32(targetReg, target);
return true;
+
+ case IR::OpLShift:
+ case IR::OpRShift:
+ case IR::OpURShift:
+ if (IR::Const *c = rightSource->asConst()) {
+ if ((QV4::Primitive::toUInt32(c->value) & 0x1f) == 0) {
+ Assembler::RegisterID r = as->toInt32Register(leftSource, targetReg);
+ as->storeInt32(r, target);
+ return true;
+ }
+ }
+ break;
+
+ default:
+ break;
}
Assembler::RegisterID l = as->toInt32Register(leftSource, targetReg);
if (IR::Const *c = rightSource->asConst()) { // All cases of Y = X op Const
Assembler::TrustedImm32 r(int(c->value));
+ Assembler::TrustedImm32 ur(QV4::Primitive::toUInt32(c->value) & 0x1f);
switch (op) {
case IR::OpBitAnd: as->and32(r, l, targetReg); break;
@@ -381,9 +399,9 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
case IR::OpAdd: as->add32(r, l, targetReg); break;
case IR::OpMul: as->mul32(r, l, targetReg); break;
- case IR::OpLShift: r.m_value &= 0x1f; as->lshift32(l, r, targetReg); break;
- case IR::OpRShift: r.m_value &= 0x1f; as->rshift32(l, r, targetReg); break;
- case IR::OpURShift: r.m_value &= 0x1f; as->urshift32(l, r, targetReg);
+ case IR::OpLShift: as->lshift32(l, ur, targetReg); break;
+ case IR::OpRShift: as->rshift32(l, ur, targetReg); break;
+ case IR::OpURShift: as->urshift32(l, ur, targetReg);
as->storeUInt32(targetReg, target); // IMPORTANT: do NOT do a break here! The stored type of an urshift is different from the other binary operations!
return true;
@@ -415,32 +433,33 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
case IR::OpAdd: as->add32(l, r, targetReg); break;
case IR::OpMul: as->mul32(l, r, targetReg); break;
-#if CPU(ARM) || CPU(X86) || CPU(X86_64)
- // The ARM assembler will generate an and with 0x1f for us, and Intel will do it on the CPU.
-
+#if CPU(X86) || CPU(X86_64)
+ // Intel does the & 0x1f on the CPU, so:
case IR::OpLShift: as->lshift32(l, r, targetReg); break;
case IR::OpRShift: as->rshift32(l, r, targetReg); break;
case IR::OpURShift: as->urshift32(l, r, targetReg);
as->storeUInt32(targetReg, target); // IMPORTANT: do NOT do a break here! The stored type of an urshift is different from the other binary operations!
return true;
#else
- case IR::OpLShift:
- as->move(r, Assembler::ScratchRegister);
- as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister);
- as->lshift32(l, Assembler::ScratchRegister, targetReg);
- break;
-
- case IR::OpRShift:
- as->move(r, Assembler::ScratchRegister);
- as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister);
- as->rshift32(l, Assembler::ScratchRegister, targetReg);
- break;
-
+ // Not all CPUs accept shifts over more than 31 bits, and some CPUs (like ARM) will do
+ // surprising stuff when shifting over 0 bits.
+#define CHECK_RHS(op) { \
+ as->and32(Assembler::TrustedImm32(0x1f), r, Assembler::ScratchRegister); \
+ Assembler::Jump notZero = as->branch32(Assembler::NotEqual, Assembler::ScratchRegister, Assembler::TrustedImm32(0)); \
+ as->move(l, targetReg); \
+ Assembler::Jump done = as->jump(); \
+ notZero.link(as); \
+ op; \
+ done.link(as); \
+}
+ case IR::OpLShift: CHECK_RHS(as->lshift32(l, Assembler::ScratchRegister, targetReg)); break;
+ case IR::OpRShift: CHECK_RHS(as->rshift32(l, Assembler::ScratchRegister, targetReg)); break;
case IR::OpURShift:
- as->move(r, Assembler::ScratchRegister);
- as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister);
- as->storeUInt32(targetReg, target); // IMPORTANT: do NOT do a break here! The stored type of an urshift is different from the other binary operations!
+ CHECK_RHS(as->urshift32(l, Assembler::ScratchRegister, targetReg));
+ as->storeUInt32(targetReg, target);
+ // IMPORTANT: do NOT do a break here! The stored type of an urshift is different from the other binary operations!
return true;
+#undef CHECK_RHS
#endif
case IR::OpSub: // already handled before
diff --git a/src/qml/jit/qv4binop_p.h b/src/qml/jit/qv4binop_p.h
index 4fa2369312..96c8281d57 100644
--- a/src/qml/jit/qv4binop_p.h
+++ b/src/qml/jit/qv4binop_p.h
@@ -33,6 +33,17 @@
#ifndef QV4BINOP_P_H
#define QV4BINOP_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qv4jsir_p.h>
#include <qv4isel_masm_p.h>
#include <qv4assembler_p.h>
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index da511cd1eb..b6df5fb08c 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -45,6 +45,7 @@
#include "qv4binop_p.h"
#include <QtCore/QBuffer>
+#include <QtCore/QCoreApplication>
#include <assembler/LinkBuffer.h>
#include <WTFStubs.h>
@@ -120,6 +121,19 @@ static void printDisassembledOutputWithCalls(QByteArray processedOutput, const Q
qDebug("%s", processedOutput.constData());
}
+#if defined(Q_OS_LINUX)
+static FILE *pmap;
+
+static void qt_closePmap()
+{
+ if (pmap) {
+ fclose(pmap);
+ pmap = 0;
+ }
+}
+
+#endif
+
JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
{
Label endOfCode = label();
@@ -167,19 +181,21 @@ JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
*codeSize = linkBuffer.offsetOf(endOfCode);
+ QByteArray name;
+
JSC::MacroAssemblerCodeRef codeRef;
- static bool showCode = !qgetenv("QV4_SHOW_ASM").isNull();
+ static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_ASM");
if (showCode) {
QBuffer buf;
buf.open(QIODevice::WriteOnly);
WTF::setDataFile(new QIODevicePrintStream(&buf));
- QByteArray name = _function->name->toUtf8();
+ name = _function->name->toUtf8();
if (name.isEmpty()) {
name = QByteArray::number(quintptr(_function), 16);
name.prepend("IR::Function(0x");
- name.append(")");
+ name.append(')');
}
codeRef = linkBuffer.finalizeCodeWithDisassembly("%s", name.data());
@@ -189,6 +205,50 @@ JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
codeRef = linkBuffer.finalizeCodeWithoutDisassembly();
}
+#if defined(Q_OS_LINUX)
+ // This implements writing of JIT'd addresses so that perf can find the
+ // symbol names.
+ //
+ // Perf expects the mapping to be in a certain place and have certain
+ // content, for more information, see:
+ // https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/jit-interface.txt
+ static bool doProfile = !qEnvironmentVariableIsEmpty("QV4_PROFILE_WRITE_PERF_MAP");
+ static bool profileInitialized = false;
+ if (doProfile && !profileInitialized) {
+ profileInitialized = true;
+
+ char pname[PATH_MAX];
+ snprintf(pname, PATH_MAX - 1, "/tmp/perf-%lu.map",
+ (unsigned long)QCoreApplication::applicationPid());
+
+ pmap = fopen(pname, "w");
+ if (!pmap)
+ qWarning("QV4: Can't write %s, call stacks will not contain JavaScript function names", pname);
+
+ // make sure we clean up nicely
+ std::atexit(qt_closePmap);
+ }
+
+ if (pmap) {
+ // this may have been pre-populated, if QV4_SHOW_ASM was on
+ if (name.isEmpty()) {
+ name = _function->name->toUtf8();
+ if (name.isEmpty()) {
+ name = QByteArray::number(quintptr(_function), 16);
+ name.prepend("IR::Function(0x");
+ name.append(')');
+ }
+ }
+
+ fprintf(pmap, "%llx %x %.*s\n",
+ (long long unsigned int)codeRef.code().executableAddress(),
+ *codeSize,
+ name.length(),
+ name.constData());
+ fflush(pmap);
+ }
+#endif
+
return codeRef;
}
@@ -215,7 +275,7 @@ void InstructionSelection::run(int functionIndex)
IR::Optimizer opt(_function);
opt.run(qmlEngine);
- static const bool withRegisterAllocator = qgetenv("QV4_NO_REGALLOC").isEmpty();
+ static const bool withRegisterAllocator = qEnvironmentVariableIsEmpty("QV4_NO_REGALLOC");
if (Assembler::RegAllocIsSupported && opt.isInSSA() && withRegisterAllocator) {
RegisterAllocator regalloc(Assembler::getRegisterInfo());
regalloc.run(_function, opt);
@@ -317,7 +377,7 @@ const void *InstructionSelection::addConstantTable(QVector<Primitive> *values)
QQmlRefPointer<QV4::CompiledData::CompilationUnit> InstructionSelection::backendCompileStep()
{
QQmlRefPointer<QV4::CompiledData::CompilationUnit> result;
- result.take(compilationUnit.take());
+ result.adopt(compilationUnit.take());
return result;
}
@@ -339,6 +399,23 @@ void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args
}
}
+void InstructionSelection::callBuiltinTypeofQmlContextProperty(IR::Expr *base,
+ IR::Member::MemberKind kind,
+ int propertyIndex, IR::Expr *result)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject) {
+ generateFunctionCall(result, Runtime::typeofScopeObjectProperty, Assembler::EngineRegister,
+ Assembler::PointerToValue(base),
+ Assembler::TrustedImm32(propertyIndex));
+ } else if (kind == IR::Member::MemberOfQmlContextObject) {
+ generateFunctionCall(result, Runtime::typeofContextObjectProperty,
+ Assembler::EngineRegister, Assembler::PointerToValue(base),
+ Assembler::TrustedImm32(propertyIndex));
+ } else {
+ Q_UNREACHABLE();
+ }
+}
+
void InstructionSelection::callBuiltinTypeofMember(IR::Expr *base, const QString &name,
IR::Expr *result)
{
@@ -574,9 +651,9 @@ void InstructionSelection::loadThisObject(IR::Expr *temp)
#endif
}
-void InstructionSelection::loadQmlIdArray(IR::Expr *temp)
+void InstructionSelection::loadQmlContext(IR::Expr *temp)
{
- generateFunctionCall(temp, Runtime::getQmlIdArray, Assembler::EngineRegister);
+ generateFunctionCall(temp, Runtime::getQmlContext, Assembler::EngineRegister);
}
void InstructionSelection::loadQmlImportedScripts(IR::Expr *temp)
@@ -584,16 +661,6 @@ void InstructionSelection::loadQmlImportedScripts(IR::Expr *temp)
generateFunctionCall(temp, Runtime::getQmlImportedScripts, Assembler::EngineRegister);
}
-void InstructionSelection::loadQmlContextObject(IR::Expr *temp)
-{
- generateFunctionCall(temp, Runtime::getQmlContextObject, Assembler::EngineRegister);
-}
-
-void InstructionSelection::loadQmlScopeObject(IR::Expr *temp)
-{
- generateFunctionCall(temp, Runtime::getQmlScopeObject, Assembler::EngineRegister);
-}
-
void InstructionSelection::loadQmlSingleton(const QString &name, IR::Expr *temp)
{
generateFunctionCall(temp, Runtime::getQmlSingleton, Assembler::EngineRegister, Assembler::StringToIndex(name));
@@ -614,7 +681,7 @@ void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Expr *target)
_as->toUInt32Register(sourceConst, (Assembler::RegisterID) targetTemp->index);
} else if (targetTemp->type == IR::BoolType) {
Q_ASSERT(sourceConst->type == IR::BoolType);
- _as->move(Assembler::TrustedImm32(convertToValue(sourceConst).int_32),
+ _as->move(Assembler::TrustedImm32(convertToValue(sourceConst).int_32()),
(Assembler::RegisterID) targetTemp->index);
} else {
Q_UNREACHABLE();
@@ -631,7 +698,7 @@ void InstructionSelection::loadString(const QString &str, IR::Expr *target)
Pointer srcAddr = _as->loadStringAddress(Assembler::ReturnValueRegister, str);
_as->loadPtr(srcAddr, Assembler::ReturnValueRegister);
Pointer destAddr = _as->loadAddress(Assembler::ScratchRegister, target);
-#if QT_POINTER_SIZE == 8
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
_as->store64(Assembler::ReturnValueRegister, destAddr);
#else
_as->store32(Assembler::ReturnValueRegister, destAddr);
@@ -680,6 +747,18 @@ void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::
}
}
+void InstructionSelection::getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int index, IR::Expr *target)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject)
+ generateFunctionCall(target, Runtime::getQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index));
+ else if (kind == IR::Member::MemberOfQmlContextObject)
+ generateFunctionCall(target, Runtime::getQmlContextObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index));
+ else if (kind == IR::Member::MemberOfIdObjectsArray)
+ generateFunctionCall(target, Runtime::getQmlIdObject, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index));
+ else
+ Q_ASSERT(false);
+}
+
void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target)
{
if (attachedPropertiesId != 0)
@@ -708,6 +787,18 @@ void InstructionSelection::setProperty(IR::Expr *source, IR::Expr *targetBase,
}
}
+void InstructionSelection::setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex)
+{
+ if (kind == IR::Member::MemberOfQmlScopeObject)
+ generateFunctionCall(Assembler::Void, Runtime::setQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase),
+ Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source));
+ else if (kind == IR::Member::MemberOfQmlContextObject)
+ generateFunctionCall(Assembler::Void, Runtime::setQmlContextObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase),
+ Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source));
+ else
+ Q_ASSERT(false);
+}
+
void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex)
{
generateFunctionCall(Assembler::Void, Runtime::setQmlQObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase),
@@ -868,10 +959,10 @@ void InstructionSelection::swapValues(IR::Expr *source, IR::Expr *target)
quint32 tag;
switch (regTemp->type) {
case IR::BoolType:
- tag = QV4::Value::_Boolean_Type;
+ tag = QV4::Value::Boolean_Type_Internal;
break;
case IR::SInt32Type:
- tag = QV4::Value::_Integer_Type;
+ tag = QV4::Value::Integer_Type_Internal;
break;
default:
tag = QV4::Value::Undefined_Type;
@@ -901,6 +992,24 @@ void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr
binop.generate(leftSource, rightSource, target);
}
+void InstructionSelection::callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result)
+{
+ prepareCallData(args, base);
+
+ if (kind == IR::Member::MemberOfQmlScopeObject)
+ generateFunctionCall(result, Runtime::callQmlScopeObjectProperty,
+ Assembler::EngineRegister,
+ Assembler::TrustedImm32(propertyIndex),
+ baseAddressForCallData());
+ else if (kind == IR::Member::MemberOfQmlContextObject)
+ generateFunctionCall(result, Runtime::callQmlContextObjectProperty,
+ Assembler::EngineRegister,
+ Assembler::TrustedImm32(propertyIndex),
+ baseAddressForCallData());
+ else
+ Q_ASSERT(false);
+}
+
void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
IR::Expr *result)
{
@@ -987,13 +1096,13 @@ void InstructionSelection::convertTypeToDouble(IR::Expr *source, IR::Expr *targe
// check if it's an int32:
Assembler::Jump isNoInt = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
- Assembler::TrustedImm32(Value::_Integer_Type));
+ Assembler::TrustedImm32(Value::Integer_Type_Internal));
convertIntToDouble(source, target);
Assembler::Jump intDone = _as->jump();
// not an int, check if it's NOT a double:
isNoInt.link(_as);
-#if QT_POINTER_SIZE == 8
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
_as->and32(Assembler::TrustedImm32(Value::IsDouble_Mask), Assembler::ScratchRegister);
Assembler::Jump isDbl = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
Assembler::TrustedImm32(0));
@@ -1011,7 +1120,7 @@ void InstructionSelection::convertTypeToDouble(IR::Expr *source, IR::Expr *targe
Assembler::Pointer addr2 = _as->loadAddress(Assembler::ScratchRegister, source);
IR::Temp *targetTemp = target->asTemp();
if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
-#if QT_POINTER_SIZE == 8
+#if Q_PROCESSOR_WORDSIZE == 8
_as->load64(addr2, Assembler::ScratchRegister);
_as->store64(Assembler::ScratchRegister, _as->loadAddress(Assembler::ReturnValueRegister, target));
#else
@@ -1080,7 +1189,7 @@ void InstructionSelection::convertTypeToSInt32(IR::Expr *source, IR::Expr *targe
switch (source->type) {
case IR::VarType: {
-#if QT_POINTER_SIZE == 8
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
Assembler::Pointer addr = _as->loadAddress(Assembler::ScratchRegister, source);
_as->load64(addr, Assembler::ScratchRegister);
_as->move(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
@@ -1110,7 +1219,7 @@ void InstructionSelection::convertTypeToSInt32(IR::Expr *source, IR::Expr *targe
Assembler::Pointer targetAddr = _as->loadAddress(Assembler::ScratchRegister, target);
_as->store32(Assembler::ReturnValueRegister, targetAddr);
targetAddr.offset += 4;
- _as->store32(Assembler::TrustedImm32(Value::_Integer_Type), targetAddr);
+ _as->store32(Assembler::TrustedImm32(Value::Integer_Type_Internal), targetAddr);
} else {
_as->storeInt32(Assembler::ReturnValueRegister, target);
}
@@ -1123,14 +1232,14 @@ void InstructionSelection::convertTypeToSInt32(IR::Expr *source, IR::Expr *targe
// check if it's an int32:
Assembler::Jump fallback = _as->branch32(Assembler::NotEqual, Assembler::ReturnValueRegister,
- Assembler::TrustedImm32(Value::_Integer_Type));
+ Assembler::TrustedImm32(Value::Integer_Type_Internal));
IR::Temp *targetTemp = target->asTemp();
if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
_as->load32(addr, Assembler::ReturnValueRegister);
Assembler::Pointer targetAddr = _as->loadAddress(Assembler::ScratchRegister, target);
_as->store32(Assembler::ReturnValueRegister, targetAddr);
targetAddr.offset += 4;
- _as->store32(Assembler::TrustedImm32(Value::_Integer_Type), targetAddr);
+ _as->store32(Assembler::TrustedImm32(Value::Integer_Type_Internal), targetAddr);
} else {
_as->load32(addr, (Assembler::RegisterID) targetTemp->index);
}
@@ -1187,7 +1296,7 @@ void InstructionSelection::convertTypeToUInt32(IR::Expr *source, IR::Expr *targe
// check if it's an int32:
Assembler::Jump isNoInt = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
- Assembler::TrustedImm32(Value::_Integer_Type));
+ Assembler::TrustedImm32(Value::Integer_Type_Internal));
Assembler::Pointer addr = _as->loadAddress(Assembler::ScratchRegister, source);
_as->storeUInt32(_as->toInt32Register(addr, Assembler::ScratchRegister), target);
Assembler::Jump intDone = _as->jump();
@@ -1297,11 +1406,11 @@ void InstructionSelection::visitCJump(IR::CJump *s)
} else {
Address temp = _as->loadAddress(Assembler::ScratchRegister, s->cond);
Address tag = temp;
- tag.offset += qOffsetOf(QV4::Value, tag);
+ tag.offset += QV4::Value::tagOffset();
Assembler::Jump booleanConversion = _as->branch32(Assembler::NotEqual, tag, Assembler::TrustedImm32(QV4::Value::Boolean_Type));
Address data = temp;
- data.offset += qOffsetOf(QV4::Value, int_32);
+ data.offset += QV4::Value::valueOffset();
_as->load32(data, Assembler::ReturnValueRegister);
Assembler::Jump testBoolean = _as->jump();
@@ -1383,11 +1492,14 @@ void InstructionSelection::visitRet(IR::Ret *s)
// this only happens if the method doesn't have a return statement and can
// only exit through an exception
} else if (IR::Temp *t = s->expr->asTemp()) {
-#if CPU(X86) || CPU(ARM)
+#if CPU(X86) || CPU(ARM) || CPU(MIPS)
# if CPU(X86)
Assembler::RegisterID lowReg = JSC::X86Registers::eax;
Assembler::RegisterID highReg = JSC::X86Registers::edx;
+# elif CPU(MIPS)
+ Assembler::RegisterID lowReg = JSC::MIPSRegisters::v0;
+ Assembler::RegisterID highReg = JSC::MIPSRegisters::v1;
# else // CPU(ARM)
Assembler::RegisterID lowReg = JSC::ARMRegisters::r0;
Assembler::RegisterID highReg = JSC::ARMRegisters::r1;
@@ -1406,16 +1518,16 @@ void InstructionSelection::visitRet(IR::Ret *s)
Assembler::Jump done = _as->jump();
intRange.link(_as);
_as->move(srcReg, lowReg);
- _as->move(Assembler::TrustedImm32(QV4::Value::_Integer_Type), highReg);
+ _as->move(Assembler::TrustedImm32(QV4::Value::Integer_Type_Internal), highReg);
done.link(_as);
} break;
case IR::SInt32Type:
_as->move((Assembler::RegisterID) t->index, lowReg);
- _as->move(Assembler::TrustedImm32(QV4::Value::_Integer_Type), highReg);
+ _as->move(Assembler::TrustedImm32(QV4::Value::Integer_Type_Internal), highReg);
break;
case IR::BoolType:
_as->move((Assembler::RegisterID) t->index, lowReg);
- _as->move(Assembler::TrustedImm32(QV4::Value::_Boolean_Type), highReg);
+ _as->move(Assembler::TrustedImm32(QV4::Value::Boolean_Type_Internal), highReg);
break;
default:
Q_UNREACHABLE();
@@ -1444,7 +1556,7 @@ void InstructionSelection::visitRet(IR::Ret *s)
Assembler::Jump done = _as->jump();
intRange.link(_as);
_as->zeroExtend32ToPtr(srcReg, Assembler::ReturnValueRegister);
- quint64 tag = QV4::Value::_Integer_Type;
+ quint64 tag = QV4::Value::Integer_Type_Internal;
_as->or64(Assembler::TrustedImm64(tag << 32),
Assembler::ReturnValueRegister);
done.link(_as);
@@ -1453,10 +1565,10 @@ void InstructionSelection::visitRet(IR::Ret *s)
quint64 tag;
switch (t->type) {
case IR::SInt32Type:
- tag = QV4::Value::_Integer_Type;
+ tag = QV4::Value::Integer_Type_Internal;
break;
case IR::BoolType:
- tag = QV4::Value::_Boolean_Type;
+ tag = QV4::Value::Boolean_Type_Internal;
break;
default:
tag = QV4::Value::Undefined_Type;
@@ -1472,13 +1584,16 @@ void InstructionSelection::visitRet(IR::Ret *s)
} else if (IR::Const *c = s->expr->asConst()) {
QV4::Primitive retVal = convertToValue(c);
#if CPU(X86)
- _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::X86Registers::eax);
- _as->move(Assembler::TrustedImm32(retVal.tag), JSC::X86Registers::edx);
+ _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::X86Registers::eax);
+ _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::X86Registers::edx);
#elif CPU(ARM)
- _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::ARMRegisters::r0);
- _as->move(Assembler::TrustedImm32(retVal.tag), JSC::ARMRegisters::r1);
+ _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::ARMRegisters::r0);
+ _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::ARMRegisters::r1);
+#elif CPU(MIPS)
+ _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::MIPSRegisters::v0);
+ _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::MIPSRegisters::v1);
#else
- _as->move(Assembler::TrustedImm64(retVal.val), Assembler::ReturnValueRegister);
+ _as->move(Assembler::TrustedImm64(retVal.rawValue()), Assembler::ReturnValueRegister);
#endif
} else {
Q_UNREACHABLE();
@@ -1499,13 +1614,16 @@ void InstructionSelection::visitRet(IR::Ret *s)
_as->exceptionReturnLabel = _as->label();
QV4::Primitive retVal = Primitive::undefinedValue();
#if CPU(X86)
- _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::X86Registers::eax);
- _as->move(Assembler::TrustedImm32(retVal.tag), JSC::X86Registers::edx);
+ _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::X86Registers::eax);
+ _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::X86Registers::edx);
#elif CPU(ARM)
- _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::ARMRegisters::r0);
- _as->move(Assembler::TrustedImm32(retVal.tag), JSC::ARMRegisters::r1);
+ _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::ARMRegisters::r0);
+ _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::ARMRegisters::r1);
+#elif CPU(MIPS)
+ _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::MIPSRegisters::v0);
+ _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::MIPSRegisters::v1);
#else
- _as->move(Assembler::TrustedImm64(retVal.val), Assembler::ReturnValueRegister);
+ _as->move(Assembler::TrustedImm64(retVal.rawValue()), Assembler::ReturnValueRegister);
#endif
_as->jump(leaveStackFrame);
}
@@ -1539,7 +1657,7 @@ int InstructionSelection::prepareCallData(IR::ExprList* args, IR::Expr *thisObje
}
Pointer p = _as->stackLayout().callDataAddress(qOffsetOf(CallData, tag));
- _as->store32(Assembler::TrustedImm32(QV4::Value::_Integer_Type), p);
+ _as->store32(Assembler::TrustedImm32(QV4::Value::Integer_Type_Internal), p);
p = _as->stackLayout().callDataAddress(qOffsetOf(CallData, argc));
_as->store32(Assembler::TrustedImm32(argc), p);
p = _as->stackLayout().callDataAddress(qOffsetOf(CallData, thisObject));
@@ -1718,7 +1836,7 @@ bool InstructionSelection::visitCJumpStrictNullUndefined(IR::Type nullOrUndef, I
Assembler::RelationalCondition cond = binop->op == IR::OpStrictEqual ? Assembler::Equal
: Assembler::NotEqual;
- const Assembler::TrustedImm32 tag(nullOrUndef == IR::NullType ? int(QV4::Value::_Null_Type)
+ const Assembler::TrustedImm32 tag(nullOrUndef == IR::NullType ? int(QV4::Value::Null_Type_Internal)
: int(QV4::Value::Undefined_Type));
_as->generateCJumpOnCompare(cond, tagReg, tag, _block, trueBlock, falseBlock);
return true;
@@ -1760,7 +1878,7 @@ bool InstructionSelection::visitCJumpStrictBool(IR::Binop *binop, IR::BasicBlock
// check if the tag of the var operand is indicates 'boolean'
_as->load32(otherAddr, Assembler::ScratchRegister);
Assembler::Jump noBool = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
- Assembler::TrustedImm32(QV4::Value::_Boolean_Type));
+ Assembler::TrustedImm32(QV4::Value::Boolean_Type_Internal));
if (binop->op == IR::OpStrictEqual)
_as->addPatch(falseBlock, noBool);
else
@@ -1809,7 +1927,7 @@ bool InstructionSelection::visitCJumpNullUndefined(IR::Type nullOrUndef, IR::Bin
if (binop->op == IR::OpNotEqual)
qSwap(trueBlock, falseBlock);
- Assembler::Jump isNull = _as->branch32(Assembler::Equal, tagReg, Assembler::TrustedImm32(int(QV4::Value::_Null_Type)));
+ Assembler::Jump isNull = _as->branch32(Assembler::Equal, tagReg, Assembler::TrustedImm32(int(QV4::Value::Null_Type_Internal)));
Assembler::Jump isUndefined = _as->branch32(Assembler::Equal, tagReg, Assembler::TrustedImm32(int(QV4::Value::Undefined_Type)));
_as->addPatch(trueBlock, isNull);
_as->addPatch(trueBlock, isUndefined);
diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h
index 87b4a20bfc..6e9b02b034 100644
--- a/src/qml/jit/qv4isel_masm_p.h
+++ b/src/qml/jit/qv4isel_masm_p.h
@@ -33,6 +33,17 @@
#ifndef QV4ISEL_MASM_P_H
#define QV4ISEL_MASM_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "private/qv4global_p.h"
#include "private/qv4jsir_p.h"
#include "private/qv4isel_p.h"
@@ -69,6 +80,7 @@ protected:
virtual QQmlRefPointer<QV4::CompiledData::CompilationUnit> backendCompileStep();
virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result);
+ virtual void callBuiltinTypeofQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::Expr *result);
virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Expr *result);
virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result);
virtual void callBuiltinTypeofName(const QString &name, IR::Expr *result);
@@ -91,14 +103,13 @@ protected:
virtual void callBuiltinSetupArgumentObject(IR::Expr *result);
virtual void callBuiltinConvertThisToObject();
virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result);
+ virtual void callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result);
virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result);
virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result);
virtual void convertType(IR::Expr *source, IR::Expr *target);
virtual void loadThisObject(IR::Expr *temp);
- virtual void loadQmlIdArray(IR::Expr *target);
+ virtual void loadQmlContext(IR::Expr *target);
virtual void loadQmlImportedScripts(IR::Expr *target);
- virtual void loadQmlContextObject(IR::Expr *target);
- virtual void loadQmlScopeObject(IR::Expr *target);
virtual void loadQmlSingleton(const QString &name, IR::Expr *target);
virtual void loadConst(IR::Const *sourceConst, IR::Expr *target);
virtual void loadString(const QString &str, IR::Expr *target);
@@ -107,8 +118,10 @@ protected:
virtual void setActivationProperty(IR::Expr *source, const QString &targetName);
virtual void initClosure(IR::Closure *closure, IR::Expr *target);
virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target);
+ virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target);
virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target);
virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName);
+ virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex);
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex);
virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target);
virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex);
diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp
index ae06a99d2a..d1d97c8f84 100644
--- a/src/qml/jit/qv4regalloc.cpp
+++ b/src/qml/jit/qv4regalloc.cpp
@@ -35,7 +35,7 @@
#include <QtCore/QDebug>
#include "qv4regalloc_p.h"
#include "qv4alloca_p.h"
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <algorithm>
#if defined(Q_CC_MINGW)
@@ -267,6 +267,7 @@ public:
protected: // IRDecoder
virtual void callBuiltinInvalid(IR::Name *, IR::ExprList *, IR::Expr *) {}
+ virtual void callBuiltinTypeofQmlContextProperty(IR::Expr *, IR::Member::MemberKind, int, IR::Expr *) {}
virtual void callBuiltinTypeofMember(IR::Expr *, const QString &, IR::Expr *) {}
virtual void callBuiltinTypeofSubscript(IR::Expr *, IR::Expr *, IR::Expr *) {}
virtual void callBuiltinTypeofName(const QString &, IR::Expr *) {}
@@ -299,6 +300,16 @@ protected: // IRDecoder
addCall();
}
+ virtual void callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind /*kind*/, int propertyIndex, IR::ExprList *args, IR::Expr *result)
+ {
+ Q_UNUSED(propertyIndex)
+
+ addDef(result);
+ addUses(base->asTemp(), Use::CouldHaveRegister);
+ addUses(args, Use::CouldHaveRegister);
+ addCall();
+ }
+
virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
IR::Expr *result)
{
@@ -421,7 +432,7 @@ protected: // IRDecoder
addDef(temp);
}
- virtual void loadQmlIdArray(IR::Expr *temp)
+ virtual void loadQmlContext(IR::Expr *temp)
{
addDef(temp);
addCall();
@@ -433,20 +444,6 @@ protected: // IRDecoder
addCall();
}
- virtual void loadQmlContextObject(Expr *temp)
- {
- addDef(temp);
- addCall();
- }
-
- virtual void loadQmlScopeObject(Expr *temp)
- {
- Q_UNUSED(temp);
-
- addDef(temp);
- addCall();
- }
-
virtual void loadQmlSingleton(const QString &/*name*/, Expr *temp)
{
Q_UNUSED(temp);
@@ -511,6 +508,13 @@ protected: // IRDecoder
addCall();
}
+ virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind /*kind*/, int /*propertyIndex*/)
+ {
+ addUses(source->asTemp(), Use::CouldHaveRegister);
+ addUses(targetBase->asTemp(), Use::CouldHaveRegister);
+ addCall();
+ }
+
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int /*propertyIndex*/)
{
addUses(source->asTemp(), Use::CouldHaveRegister);
@@ -518,6 +522,13 @@ protected: // IRDecoder
addCall();
}
+ virtual void getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind /*kind*/, int /*index*/, IR::Expr *target)
+ {
+ addDef(target);
+ addUses(base->asTemp(), Use::CouldHaveRegister);
+ addCall();
+ }
+
virtual void getQObjectProperty(IR::Expr *base, int /*propertyIndex*/, bool /*captureRequired*/, bool /*isSingleton*/, int /*attachedPropertiesId*/, IR::Expr *target)
{
addDef(target);
@@ -935,7 +946,7 @@ private:
return;
while (!_unprocessed.isEmpty()) {
- const LifeTimeInterval *i = _unprocessed.first();
+ const LifeTimeInterval *i = _unprocessed.constFirst();
if (i->start() > position)
break;
@@ -1313,7 +1324,7 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt)
if (DebugRegAlloc)
qDebug() << "*** Finished regalloc , result:";
- static bool showCode = !qgetenv("QV4_SHOW_IR").isNull();
+ static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_IR");
if (showCode) {
QBuffer buf;
buf.open(QIODevice::WriteOnly);
diff --git a/src/qml/jit/qv4regalloc_p.h b/src/qml/jit/qv4regalloc_p.h
index f0d78cf0d3..1b6eb34e0b 100644
--- a/src/qml/jit/qv4regalloc_p.h
+++ b/src/qml/jit/qv4regalloc_p.h
@@ -33,6 +33,17 @@
#ifndef QV4REGALLOC_P_H
#define QV4REGALLOC_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4isel_p.h"
#include "qv4ssa_p.h"
diff --git a/src/qml/jit/qv4registerinfo_p.h b/src/qml/jit/qv4registerinfo_p.h
index ebd8537a85..cfd7bcb071 100644
--- a/src/qml/jit/qv4registerinfo_p.h
+++ b/src/qml/jit/qv4registerinfo_p.h
@@ -34,6 +34,17 @@
#ifndef QV4REGISTERINFO_P_H
#define QV4REGISTERINFO_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/QString>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jit/qv4targetplatform_p.h b/src/qml/jit/qv4targetplatform_p.h
index 05741f0ae5..1e62b23fe4 100644
--- a/src/qml/jit/qv4targetplatform_p.h
+++ b/src/qml/jit/qv4targetplatform_p.h
@@ -34,6 +34,17 @@
#ifndef QV4TARGETPLATFORM_P_H
#define QV4TARGETPLATFORM_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <config.h>
#if ENABLE(ASSEMBLER)
@@ -346,6 +357,71 @@ public:
static void platformLeaveStandardStackFrame(JSC::MacroAssembler *as) { as->pop(JSC::ARMRegisters::lr); }
#endif // Linux on ARM (32 bit)
+#if defined(Q_PROCESSOR_MIPS_32) && defined(Q_OS_LINUX)
+ enum { RegAllocIsSupported = 1 };
+
+ static const JSC::MacroAssembler::RegisterID StackFrameRegister = JSC::MIPSRegisters::fp;
+ static const JSC::MacroAssembler::RegisterID StackPointerRegister = JSC::MIPSRegisters::sp;
+ static const JSC::MacroAssembler::RegisterID LocalsRegister = JSC::MIPSRegisters::s0;
+ static const JSC::MacroAssembler::RegisterID EngineRegister = JSC::MIPSRegisters::s1;
+ static const JSC::MacroAssembler::RegisterID ReturnValueRegister = JSC::MIPSRegisters::v0;
+ static const JSC::MacroAssembler::RegisterID ScratchRegister = JSC::MIPSRegisters::s2;
+ static const JSC::MacroAssembler::FPRegisterID FPGpr0 = JSC::MIPSRegisters::f0;
+ static const JSC::MacroAssembler::FPRegisterID FPGpr1 = JSC::MIPSRegisters::f2;
+
+ static RegisterInformation getPlatformRegisterInfo()
+ {
+ typedef RegisterInfo RI;
+ return RegisterInformation()
+ // Note: t0, t1, t2, t3 and f16 are already used by MacroAssemblerMIPS.
+ << RI(JSC::MIPSRegisters::t4, QStringLiteral("t4"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::t5, QStringLiteral("t5"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::t6, QStringLiteral("t6"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::t7, QStringLiteral("t7"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::t8, QStringLiteral("t8"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::s0, QStringLiteral("s0"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::MIPSRegisters::s1, QStringLiteral("s1"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::MIPSRegisters::s2, QStringLiteral("s2"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::MIPSRegisters::s3, QStringLiteral("s3"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f4, QStringLiteral("f4"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f6, QStringLiteral("f6"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f8, QStringLiteral("f8"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f10, QStringLiteral("f10"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f18, QStringLiteral("f18"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f20, QStringLiteral("f20"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f22, QStringLiteral("f22"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f24, QStringLiteral("f24"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f26, QStringLiteral("f26"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::MIPSRegisters::f28, QStringLiteral("f28"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc)
+ ;
+ }
+
+#undef HAVE_ALU_OPS_WITH_MEM_OPERAND
+#undef VALUE_FITS_IN_REGISTER
+ static const int RegisterSize = 4;
+
+#define ARGUMENTS_IN_REGISTERS
+ static const int RegisterArgumentCount = 4;
+ static JSC::MacroAssembler::RegisterID registerForArgument(int index)
+ {
+ static JSC::MacroAssembler::RegisterID regs[RegisterArgumentCount] = {
+ JSC::MIPSRegisters::a0,
+ JSC::MIPSRegisters::a1,
+ JSC::MIPSRegisters::a2,
+ JSC::MIPSRegisters::a3
+ };
+
+ Q_ASSERT(index >= 0 && index < RegisterArgumentCount);
+ return regs[index];
+ };
+
+ static const int StackAlignment = 8;
+ static const int StackShadowSpace = 4 * RegisterSize; // Stack space for 4 argument registers.
+ static const int StackSpaceAllocatedUponFunctionEntry = 1 * RegisterSize; // Registers saved in platformEnterStandardStackFrame below.
+ static void platformEnterStandardStackFrame(JSC::MacroAssembler *as) { as->push(JSC::MIPSRegisters::ra); }
+ static void platformLeaveStandardStackFrame(JSC::MacroAssembler *as) { as->pop(JSC::MIPSRegisters::ra); }
+#endif // Linux on MIPS (32 bit)
+
public: // utility functions
static RegisterInformation getRegisterInfo()
{
diff --git a/src/qml/jit/qv4unop_p.h b/src/qml/jit/qv4unop_p.h
index f96898ce1b..69a70062b8 100644
--- a/src/qml/jit/qv4unop_p.h
+++ b/src/qml/jit/qv4unop_p.h
@@ -33,6 +33,17 @@
#ifndef QV4UNOP_P_H
#define QV4UNOP_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qv4jsir_p.h>
#include <qv4isel_masm_p.h>
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index ee27c21aed..5ccbccebad 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -77,7 +77,6 @@ Q_DECLARE_METATYPE(QList<int>)
\ingroup qtjavascript
\inmodule QtQml
- \mainclass
\section1 Evaluating Scripts
@@ -161,8 +160,82 @@ Q_DECLARE_METATYPE(QList<int>)
\snippet code/src_script_qjsengine.cpp 5
- \sa QJSValue, {Making Applications Scriptable}
+ \section1 Extensions
+ QJSEngine provides a compliant ECMAScript implementation. By default,
+ familiar utilities like logging are not available, but they can can be
+ installed via the \l installExtensions() function.
+
+ \sa QJSValue, {Making Applications Scriptable},
+ {List of JavaScript Objects and Functions}
+
+*/
+
+/*!
+ \enum QJSEngine::Extension
+
+ This enum is used to specify extensions to be installed via
+ \l installExtensions().
+
+ \value TranslationExtension Indicates that translation functions (\c qsTr(),
+ for example) should be installed.
+
+ \value ConsoleExtension Indicates that console functions (\c console.log(),
+ for example) should be installed.
+
+ \value GarbageCollectionExtension Indicates that garbage collection
+ functions (\c gc(), for example) should be installed.
+
+ \value AllExtensions Indicates that all extension should be installed.
+
+ \b TranslationExtension
+
+ The relation between script translation functions and C++ translation
+ functions is described in the following table:
+
+ \table
+ \header \li Script Function \li Corresponding C++ Function
+ \row \li qsTr() \li QObject::tr()
+ \row \li QT_TR_NOOP() \li QT_TR_NOOP()
+ \row \li qsTranslate() \li QCoreApplication::translate()
+ \row \li QT_TRANSLATE_NOOP() \li QT_TRANSLATE_NOOP()
+ \row \li qsTrId() \li qtTrId()
+ \row \li QT_TRID_NOOP() \li QT_TRID_NOOP()
+ \endtable
+
+ This flag also adds an \c arg() function to the string prototype.
+
+ For more information, see the \l {Internationalization with Qt}
+ documentation.
+
+ \b ConsoleExtension
+
+ The \l {Console API}{console} object implements a subset of the
+ \l {https://developer.mozilla.org/en-US/docs/Web/API/Console}{Console API},
+ which provides familiar logging functions, such as \c console.log().
+
+ The list of functions added is as follows:
+
+ \list
+ \li \c console.assert()
+ \li \c console.debug()
+ \li \c console.exception()
+ \li \c console.info()
+ \li \c console.log() (equivalent to \c console.debug())
+ \li \c console.error()
+ \li \c console.time()
+ \li \c console.timeEnd()
+ \li \c console.trace()
+ \li \c console.count()
+ \li \c console.warn()
+ \li \c {print()} (equivalent to \c console.debug())
+ \endlist
+
+ For more information, see the \l {Console API} documentation.
+
+ \b GarbageCollectionExtension
+
+ The \c gc() function is equivalent to calling \l collectGarbage().
*/
QT_BEGIN_NAMESPACE
@@ -235,8 +308,11 @@ void QJSEngine::collectGarbage()
d->m_v4Engine->memoryManager->runGC();
}
+#if QT_DEPRECATED_SINCE(5, 6)
+
/*!
\since 5.4
+ \obsolete
Installs translator functions on the given \a object, or on the Global
Object if no object is specified.
@@ -260,30 +336,46 @@ void QJSEngine::collectGarbage()
*/
void QJSEngine::installTranslatorFunctions(const QJSValue &object)
{
+ installExtensions(TranslationExtension, object);
+}
+
+#endif // QT_DEPRECATED_SINCE(5, 6)
+
+
+/*!
+ \since 5.6
+
+ Installs JavaScript \a extensions to add functionality that is not
+ available in a standard ECMAScript implementation.
+
+ The extensions are installed on the given \a object, or on the
+ \l {globalObject()}{Global Object} if no object is specified.
+
+ Several extensions can be installed at once by \c {OR}-ing the enum values:
+
+ \code
+ installExtensions(QJSEngine::TranslationExtension | QJSEngine::ConsoleExtension);
+ \endcode
+
+ \sa Extension
+*/
+void QJSEngine::installExtensions(QJSEngine::Extensions extensions, const QJSValue &object)
+{
QV4::ExecutionEngine *otherEngine = QJSValuePrivate::engine(&object);
if (otherEngine && otherEngine != d->m_v4Engine) {
- qWarning("QJSEngine: Trying to install a translator function from a different engine");
+ qWarning("QJSEngine: Trying to install extensions from a different engine");
return;
}
+
QV4::Scope scope(d->m_v4Engine);
QV4::ScopedObject obj(scope);
QV4::Value *val = QJSValuePrivate::getValue(&object);
if (val)
obj = val;
if (!obj)
- obj = scope.engine->globalObject();
-#ifndef QT_NO_TRANSLATION
- obj->defineDefaultProperty(QStringLiteral("qsTranslate"), QV4::GlobalExtensions::method_qsTranslate);
- obj->defineDefaultProperty(QStringLiteral("QT_TRANSLATE_NOOP"), QV4::GlobalExtensions::method_qsTranslateNoOp);
- obj->defineDefaultProperty(QStringLiteral("qsTr"), QV4::GlobalExtensions::method_qsTr);
- obj->defineDefaultProperty(QStringLiteral("QT_TR_NOOP"), QV4::GlobalExtensions::method_qsTrNoOp);
- obj->defineDefaultProperty(QStringLiteral("qsTrId"), QV4::GlobalExtensions::method_qsTrId);
- obj->defineDefaultProperty(QStringLiteral("QT_TRID_NOOP"), QV4::GlobalExtensions::method_qsTrIdNoOp);
-
- // string prototype extension
- scope.engine->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("arg"),
- QV4::GlobalExtensions::method_string_arg);
-#endif
+ obj = scope.engine->globalObject;
+
+ QV4::GlobalExtensions::init(obj, extensions);
}
/*!
@@ -318,8 +410,10 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
{
QV4::ExecutionEngine *v4 = d->m_v4Engine;
QV4::Scope scope(v4);
- QV4::ScopedContext ctx(scope, v4->currentContext());
- if (ctx->d() != v4->rootContext())
+ QV4::ExecutionContextSaver saver(scope);
+
+ QV4::ExecutionContext *ctx = v4->currentContext;
+ if (ctx->d() != v4->rootContext()->d())
ctx = v4->pushGlobalContext();
QV4::ScopedValue result(scope);
@@ -331,8 +425,7 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
result = script.run();
if (scope.engine->hasException)
result = v4->catchException();
- if (ctx->d() != v4->rootContext())
- v4->popContext();
+
return QJSValue(v4, result->asReturnedValue());
}
@@ -414,7 +507,7 @@ QJSValue QJSEngine::globalObject() const
{
Q_D(const QJSEngine);
QV4::Scope scope(d->m_v4Engine);
- QV4::ScopedValue v(scope, d->m_v4Engine->globalObject());
+ QV4::ScopedValue v(scope, d->m_v4Engine->globalObject);
return QJSValue(d->m_v4Engine, v->asReturnedValue());
}
@@ -554,7 +647,7 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
Creates a QJSValue with the given \a value.
- \sa fromScriptValue(), newVariant()
+ \sa fromScriptValue()
*/
/*! \fn T QJSEngine::fromScriptValue(const QJSValue &value)
@@ -581,7 +674,7 @@ QJSEnginePrivate::~QJSEnginePrivate()
QQmlPropertyCache *QJSEnginePrivate::createCache(const QMetaObject *mo)
{
if (!mo->superClass()) {
- QQmlPropertyCache *rv = new QQmlPropertyCache(q_func(), mo);
+ QQmlPropertyCache *rv = new QQmlPropertyCache(QV8Engine::getV4(q_func()), mo);
propertyCache.insert(mo, rv);
return rv;
} else {
diff --git a/src/qml/jsapi/qjsengine.h b/src/qml/jsapi/qjsengine.h
index 123eb727df..40b0a60369 100644
--- a/src/qml/jsapi/qjsengine.h
+++ b/src/qml/jsapi/qjsengine.h
@@ -81,7 +81,19 @@ public:
void collectGarbage();
- void installTranslatorFunctions(const QJSValue &object = QJSValue());
+#if QT_DEPRECATED_SINCE(5, 6)
+ QT_DEPRECATED void installTranslatorFunctions(const QJSValue &object = QJSValue());
+#endif
+
+ enum Extension {
+ TranslationExtension = 0x1,
+ ConsoleExtension = 0x2,
+ GarbageCollectionExtension = 0x4,
+ AllExtensions = 0xffffffff
+ };
+ Q_DECLARE_FLAGS(Extensions, Extension)
+
+ void installExtensions(Extensions extensions, const QJSValue &object = QJSValue());
QV8Engine *handle() const { return d; }
@@ -102,6 +114,8 @@ private:
friend class QV8Engine;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QJSEngine::Extensions)
+
inline bool qjsvalue_cast_helper(const QJSValue &value, int type, void *ptr)
{
return QJSEngine::convertV2(value, type, ptr);
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 1d9dc2b6db..a49b98c921 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -37,13 +37,14 @@
#include "qjsengine.h"
#include "qjsvalue.h"
#include "qjsvalue_p.h"
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include "qv4dateobject_p.h"
#include "qv4runtime_p.h"
#include "qv4variantobject_p.h"
#include "qv4regexpobject_p.h"
+#include "qv4errorobject_p.h"
#include "private/qv8engine_p.h"
#include <private/qv4mm_p.h>
#include <private/qv4scopedvalue_p.h>
@@ -57,7 +58,6 @@
\ingroup qtjavascript
\inmodule QtQml
- \mainclass
QJSValue supports the types defined in the \l{ECMA-262}
standard: The primitive types, which are Undefined, Null, Boolean,
@@ -329,8 +329,7 @@ bool QJSValue::isError() const
QV4::Value *val = QJSValuePrivate::getValue(this);
if (!val)
return false;
- Object *o = val->asObject();
- return o && o->asErrorObject();
+ return val->as<ErrorObject>();
}
/*!
@@ -344,7 +343,7 @@ bool QJSValue::isArray() const
QV4::Value *val = QJSValuePrivate::getValue(this);
if (!val)
return false;
- return val->asArrayObject();
+ return val->as<ArrayObject>();
}
/*!
@@ -361,7 +360,7 @@ bool QJSValue::isObject() const
QV4::Value *val = QJSValuePrivate::getValue(this);
if (!val)
return false;
- return val->asObject();
+ return val->as<Object>();
}
/*!
@@ -375,7 +374,7 @@ bool QJSValue::isCallable() const
QV4::Value *val = QJSValuePrivate::getValue(this);
if (!val)
return false;
- return val->asFunctionObject();
+ return val->as<FunctionObject>();
}
/*!
@@ -601,7 +600,7 @@ QVariant QJSValue::toVariant() const
QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch);
Q_ASSERT(val);
- if (Object *o = val->asObject())
+ if (Object *o = val->as<Object>())
return o->engine()->toVariant(*val, /*typeHint*/ -1, /*createJSValueForObjects*/ false);
if (val->isString())
@@ -640,7 +639,7 @@ QJSValue QJSValue::call(const QJSValueList &args)
if (!val)
return QJSValue();
- FunctionObject *f = val->asFunctionObject();
+ FunctionObject *f = val->as<FunctionObject>();
if (!f)
return QJSValue();
@@ -649,7 +648,7 @@ QJSValue QJSValue::call(const QJSValueList &args)
Scope scope(engine);
ScopedCallData callData(scope, args.length());
- callData->thisObject = engine->globalObject()->asReturnedValue();
+ callData->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");
@@ -691,7 +690,7 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList
if (!val)
return QJSValue();
- FunctionObject *f = val->asFunctionObject();
+ FunctionObject *f = val->as<FunctionObject>();
if (!f)
return QJSValue();
@@ -745,7 +744,7 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args)
if (!val)
return QJSValue();
- FunctionObject *f = val->asFunctionObject();
+ FunctionObject *f = val->as<FunctionObject>();
if (!f)
return QJSValue();
@@ -801,7 +800,7 @@ QJSValue QJSValue::prototype() const
if (!engine)
return QJSValue();
QV4::Scope scope(engine);
- ScopedObject o(scope, QJSValuePrivate::getValue(this)->asObject());
+ ScopedObject o(scope, QJSValuePrivate::getValue(this)->as<Object>());
if (!o)
return QJSValue();
ScopedObject p(scope, o->prototype());
@@ -1041,7 +1040,7 @@ QJSValue QJSValue::property(quint32 arrayIndex) const
if (!o)
return QJSValue();
- QV4::ScopedValue result(scope, arrayIndex == UINT_MAX ? o->get(engine->id_uintMax) : o->getIndexed(arrayIndex));
+ QV4::ScopedValue result(scope, arrayIndex == UINT_MAX ? o->get(engine->id_uintMax()) : o->getIndexed(arrayIndex));
if (engine->hasException)
engine->catchException();
return QJSValue(engine, result->asReturnedValue());
@@ -1120,7 +1119,7 @@ void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value)
if (arrayIndex != UINT_MAX)
o->putIndexed(arrayIndex, v);
else
- o->put(engine->id_uintMax, v);
+ o->put(engine->id_uintMax(), v);
if (engine->hasException)
engine->catchException();
}
@@ -1236,7 +1235,7 @@ QDateTime QJSValue::toDateTime() const
{
QV4::Value *val = QJSValuePrivate::getValue(this);
if (val) {
- QV4::DateObject *date = val->asDateObject();
+ QV4::DateObject *date = val->as<DateObject>();
if (date)
return date->toQDateTime();
}
@@ -1250,7 +1249,7 @@ QDateTime QJSValue::toDateTime() const
bool QJSValue::isDate() const
{
QV4::Value *val = QJSValuePrivate::getValue(this);
- return val && val->asDateObject();
+ return val && val->as<DateObject>();
}
/*!
diff --git a/src/qml/jsapi/qjsvalue_p.h b/src/qml/jsapi/qjsvalue_p.h
index 93a28a4a5f..08dc184412 100644
--- a/src/qml/jsapi/qjsvalue_p.h
+++ b/src/qml/jsapi/qjsvalue_p.h
@@ -47,7 +47,7 @@
#include <qjsvalue.h>
#include <private/qtqmlglobal_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4string_p.h>
#include <private/qv4engine_p.h>
#include <private/qv4object_p.h>
diff --git a/src/qml/jsapi/qjsvalueiterator.cpp b/src/qml/jsapi/qjsvalueiterator.cpp
index 1ee4121f5c..a24953ae3f 100644
--- a/src/qml/jsapi/qjsvalueiterator.cpp
+++ b/src/qml/jsapi/qjsvalueiterator.cpp
@@ -52,9 +52,6 @@ QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValue &v)
QV4::Scope scope(e);
QV4::ScopedObject o(scope, QJSValuePrivate::getValue(&v));
iterator.set(e, e->newForEachIteratorObject(o));
-
- currentName = (QV4::String *)0;
- nextName = (QV4::String *)0;
}
@@ -102,8 +99,10 @@ QJSValueIterator::QJSValueIterator(const QJSValue& object)
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
it->d()->it.flags = QV4::ObjectIterator::NoFlags;
QV4::ScopedString nm(scope);
- it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
- d_ptr->nextName = nm;
+ QV4::Property nextProperty;
+ QV4::PropertyAttributes nextAttributes;
+ it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes);
+ d_ptr->nextName.set(v4, nm.asReturnedValue());
}
/*!
@@ -125,7 +124,7 @@ bool QJSValueIterator::hasNext() const
QV4::Value *val = QJSValuePrivate::getValue(&d_ptr->value);
if (!val || !val->isObject())
return false;
- return !!d_ptr->nextName || d_ptr->nextIndex != UINT_MAX;
+ return d_ptr->nextName.as<QV4::String>() || d_ptr->nextIndex != UINT_MAX;
}
/*!
@@ -143,8 +142,6 @@ bool QJSValueIterator::next()
return false;
d_ptr->currentName = d_ptr->nextName;
d_ptr->currentIndex = d_ptr->nextIndex;
- d_ptr->currentProperty.copy(&d_ptr->nextProperty, d_ptr->nextAttributes);
- d_ptr->currentAttributes = d_ptr->nextAttributes;
QV4::ExecutionEngine *v4 = d_ptr->iterator.engine();
if (!v4)
@@ -152,9 +149,11 @@ bool QJSValueIterator::next()
QV4::Scope scope(v4);
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
QV4::ScopedString nm(scope);
- it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
- d_ptr->nextName = nm;
- return !!d_ptr->currentName || d_ptr->currentIndex != UINT_MAX;
+ QV4::Property nextProperty;
+ QV4::PropertyAttributes nextAttributes;
+ it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes);
+ d_ptr->nextName.set(v4, nm.asReturnedValue());
+ return d_ptr->currentName.as<QV4::String>() || d_ptr->currentIndex != UINT_MAX;
}
/*!
@@ -168,8 +167,8 @@ QString QJSValueIterator::name() const
QV4::Value *val = QJSValuePrivate::getValue(&d_ptr->value);
if (!val || !val->isObject())
return QString();
- if (!!d_ptr->currentName)
- return d_ptr->currentName->toQString();
+ if (QV4::String *s = d_ptr->currentName.as<QV4::String>())
+ return s->toQString();
if (d_ptr->currentIndex < UINT_MAX)
return QString::number(d_ptr->currentIndex);
return QString();
@@ -192,10 +191,10 @@ QJSValue QJSValueIterator::value() const
if (!obj)
return QJSValue();
- if (!d_ptr->currentName && d_ptr->currentIndex == UINT_MAX)
+ if (!d_ptr->currentName.as<QV4::String>() && d_ptr->currentIndex == UINT_MAX)
return QJSValue();
- QV4::ScopedValue v(scope, obj->getValue(*obj, &d_ptr->currentProperty, d_ptr->currentAttributes));
+ QV4::ScopedValue v(scope, d_ptr->currentIndex == UINT_MAX ? obj->get(d_ptr->currentName.as<QV4::String>()) : obj->getIndexed(d_ptr->currentIndex));
if (scope.hasException()) {
engine->catchException();
return QJSValue();
@@ -214,8 +213,8 @@ QJSValueIterator& QJSValueIterator::operator=(QJSValue& object)
d_ptr->value = object;
d_ptr->currentIndex = UINT_MAX;
d_ptr->nextIndex = UINT_MAX;
- d_ptr->currentName = (QV4::String *)0;
- d_ptr->nextName = (QV4::String *)0;
+ d_ptr->currentName.clear();
+ d_ptr->nextName.clear();
QV4::ExecutionEngine *v4 = d_ptr->iterator.engine();
if (!v4) {
d_ptr->iterator.clear();
@@ -228,8 +227,10 @@ QJSValueIterator& QJSValueIterator::operator=(QJSValue& object)
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
it->d()->it.flags = QV4::ObjectIterator::NoFlags;
QV4::ScopedString nm(scope);
- it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
- d_ptr->nextName = nm;
+ QV4::Property nextProperty;
+ QV4::PropertyAttributes nextAttributes;
+ it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes);
+ d_ptr->nextName.set(v4, nm.asReturnedValue());
return *this;
}
diff --git a/src/qml/jsapi/qjsvalueiterator_p.h b/src/qml/jsapi/qjsvalueiterator_p.h
index c17fedf73e..dfc5e18cd6 100644
--- a/src/qml/jsapi/qjsvalueiterator_p.h
+++ b/src/qml/jsapi/qjsvalueiterator_p.h
@@ -34,6 +34,17 @@
#ifndef QJSVALUEITERATOR_P_H
#define QJSVALUEITERATOR_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qjsvalue.h"
#include "private/qv4objectiterator_p.h"
@@ -48,15 +59,9 @@ public:
QJSValue value;
QV4::PersistentValue iterator;
- // ### GC
- QV4::Property currentProperty;
- QV4::PropertyAttributes currentAttributes;
- QV4::StringValue currentName;
+ QV4::PersistentValue currentName;
uint currentIndex;
- // ### GC
- QV4::Property nextProperty;
- QV4::PropertyAttributes nextAttributes;
- QV4::StringValue nextName;
+ QV4::PersistentValue nextName;
uint nextIndex;
};
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index ef44ca6f4d..5ffdebe328 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -10,7 +10,6 @@ SOURCES += \
$$PWD/qv4lookup.cpp \
$$PWD/qv4identifier.cpp \
$$PWD/qv4identifiertable.cpp \
- $$PWD/qv4mm.cpp \
$$PWD/qv4managed.cpp \
$$PWD/qv4internalclass.cpp \
$$PWD/qv4sparsearray.cpp \
@@ -40,7 +39,6 @@ SOURCES += \
$$PWD/qv4sequenceobject.cpp \
$$PWD/qv4include.cpp \
$$PWD/qv4qobjectwrapper.cpp \
- $$PWD/qv4qmlextensions.cpp \
$$PWD/qv4vme_moth.cpp \
$$PWD/qv4profiling.cpp \
$$PWD/qv4arraybuffer.cpp \
@@ -57,7 +55,6 @@ HEADERS += \
$$PWD/qv4lookup_p.h \
$$PWD/qv4identifier_p.h \
$$PWD/qv4identifiertable_p.h \
- $$PWD/qv4mm_p.h \
$$PWD/qv4managed_p.h \
$$PWD/qv4internalclass_p.h \
$$PWD/qv4sparsearray_p.h \
@@ -90,7 +87,6 @@ HEADERS += \
$$PWD/qv4sequenceobject_p.h \
$$PWD/qv4include_p.h \
$$PWD/qv4qobjectwrapper_p.h \
- $$PWD/qv4qmlextensions_p.h \
$$PWD/qv4vme_moth_p.h \
$$PWD/qv4profiling_p.h \
$$PWD/qv4arraybuffer_p.h \
@@ -102,7 +98,7 @@ HEADERS += \
HEADERS += \
$$PWD/qv4runtime_p.h \
- $$PWD/qv4value_inl_p.h \
+ $$PWD/qv4value_p.h \
$$PWD/qv4string_p.h \
$$PWD/qv4value_p.h
diff --git a/src/qml/jsruntime/qv4alloca_p.h b/src/qml/jsruntime/qv4alloca_p.h
index a4537868e2..df40a018ba 100644
--- a/src/qml/jsruntime/qv4alloca_p.h
+++ b/src/qml/jsruntime/qv4alloca_p.h
@@ -34,6 +34,17 @@
#ifndef QV4_ALLOCA_H
#define QV4_ALLOCA_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qglobal.h>
#if defined(Q_OS_WIN)
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 92c77570af..698b4c325c 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -33,18 +33,17 @@
#include <qv4argumentsobject_p.h>
#include <qv4alloca_p.h>
#include <qv4scopedvalue_p.h>
+#include "qv4string_p.h"
using namespace QV4;
DEFINE_OBJECT_VTABLE(ArgumentsObject);
Heap::ArgumentsObject::ArgumentsObject(QV4::CallContext *context)
- : Heap::Object(context->d()->strictMode ? context->d()->engine->strictArgumentsObjectClass : context->d()->engine->argumentsObjectClass,
- context->d()->engine->objectPrototype.asObject())
- , context(context->d())
+ : context(context->d())
, fullyCreated(false)
{
- Q_ASSERT(vtable == QV4::ArgumentsObject::staticVTable());
+ Q_ASSERT(vtable() == QV4::ArgumentsObject::staticVTable());
ExecutionEngine *v4 = context->d()->engine;
Scope scope(v4);
@@ -53,22 +52,22 @@ Heap::ArgumentsObject::ArgumentsObject(QV4::CallContext *context)
args->setArrayType(Heap::ArrayData::Complex);
if (context->d()->strictMode) {
- Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee));
- Q_ASSERT(CallerPropertyIndex == args->internalClass()->find(context->d()->engine->id_caller));
- args->propertyAt(CalleePropertyIndex)->value = v4->thrower;
- args->propertyAt(CalleePropertyIndex)->set = v4->thrower;
- args->propertyAt(CallerPropertyIndex)->value = v4->thrower;
- args->propertyAt(CallerPropertyIndex)->set = v4->thrower;
+ Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee()));
+ Q_ASSERT(CallerPropertyIndex == args->internalClass()->find(context->d()->engine->id_caller()));
+ *args->propertyData(CalleePropertyIndex + QV4::Object::GetterOffset) = v4->thrower();
+ *args->propertyData(CalleePropertyIndex + QV4::Object::SetterOffset) = v4->thrower();
+ *args->propertyData(CallerPropertyIndex + QV4::Object::GetterOffset) = v4->thrower();
+ *args->propertyData(CallerPropertyIndex + QV4::Object::SetterOffset) = v4->thrower();
args->arrayReserve(context->argc());
args->arrayPut(0, context->args(), context->argc());
args->d()->fullyCreated = true;
} else {
- Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee));
- args->memberData()->data[CalleePropertyIndex] = context->d()->function->asReturnedValue();
+ Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee()));
+ *args->propertyData(CalleePropertyIndex) = context->d()->function->asReturnedValue();
}
- Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(context->d()->engine->id_length));
- args->memberData()->data[LengthPropertyIndex] = Primitive::fromInt32(context->d()->callData->argc);
+ Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(context->d()->engine->id_length()));
+ *args->propertyData(LengthPropertyIndex) = Primitive::fromInt32(context->d()->callData->argc);
}
void ArgumentsObject::fullyCreate()
@@ -76,17 +75,16 @@ void ArgumentsObject::fullyCreate()
if (fullyCreated())
return;
- uint numAccessors = qMin((int)context()->function->formalParameterCount(), context()->callData->argc);
uint argCount = context()->callData->argc;
+ uint numAccessors = qMin(context()->function->formalParameterCount(), argCount);
ArrayData::realloc(this, Heap::ArrayData::Sparse, argCount, true);
context()->engine->requireArgumentsAccessors(numAccessors);
Scope scope(engine());
Scoped<MemberData> md(scope, d()->mappedArguments);
- if (!md || md->size() < numAccessors)
- d()->mappedArguments = md->reallocate(engine(), d()->mappedArguments, numAccessors);
- for (uint i = 0; i < (uint)numAccessors; ++i) {
- mappedArguments()->data[i] = context()->callData->args[i];
+ d()->mappedArguments = md->allocate(engine(), numAccessors);
+ for (uint i = 0; i < numAccessors; ++i) {
+ d()->mappedArguments->data[i] = context()->callData->args[i];
arraySet(i, context()->engine->argumentsAccessors + i, Attr_Accessor);
}
arrayPut(numAccessors, context()->callData->args + numAccessors, argCount - numAccessors);
@@ -116,13 +114,13 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con
map->copy(pd, mapAttrs);
setArrayAttributes(index, Attr_Data);
pd = arrayData()->getProperty(index);
- pd->value = mappedArguments()->data[index];
+ pd->value = d()->mappedArguments->data[index];
}
- bool strict = engine->currentContext()->strictMode;
- engine->currentContext()->strictMode = false;
+ bool strict = engine->current->strictMode;
+ engine->current->strictMode = false;
bool result = Object::defineOwnProperty2(scope.engine, index, desc, attrs);
- engine->currentContext()->strictMode = strict;
+ engine->current->strictMode = strict;
if (isMapped && attrs.isData()) {
Q_ASSERT(arrayData());
@@ -139,14 +137,14 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con
}
}
- if (engine->currentContext()->strictMode && !result)
+ if (engine->current->strictMode && !result)
return engine->throwTypeError();
return result;
}
-ReturnedValue ArgumentsObject::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue ArgumentsObject::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
- ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
+ const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
if (args->fullyCreated())
return Object::getIndexed(m, index, hasProperty);
@@ -199,11 +197,11 @@ PropertyAttributes ArgumentsObject::queryIndexed(const Managed *m, uint index)
DEFINE_OBJECT_VTABLE(ArgumentsGetterFunction);
-ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
+ReturnedValue ArgumentsGetterFunction::call(const Managed *getter, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<ArgumentsGetterFunction *>(getter)->engine();
+ ExecutionEngine *v4 = static_cast<const ArgumentsGetterFunction *>(getter)->engine();
Scope scope(v4);
- Scoped<ArgumentsGetterFunction> g(scope, static_cast<ArgumentsGetterFunction *>(getter));
+ Scoped<ArgumentsGetterFunction> g(scope, static_cast<const ArgumentsGetterFunction *>(getter));
Scoped<ArgumentsObject> o(scope, callData->thisObject.as<ArgumentsObject>());
if (!o)
return v4->throwTypeError();
@@ -214,11 +212,11 @@ ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
DEFINE_OBJECT_VTABLE(ArgumentsSetterFunction);
-ReturnedValue ArgumentsSetterFunction::call(Managed *setter, CallData *callData)
+ReturnedValue ArgumentsSetterFunction::call(const Managed *setter, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<ArgumentsSetterFunction *>(setter)->engine();
+ ExecutionEngine *v4 = static_cast<const ArgumentsSetterFunction *>(setter)->engine();
Scope scope(v4);
- Scoped<ArgumentsSetterFunction> s(scope, static_cast<ArgumentsSetterFunction *>(setter));
+ Scoped<ArgumentsSetterFunction> s(scope, static_cast<const ArgumentsSetterFunction *>(setter));
Scoped<ArgumentsObject> o(scope, callData->thisObject.as<ArgumentsObject>());
if (!o)
return v4->throwTypeError();
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index 43cd6d1dee..7a9c4b1d51 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4ARGUMENTSOBJECTS_H
#define QV4ARGUMENTSOBJECTS_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
@@ -59,9 +70,9 @@ struct ArgumentsObject : Object {
CallerPropertyIndex = 3
};
ArgumentsObject(QV4::CallContext *context);
- CallContext *context;
+ Pointer<CallContext> context;
bool fullyCreated;
- MemberData *mappedArguments;
+ Pointer<MemberData> mappedArguments;
};
}
@@ -71,7 +82,7 @@ struct ArgumentsGetterFunction: FunctionObject
V4_OBJECT2(ArgumentsGetterFunction, FunctionObject)
uint index() const { return d()->index; }
- static ReturnedValue call(Managed *that, CallData *d);
+ static ReturnedValue call(const Managed *that, CallData *d);
};
inline
@@ -86,7 +97,7 @@ struct ArgumentsSetterFunction: FunctionObject
V4_OBJECT2(ArgumentsSetterFunction, FunctionObject)
uint index() const { return d()->index; }
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
inline
@@ -103,15 +114,14 @@ struct ArgumentsObject: Object {
Heap::CallContext *context() const { return d()->context; }
bool fullyCreated() const { return d()->fullyCreated; }
- Heap::MemberData *mappedArguments() { return d()->mappedArguments; }
static bool isNonStrictArgumentsObject(Managed *m) {
- return m->d()->vtable->type == Type_ArgumentsObject &&
+ return m->d()->vtable()->type == Type_ArgumentsObject &&
!static_cast<ArgumentsObject *>(m)->context()->strictMode;
}
bool defineOwnProperty(ExecutionEngine *engine, uint index, const Property *desc, PropertyAttributes attrs);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static void putIndexed(Managed *m, uint index, const Value &value);
static bool deleteIndexedProperty(Managed *m, uint index);
static PropertyAttributes queryIndexed(const Managed *m, uint index);
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp
index dc65b5d21a..0a3aa414de 100644
--- a/src/qml/jsruntime/qv4arraybuffer.cpp
+++ b/src/qml/jsruntime/qv4arraybuffer.cpp
@@ -33,6 +33,7 @@
#include "qv4arraybuffer_p.h"
#include "qv4typedarray_p.h"
#include "qv4dataview_p.h"
+#include "qv4string_p.h"
using namespace QV4;
@@ -44,9 +45,9 @@ Heap::ArrayBufferCtor::ArrayBufferCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue ArrayBufferCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ArrayBufferCtor::construct(const Managed *m, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(m)->engine();
Scope scope(v4);
ScopedValue l(scope, callData->argument(0));
@@ -57,14 +58,14 @@ ReturnedValue ArrayBufferCtor::construct(Managed *m, CallData *callData)
if (len != dl)
return v4->throwRangeError(QLatin1String("ArrayBuffer constructor: invalid length"));
- Scoped<ArrayBuffer> a(scope, v4->memoryManager->alloc<ArrayBuffer>(v4, len));
+ Scoped<ArrayBuffer> a(scope, v4->newArrayBuffer(len));
if (scope.engine->hasException)
return Encode::undefined();
return a.asReturnedValue();
}
-ReturnedValue ArrayBufferCtor::call(Managed *that, CallData *callData)
+ReturnedValue ArrayBufferCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
@@ -82,22 +83,20 @@ ReturnedValue ArrayBufferCtor::method_isView(CallContext *ctx)
}
-Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, size_t length)
- : Heap::Object(e->emptyClass, e->arrayBufferPrototype.asObject())
+Heap::ArrayBuffer::ArrayBuffer(size_t length)
{
data = QTypedArrayData<char>::allocate(length + 1);
if (!data) {
data = 0;
- e->throwRangeError(QStringLiteral("ArrayBuffer: out of memory"));
+ internalClass->engine->throwRangeError(QStringLiteral("ArrayBuffer: out of memory"));
return;
}
data->size = int(length);
memset(data->data(), 0, length + 1);
}
-Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, const QByteArray& array)
- : Heap::Object(e->emptyClass, e->arrayBufferPrototype.asObject())
- , data(const_cast<QByteArray&>(array).data_ptr())
+Heap::ArrayBuffer::ArrayBuffer(const QByteArray& array)
+ : data(const_cast<QByteArray&>(array).data_ptr())
{
data->ref.ref();
}
@@ -138,10 +137,10 @@ void ArrayBufferPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
ctor->defineDefaultProperty(QStringLiteral("isView"), ArrayBufferCtor::method_isView, 1);
- defineDefaultProperty(engine->id_constructor, (o = ctor));
+ defineDefaultProperty(engine->id_constructor(), (o = ctor));
defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, 0);
defineDefaultProperty(QStringLiteral("slice"), method_slice, 2);
}
@@ -172,7 +171,7 @@ ReturnedValue ArrayBufferPrototype::method_slice(CallContext *ctx)
double first = (start < 0) ? qMax(a->d()->data->size + start, 0.) : qMin(start, (double)a->d()->data->size);
double final = (end < 0) ? qMax(a->d()->data->size + end, 0.) : qMin(end, (double)a->d()->data->size);
- ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor));
+ ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor()));
if (!constructor)
return scope.engine->throwTypeError();
diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h
index fe3150618d..56f45b5a72 100644
--- a/src/qml/jsruntime/qv4arraybuffer_p.h
+++ b/src/qml/jsruntime/qv4arraybuffer_p.h
@@ -33,6 +33,17 @@
#ifndef QV4ARRAYBUFFER_H
#define QV4ARRAYBUFFER_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
@@ -47,8 +58,8 @@ struct ArrayBufferCtor : FunctionObject {
};
struct Q_QML_PRIVATE_EXPORT ArrayBuffer : Object {
- ArrayBuffer(ExecutionEngine *e, size_t length);
- ArrayBuffer(ExecutionEngine *e, const QByteArray& array);
+ ArrayBuffer(size_t length);
+ ArrayBuffer(const QByteArray& array);
~ArrayBuffer();
QTypedArrayData<char> *data;
@@ -61,8 +72,8 @@ struct ArrayBufferCtor: FunctionObject
{
V4_OBJECT2(ArrayBufferCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
static ReturnedValue method_isView(CallContext *ctx);
@@ -72,6 +83,7 @@ struct Q_QML_PRIVATE_EXPORT ArrayBuffer : Object
{
V4_OBJECT2(ArrayBuffer, Object)
V4_NEEDS_DESTROY
+ V4_PROTOTYPE(arrayBufferPrototype)
QByteArray asByteArray() const;
uint byteLength() const { return d()->byteLength(); }
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index afcfa00905..ec0185de64 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -33,13 +33,14 @@
#include "qv4arraydata_p.h"
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4runtime_p.h"
#include "qv4argumentsobject_p.h"
+#include "qv4string_p.h"
using namespace QV4;
-const QV4::ManagedVTable QV4::ArrayData::static_vtbl = {
+const QV4::VTable QV4::ArrayData::static_vtbl = {
0,
QV4::ArrayData::IsExecutionContext,
QV4::ArrayData::IsString,
@@ -90,6 +91,13 @@ const ArrayVTable SparseArrayData::static_vtbl =
Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SimpleArrayData));
Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SparseArrayData));
+static Q_ALWAYS_INLINE void storeValue(ReturnedValue *target, uint value)
+{
+ Value v = Value::fromReturnedValue(*target);
+ v.setValue(value);
+ *target = v.asReturnedValue();
+}
+
void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAttributes)
{
Scope scope(o->engine());
@@ -165,7 +173,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
Heap::SparseArrayData *sparse = static_cast<Heap::SparseArrayData *>(newData->d());
- uint *lastFree;
+ ReturnedValue *lastFree;
if (d && d->type() == Heap::ArrayData::Sparse) {
Heap::SparseArrayData *old = static_cast<Heap::SparseArrayData *>(d->d());
sparse->sparse = old->sparse;
@@ -180,20 +188,20 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
SparseArrayNode *n = sparse->sparse->insert(i);
n->value = i;
} else {
- *lastFree = i;
- sparse->arrayData[i].tag = Value::Empty_Type;
- lastFree = &sparse->arrayData[i].uint_32;
+ storeValue(lastFree, i);
+ sparse->arrayData[i].setTag(Value::Empty_Type);
+ lastFree = &sparse->arrayData[i].rawValueRef();
}
}
}
if (toCopy < sparse->alloc) {
for (uint i = toCopy; i < sparse->alloc; ++i) {
- *lastFree = i;
- sparse->arrayData[i].tag = Value::Empty_Type;
- lastFree = &sparse->arrayData[i].uint_32;
+ storeValue(lastFree, i);
+ sparse->arrayData[i].setTag(Value::Empty_Type);
+ lastFree = &sparse->arrayData[i].rawValueRef();
}
- *lastFree = UINT_MAX;
+ storeValue(lastFree, UINT_MAX);
}
// ### Could explicitly free the old data
}
@@ -230,7 +238,7 @@ ReturnedValue SimpleArrayData::get(const Heap::ArrayData *d, uint index)
bool SimpleArrayData::put(Object *o, uint index, const Value &value)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Q_ASSERT(index >= dd->len || !dd->attrs || !dd->attrs[index].isAccessor());
// ### honour attributes
dd->data(index) = value;
@@ -244,7 +252,7 @@ bool SimpleArrayData::put(Object *o, uint index, const Value &value)
bool SimpleArrayData::del(Object *o, uint index)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (index >= dd->len)
return true;
@@ -266,12 +274,12 @@ void SimpleArrayData::setAttribute(Object *o, uint index, PropertyAttributes att
void SimpleArrayData::push_front(Object *o, const Value *values, uint n)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Q_ASSERT(!dd->attrs);
if (dd->len + n > dd->alloc) {
realloc(o, Heap::ArrayData::Simple, dd->len + n, false);
Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Simple);
- dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
dd->offset = (dd->offset - n) % dd->alloc;
dd->len += n;
@@ -281,7 +289,7 @@ void SimpleArrayData::push_front(Object *o, const Value *values, uint n)
ReturnedValue SimpleArrayData::pop_front(Object *o)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Q_ASSERT(!dd->attrs);
if (!dd->len)
return Encode::undefined();
@@ -294,7 +302,7 @@ ReturnedValue SimpleArrayData::pop_front(Object *o)
uint SimpleArrayData::truncate(Object *o, uint newLen)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (dd->len < newLen)
return newLen;
@@ -318,10 +326,10 @@ uint SimpleArrayData::length(const Heap::ArrayData *d)
bool SimpleArrayData::putArray(Object *o, uint index, const Value *values, uint n)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (index + n > dd->alloc) {
reallocate(o, index + n + 1, false);
- dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
for (uint i = dd->len; i < index; ++i)
dd->data(i) = Primitive::emptyValue();
@@ -337,13 +345,10 @@ void SparseArrayData::free(Heap::ArrayData *d, uint idx)
Value *v = d->arrayData + idx;
if (d->attrs && d->attrs[idx].isAccessor()) {
// double slot, free both. Order is important, so we have a double slot for allocation again afterwards.
- v[1].tag = Value::Empty_Type;
- v[1].uint_32 = d->freeList;
- v[0].tag = Value::Empty_Type;
- v[0].uint_32 = idx + 1;
+ v[1].setTagValue(Value::Empty_Type, Value::fromReturnedValue(d->freeList).value());
+ v[0].setTagValue(Value::Empty_Type, idx + 1);
} else {
- v->tag = Value::Empty_Type;
- v->uint_32 = d->freeList;
+ v->setTagValue(Value::Empty_Type, Value::fromReturnedValue(d->freeList).value());
}
d->freeList = idx;
if (d->attrs)
@@ -369,35 +374,37 @@ Heap::ArrayData *SparseArrayData::reallocate(Object *o, uint n, bool enforceAttr
uint SparseArrayData::allocate(Object *o, bool doubleSlot)
{
Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Sparse);
- Heap::SparseArrayData *dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (doubleSlot) {
- uint *last = &dd->freeList;
+ ReturnedValue *last = &dd->freeList;
while (1) {
- if (*last == UINT_MAX) {
+ if (Value::fromReturnedValue(*last).value() == UINT_MAX) {
reallocate(o, dd->alloc + 2, true);
- dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
last = &dd->freeList;
- Q_ASSERT(*last != UINT_MAX);
+ Q_ASSERT(Value::fromReturnedValue(*last).value() != UINT_MAX);
}
- Q_ASSERT(dd->arrayData[*last].uint_32 != *last);
- if (dd->arrayData[*last].uint_32 == (*last + 1)) {
+ Q_ASSERT(dd->arrayData[Value::fromReturnedValue(*last).value()].value() != Value::fromReturnedValue(*last).value());
+ if (dd->arrayData[Value::fromReturnedValue(*last).value()].value() == (Value::fromReturnedValue(*last).value() + 1)) {
// found two slots in a row
- uint idx = *last;
- *last = dd->arrayData[*last + 1].uint_32;
+ uint idx = Value::fromReturnedValue(*last).uint_32();
+ Value lastV = Value::fromReturnedValue(*last);
+ lastV.setValue(dd->arrayData[lastV.value() + 1].value());
+ *last = lastV.rawValue();
dd->attrs[idx] = Attr_Accessor;
return idx;
}
- last = &dd->arrayData[*last].uint_32;
+ last = &dd->arrayData[Value::fromReturnedValue(*last).value()].rawValueRef();
}
} else {
- if (dd->freeList == UINT_MAX) {
+ if (Value::fromReturnedValue(dd->freeList).value() == UINT_MAX) {
reallocate(o, dd->alloc + 1, false);
- dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
- uint idx = dd->freeList;
+ uint idx = Value::fromReturnedValue(dd->freeList).value();
Q_ASSERT(idx != UINT_MAX);
- dd->freeList = dd->arrayData[idx].uint_32;
+ dd->freeList = dd->arrayData[idx].uint_32();
if (dd->attrs)
dd->attrs[idx] = Attr_Data;
return idx;
@@ -418,12 +425,12 @@ bool SparseArrayData::put(Object *o, uint index, const Value &value)
if (value.isEmpty())
return true;
- Heap::SparseArrayData *s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *s = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *n = s->sparse->insert(index);
Q_ASSERT(n->value == UINT_MAX || !s->attrs || !s->attrs[n->value].isAccessor());
if (n->value == UINT_MAX)
n->value = allocate(o);
- s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ s = o->d()->arrayData.cast<Heap::SparseArrayData>();
s->arrayData[n->value] = value;
if (s->attrs)
s->attrs[n->value] = Attr_Data;
@@ -432,7 +439,7 @@ bool SparseArrayData::put(Object *o, uint index, const Value &value)
bool SparseArrayData::del(Object *o, uint index)
{
- Heap::SparseArrayData *dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *dd = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *n = dd->sparse->findNode(index);
if (!n)
@@ -452,13 +459,10 @@ bool SparseArrayData::del(Object *o, uint index)
if (isAccessor) {
// free up both indices
- dd->arrayData[pidx + 1].tag = Value::Empty_Type;
- dd->arrayData[pidx + 1].uint_32 = dd->freeList;
- dd->arrayData[pidx].tag = Value::Undefined_Type;
- dd->arrayData[pidx].uint_32 = pidx + 1;
+ dd->arrayData[pidx + 1].setTagValue(Value::Empty_Type, Value::fromReturnedValue(dd->freeList).value());
+ dd->arrayData[pidx].setTagValue(Value::Undefined_Type, pidx + 1);
} else {
- dd->arrayData[pidx].tag = Value::Empty_Type;
- dd->arrayData[pidx].uint_32 = dd->freeList;
+ dd->arrayData[pidx].setTagValue(Value::Empty_Type, Value::fromReturnedValue(dd->freeList).value());
}
dd->freeList = pidx;
@@ -468,28 +472,28 @@ bool SparseArrayData::del(Object *o, uint index)
void SparseArrayData::setAttribute(Object *o, uint index, PropertyAttributes attrs)
{
- Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *n = d->sparse->insert(index);
if (n->value == UINT_MAX) {
n->value = allocate(o, attrs.isAccessor());
- d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ d = o->d()->arrayData.cast<Heap::SparseArrayData>();
}
else if (attrs.isAccessor() != d->attrs[n->value].isAccessor()) {
// need to convert the slot
free(o->arrayData(), n->value);
n->value = allocate(o, attrs.isAccessor());
- d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ d = o->d()->arrayData.cast<Heap::SparseArrayData>();
}
d->attrs[n->value] = attrs;
}
void SparseArrayData::push_front(Object *o, const Value *values, uint n)
{
- Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>();
Q_ASSERT(!d->attrs);
for (int i = n - 1; i >= 0; --i) {
uint idx = allocate(o);
- d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ d = o->d()->arrayData.cast<Heap::SparseArrayData>();
d->arrayData[idx] = values[i];
d->sparse->push_front(idx);
}
@@ -497,7 +501,7 @@ void SparseArrayData::push_front(Object *o, const Value *values, uint n)
ReturnedValue SparseArrayData::pop_front(Object *o)
{
- Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>();
Q_ASSERT(!d->attrs);
uint idx = d->sparse->pop_front();
ReturnedValue v;
@@ -512,7 +516,7 @@ ReturnedValue SparseArrayData::pop_front(Object *o)
uint SparseArrayData::truncate(Object *o, uint newLen)
{
- Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *begin = d->sparse->lowerBound(newLen);
if (begin != d->sparse->end()) {
SparseArrayNode *it = d->sparse->end()->previousNode();
@@ -580,7 +584,7 @@ uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n)
ScopedValue v(scope);
for (const SparseArrayNode *it = os->sparse->begin();
it != os->sparse->end(); it = it->nextNode()) {
- v = otherObj->getValue(reinterpret_cast<Property *>(os->arrayData + it->value), other->d()->attrs[it->value]);
+ v = otherObj->getValue(os->arrayData[it->value], other->d()->attrs[it->value]);
obj->arraySet(oldSize + it->key(), v);
}
} else {
@@ -603,14 +607,14 @@ uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n)
return oldSize + n;
}
-Property *ArrayData::insert(Object *o, uint index, bool isAccessor)
+void ArrayData::insert(Object *o, uint index, const Value *v, bool isAccessor)
{
if (!isAccessor && o->d()->arrayData->type != Heap::ArrayData::Sparse) {
- Heap::SimpleArrayData *d = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *d = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (index < 0x1000 || index < d->len + (d->len >> 2)) {
if (index >= d->alloc) {
o->arrayReserve(index + 1);
- d = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ d = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
if (index >= d->len) {
// mark possible hole in the array
@@ -618,17 +622,20 @@ Property *ArrayData::insert(Object *o, uint index, bool isAccessor)
d->data(i) = Primitive::emptyValue();
d->len = index + 1;
}
- return reinterpret_cast<Property *>(d->arrayData + d->mappedIndex(index));
+ d->arrayData[d->mappedIndex(index)] = *v;
+ return;
}
}
o->initSparseArray();
- Heap::SparseArrayData *s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *s = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *n = s->sparse->insert(index);
if (n->value == UINT_MAX)
n->value = SparseArrayData::allocate(o, isAccessor);
- s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
- return reinterpret_cast<Property *>(s->arrayData + n->value);
+ s = o->d()->arrayData.cast<Heap::SparseArrayData>();
+ s->arrayData[n->value] = *v;
+ if (isAccessor)
+ s->arrayData[n->value + Object::SetterOffset] = v[Object::SetterOffset];
}
@@ -737,7 +744,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
if (!arrayData || !arrayData->length())
return;
- if (!(comparefn.isUndefined() || comparefn.asObject())) {
+ if (!(comparefn.isUndefined() || comparefn.as<Object>())) {
engine->throwTypeError();
return;
}
@@ -755,7 +762,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
thisObject->setArrayData(0);
ArrayData::realloc(thisObject, Heap::ArrayData::Simple, sparse->sparse()->nEntries(), sparse->attrs() ? true : false);
- Heap::SimpleArrayData *d = static_cast<Heap::SimpleArrayData *>(thisObject->d()->arrayData);
+ Heap::SimpleArrayData *d = thisObject->d()->arrayData.cast<Heap::SimpleArrayData>();
SparseArrayNode *n = sparse->sparse()->begin();
uint i = 0;
@@ -765,7 +772,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
break;
PropertyAttributes a = sparse->attrs() ? sparse->attrs()[n->value] : Attr_Data;
- d->data(i) = thisObject->getValue(reinterpret_cast<Property *>(sparse->arrayData() + n->value), a);
+ d->data(i) = thisObject->getValue(sparse->arrayData()[n->value], a);
d->attrs[i] = a.isAccessor() ? Attr_Data : a;
n = n->nextNode();
@@ -795,7 +802,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
}
} else {
- Heap::SimpleArrayData *d = static_cast<Heap::SimpleArrayData *>(thisObject->d()->arrayData);
+ Heap::SimpleArrayData *d = thisObject->d()->arrayData.cast<Heap::SimpleArrayData>();
if (len > d->len)
len = d->len;
diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h
index 915e862bbb..48d2b9dbbf 100644
--- a/src/qml/jsruntime/qv4arraydata_p.h
+++ b/src/qml/jsruntime/qv4arraydata_p.h
@@ -33,6 +33,17 @@
#ifndef QV4ARRAYDATA_H
#define QV4ARRAYDATA_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4managed_p.h"
#include "qv4property_p.h"
@@ -47,17 +58,17 @@ namespace QV4 {
Q_MANAGED_CHECK \
typedef QV4::Heap::DataClass Data; \
static const QV4::ArrayVTable static_vtbl; \
- static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+ static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \
V4_MANAGED_SIZE_TEST \
- const Data *d() const { return static_cast<const Data *>(m); } \
- Data *d() { return static_cast<Data *>(m); }
+ const Data *d() const { return static_cast<const Data *>(m()); } \
+ Data *d() { return static_cast<Data *>(m()); }
struct ArrayData;
struct ArrayVTable
{
- ManagedVTable managedVTable;
+ VTable vTable;
uint type;
Heap::ArrayData *(*reallocate)(Object *o, uint n, bool enforceAttributes);
ReturnedValue (*get)(const Heap::ArrayData *d, uint index);
@@ -86,7 +97,7 @@ struct ArrayData : public Base {
PropertyAttributes *attrs;
union {
uint len;
- uint freeList;
+ ReturnedValue freeList;
};
union {
uint offset;
@@ -96,12 +107,15 @@ struct ArrayData : public Base {
bool isSparse() const { return type == Sparse; }
- const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(Base::vtable); }
+ const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(Base::vtable()); }
inline ReturnedValue get(uint i) const {
return vtable()->get(this, i);
}
+ inline void getProperty(uint index, Property *p, PropertyAttributes *attrs);
+ inline void setProperty(uint index, const Property *p);
inline Property *getProperty(uint index);
+ inline Value *getValueOrSetter(uint index, PropertyAttributes *attrs);
inline PropertyAttributes attributes(uint i) const;
bool isEmpty(uint i) const {
@@ -205,7 +219,7 @@ struct Q_QML_EXPORT ArrayData : public Managed
static void sort(ExecutionEngine *engine, Object *thisObject, const Value &comparefn, uint dataLen);
static uint append(Object *obj, ArrayObject *otherObj, uint n);
- static Property *insert(Object *o, uint index, bool isAccessor = false);
+ static void insert(Object *o, uint index, const Value *v, bool isAccessor = false);
};
struct Q_QML_EXPORT SimpleArrayData : public ArrayData
@@ -239,8 +253,8 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData
V4_ARRAYDATA(SparseArrayData)
V4_NEEDS_DESTROY
- uint &freeList() { return d()->freeList; }
- uint freeList() const { return d()->freeList; }
+ ReturnedValue &freeList() { return d()->freeList; }
+ ReturnedValue freeList() const { return d()->freeList; }
SparseArray *sparse() const { return d()->sparse; }
void setSparse(SparseArray *s) { d()->sparse = s; }
@@ -270,6 +284,25 @@ inline SparseArrayData::~SparseArrayData()
delete sparse;
}
+void ArrayData::getProperty(uint index, Property *p, PropertyAttributes *attrs)
+{
+ Property *pd = getProperty(index);
+ Q_ASSERT(pd);
+ *attrs = attributes(index);
+ p->value = pd->value;
+ if (attrs->isAccessor())
+ p->set = pd->set;
+}
+
+void ArrayData::setProperty(uint index, const Property *p)
+{
+ Property *pd = getProperty(index);
+ Q_ASSERT(pd);
+ pd->value = p->value;
+ if (attributes(index).isAccessor())
+ pd->set = p->set;
+}
+
inline Property *ArrayData::getProperty(uint index)
{
if (isSparse())
@@ -284,6 +317,19 @@ inline PropertyAttributes ArrayData::attributes(uint i) const
return static_cast<const SimpleArrayData *>(this)->attributes(i);
}
+Value *ArrayData::getValueOrSetter(uint index, PropertyAttributes *attrs)
+{
+ Property *p = getProperty(index);
+ if (!p) {
+ *attrs = Attr_Invalid;
+ return 0;
+ }
+
+ *attrs = attributes(index);
+ return attrs->isAccessor() ? &p->set : &p->value;
+}
+
+
}
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 231eb93dd5..25d3d9329b 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -37,6 +37,7 @@
#include "qv4scopedvalue_p.h"
#include "qv4argumentsobject_p.h"
#include "qv4runtime_p.h"
+#include "qv4string_p.h"
using namespace QV4;
@@ -47,9 +48,9 @@ Heap::ArrayCtor::ArrayCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue ArrayCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ArrayCtor::construct(const Managed *m, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<ArrayCtor *>(m)->engine();
+ ExecutionEngine *v4 = static_cast<const ArrayCtor *>(m)->engine();
Scope scope(v4);
ScopedArrayObject a(scope, v4->newArrayObject());
uint len;
@@ -72,7 +73,7 @@ ReturnedValue ArrayCtor::construct(Managed *m, CallData *callData)
return a.asReturnedValue();
}
-ReturnedValue ArrayCtor::call(Managed *that, CallData *callData)
+ReturnedValue ArrayCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
@@ -81,11 +82,11 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
ctor->defineDefaultProperty(QStringLiteral("isArray"), method_isArray, 1);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString, 0);
+ defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString, 0);
defineDefaultProperty(QStringLiteral("concat"), method_concat, 1);
defineDefaultProperty(QStringLiteral("join"), method_join, 1);
@@ -110,7 +111,7 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor)
ReturnedValue ArrayPrototype::method_isArray(CallContext *ctx)
{
- bool isArray = ctx->argc() && ctx->args()[0].asArrayObject();
+ bool isArray = ctx->argc() && ctx->args()[0].as<ArrayObject>();
return Encode(isArray);
}
@@ -185,7 +186,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
r4 = arg->toQString();
ScopedObject self(scope, ctx->thisObject());
- ScopedValue length(scope, self->get(ctx->d()->engine->id_length));
+ ScopedValue length(scope, self->get(ctx->d()->engine->id_length()));
const quint32 r2 = length->isUndefined() ? 0 : length->toUInt32();
if (!r2)
@@ -194,7 +195,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
QString R;
// ### FIXME
- if (ArrayObject *a = self->asArrayObject()) {
+ if (ArrayObject *a = self->as<ArrayObject>()) {
ScopedValue e(scope);
for (uint i = 0; i < a->getLength(); ++i) {
if (i)
@@ -242,7 +243,7 @@ ReturnedValue ArrayPrototype::method_pop(CallContext *ctx)
if (!len) {
if (!instance->isArrayObject())
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromInt32(0)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0)));
return Encode::undefined();
}
@@ -256,7 +257,7 @@ ReturnedValue ArrayPrototype::method_pop(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLength(len - 1);
else
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - 1)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1)));
return result->asReturnedValue();
}
@@ -282,7 +283,7 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
}
double newLen = l + ctx->argc();
if (!instance->isArrayObject())
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen)));
else {
ScopedString str(scope, ctx->d()->engine->newString(QStringLiteral("Array.prototype.push: Overflow")));
return ctx->engine()->throwRangeError(str);
@@ -303,7 +304,7 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(len);
else
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len)));
return Encode(len);
}
@@ -354,7 +355,7 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
if (!len) {
if (!instance->isArrayObject())
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromInt32(0)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0)));
return Encode::undefined();
}
@@ -388,7 +389,7 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(len - 1);
else
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - 1)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1)));
return result->asReturnedValue();
}
@@ -523,7 +524,7 @@ ReturnedValue ArrayPrototype::method_splice(CallContext *ctx)
}
ctx->d()->strictMode = true;
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount)));
return newArray.asReturnedValue();
}
@@ -561,7 +562,7 @@ ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(newLen);
else
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen)));
return Encode(newLen);
}
@@ -619,7 +620,7 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx)
return Encode(-1);
} else {
Q_ASSERT(instance->arrayType() == Heap::ArrayData::Simple || instance->arrayType() == Heap::ArrayData::Complex);
- Heap::SimpleArrayData *sa = static_cast<Heap::SimpleArrayData *>(instance->d()->arrayData);
+ Heap::SimpleArrayData *sa = instance->d()->arrayData.cast<Heap::SimpleArrayData>();
if (len > sa->len)
len = sa->len;
uint idx = fromIndex;
diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h
index 4e67eb2e31..afd8080fa3 100644
--- a/src/qml/jsruntime/qv4arrayobject_p.h
+++ b/src/qml/jsruntime/qv4arrayobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4ARRAYOBJECT_H
#define QV4ARRAYOBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include <QtCore/qnumeric.h>
@@ -53,8 +64,8 @@ struct ArrayCtor: FunctionObject
{
V4_OBJECT2(ArrayCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct ArrayPrototype: ArrayObject
diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp
index 9c293e783b..53f8abf3f2 100644
--- a/src/qml/jsruntime/qv4booleanobject.cpp
+++ b/src/qml/jsruntime/qv4booleanobject.cpp
@@ -32,6 +32,7 @@
****************************************************************************/
#include "qv4booleanobject_p.h"
+#include "qv4string_p.h"
using namespace QV4;
@@ -43,14 +44,14 @@ Heap::BooleanCtor::BooleanCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue BooleanCtor::construct(Managed *m, CallData *callData)
+ReturnedValue BooleanCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<BooleanCtor *>(m)->engine());
+ Scope scope(static_cast<const BooleanCtor *>(m)->engine());
bool n = callData->argc ? callData->args[0].toBoolean() : false;
return Encode(scope.engine->newBooleanObject(n));
}
-ReturnedValue BooleanCtor::call(Managed *, CallData *callData)
+ReturnedValue BooleanCtor::call(const Managed *, CallData *callData)
{
bool value = callData->argc ? callData->args[0].toBoolean() : 0;
return Encode(value);
@@ -60,11 +61,11 @@ void BooleanPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString);
- defineDefaultProperty(engine->id_valueOf, method_valueOf);
+ defineDefaultProperty(engine->id_toString(), method_toString);
+ defineDefaultProperty(engine->id_valueOf(), method_valueOf);
}
ReturnedValue BooleanPrototype::method_toString(CallContext *ctx)
@@ -73,7 +74,7 @@ ReturnedValue BooleanPrototype::method_toString(CallContext *ctx)
if (ctx->thisObject().isBoolean()) {
result = ctx->thisObject().booleanValue();
} else {
- BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
+ const BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
if (!thisObject)
return ctx->engine()->throwTypeError();
result = thisObject->value();
@@ -87,7 +88,7 @@ ReturnedValue BooleanPrototype::method_valueOf(CallContext *ctx)
if (ctx->thisObject().isBoolean())
return ctx->thisObject().asReturnedValue();
- BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
+ const BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
if (!thisObject)
return ctx->engine()->throwTypeError();
diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h
index 903261bdce..203c8ba4ea 100644
--- a/src/qml/jsruntime/qv4booleanobject_p.h
+++ b/src/qml/jsruntime/qv4booleanobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4BOOLEANOBJECT_H
#define QV4BOOLEANOBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include <QtCore/qnumeric.h>
@@ -53,8 +64,8 @@ struct BooleanCtor: FunctionObject
{
V4_OBJECT2(BooleanCtor, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct BooleanPrototype: BooleanObject
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 9330f10780..007bf92639 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -36,10 +36,12 @@
#include <qv4context_p.h>
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include <qv4argumentsobject_p.h>
#include "qv4function_p.h"
#include "qv4errorobject_p.h"
+#include "qv4string_p.h"
+#include "private/qqmlcontextwrapper_p.h"
using namespace QV4;
@@ -48,8 +50,9 @@ DEFINE_MANAGED_VTABLE(CallContext);
DEFINE_MANAGED_VTABLE(WithContext);
DEFINE_MANAGED_VTABLE(CatchContext);
DEFINE_MANAGED_VTABLE(GlobalContext);
+DEFINE_MANAGED_VTABLE(QmlContext);
-Heap::CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData)
+Heap::CallContext *ExecutionContext::newCallContext(const FunctionObject *function, CallData *callData)
{
Q_ASSERT(function->function());
@@ -80,39 +83,64 @@ Heap::CallContext *ExecutionContext::newCallContext(FunctionObject *function, Ca
return c;
}
-Heap::WithContext *ExecutionContext::newWithContext(Object *with)
+Heap::WithContext *ExecutionContext::newWithContext(Heap::Object *with)
{
- return d()->engine->memoryManager->alloc<WithContext>(d()->engine, with);
+ return d()->engine->memoryManager->alloc<WithContext>(d(), with);
}
-Heap::CatchContext *ExecutionContext::newCatchContext(String *exceptionVarName, const Value &exceptionValue)
+Heap::CatchContext *ExecutionContext::newCatchContext(Heap::String *exceptionVarName, ReturnedValue exceptionValue)
{
- return d()->engine->memoryManager->alloc<CatchContext>(d()->engine, exceptionVarName, exceptionValue);
+ Scope scope(this);
+ ScopedValue e(scope, exceptionValue);
+ return d()->engine->memoryManager->alloc<CatchContext>(d(), exceptionVarName, e);
}
-Heap::CallContext *ExecutionContext::newQmlContext(FunctionObject *f, Object *qml)
+Heap::QmlContext *ExecutionContext::newQmlContext(QmlContextWrapper *qml)
{
- Scope scope(this);
- Scoped<CallContext> c(scope, d()->engine->memoryManager->allocManaged<CallContext>(requiredMemoryForExecutionContect(f, 0)));
- new (c->d()) Heap::CallContext(d()->engine, qml, f);
- return c->d();
+ Heap::QmlContext *c = d()->engine->memoryManager->alloc<QmlContext>(this, qml);
+ return c;
}
-
+Heap::QmlContext *ExecutionContext::newQmlContext(QQmlContextData *context, QObject *scopeObject)
+{
+ Scope scope(this);
+ Scoped<QmlContextWrapper> qml(scope, QmlContextWrapper::qmlScope(scope.engine, context, scopeObject));
+ Heap::QmlContext *c = d()->engine->memoryManager->alloc<QmlContext>(this, qml);
+ return c;
+}
void ExecutionContext::createMutableBinding(String *name, bool deletable)
{
Scope scope(this);
// find the right context to create the binding on
- ScopedObject activation(scope, d()->engine->globalObject());
+ ScopedObject activation(scope);
ScopedContext ctx(scope, this);
while (ctx) {
- if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
- if (!c->activation)
- c->activation = scope.engine->newObject();
- activation = c->activation;
+ if (!activation) {
+ if (!c->activation)
+ c->activation = scope.engine->newObject();
+ activation = c->activation;
+ }
+ break;
+ }
+ case Heap::ExecutionContext::Type_QmlContext: {
+ // this is ugly, as it overrides the inner callcontext, but has to stay as long
+ // as bindings still get their own callcontext
+ Heap::QmlContext *qml = static_cast<Heap::QmlContext *>(ctx->d());
+ activation = qml->qml;
+ break;
+ }
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ if (!activation)
+ activation = scope.engine->globalObject;
+ break;
+ }
+ default:
break;
}
ctx = ctx->d()->outer;
@@ -130,57 +158,46 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable)
Heap::GlobalContext::GlobalContext(ExecutionEngine *eng)
: Heap::ExecutionContext(eng, Heap::ExecutionContext::Type_GlobalContext)
{
- global = eng->globalObject()->d();
+ global = eng->globalObject->d();
}
-Heap::WithContext::WithContext(ExecutionEngine *engine, QV4::Object *with)
- : Heap::ExecutionContext(engine, Heap::ExecutionContext::Type_WithContext)
+Heap::WithContext::WithContext(ExecutionContext *outerContext, Object *with)
+ : Heap::ExecutionContext(outerContext->engine, Heap::ExecutionContext::Type_WithContext)
{
- callData = parent->callData;
- outer = parent;
- lookups = parent->lookups;
- compilationUnit = parent->compilationUnit;
+ outer = outerContext;
+ callData = outer->callData;
+ lookups = outer->lookups;
+ compilationUnit = outer->compilationUnit;
- withObject = with ? with->d() : 0;
+ withObject = with;
}
-Heap::CatchContext::CatchContext(ExecutionEngine *engine, QV4::String *exceptionVarName, const Value &exceptionValue)
- : Heap::ExecutionContext(engine, Heap::ExecutionContext::Type_CatchContext)
+Heap::CatchContext::CatchContext(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue)
+ : Heap::ExecutionContext(outerContext->engine, Heap::ExecutionContext::Type_CatchContext)
{
- strictMode = parent->strictMode;
- callData = parent->callData;
- outer = parent;
- lookups = parent->lookups;
- compilationUnit = parent->compilationUnit;
+ outer = outerContext;
+ strictMode = outer->strictMode;
+ callData = outer->callData;
+ lookups = outer->lookups;
+ compilationUnit = outer->compilationUnit;
this->exceptionVarName = exceptionVarName;
this->exceptionValue = exceptionValue;
}
-Heap::CallContext::CallContext(ExecutionEngine *engine, QV4::Object *qml, QV4::FunctionObject *function)
- : Heap::ExecutionContext(engine, Heap::ExecutionContext::Type_QmlContext)
+Heap::QmlContext::QmlContext(QV4::ExecutionContext *outerContext, QV4::QmlContextWrapper *qml)
+ : Heap::ExecutionContext(outerContext->engine(), Heap::ExecutionContext::Type_QmlContext)
{
- this->function = function->d();
- callData = reinterpret_cast<CallData *>(this + 1);
- callData->tag = QV4::Value::_Integer_Type;
- callData->argc = 0;
- callData->thisObject = Primitive::undefinedValue();
-
+ outer = outerContext->d();
strictMode = false;
- outer = function->scope();
+ callData = outer->callData;
+ lookups = outer->lookups;
+ compilationUnit = outer->compilationUnit;
- activation = qml->d();
-
- if (function->function()) {
- compilationUnit = function->function()->compilationUnit;
- lookups = compilationUnit->runtimeLookups;
- }
-
- locals = (Value *)(this + 1);
- if (function->varCount())
- std::fill(locals, locals + function->varCount(), Primitive::undefinedValue());
+ this->qml = qml->d();
}
+
Identifier * const *CallContext::formals() const
{
return (d()->function && d()->function->function) ? d()->function->function->internalClass->nameMap.constData() : 0;
@@ -209,16 +226,28 @@ bool ExecutionContext::deleteProperty(String *name)
bool hasWith = false;
ScopedContext ctx(scope, this);
for (; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name->d()))
+ return false;
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
hasWith = true;
ScopedObject withObject(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
if (withObject->hasProperty(name))
return withObject->deleteProperty(name);
- } else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) {
- Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
- if (c->exceptionVarName->isEqualTo(name))
- return false;
- } else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ break;
+ }
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ if (global->hasProperty(name))
+ return global->deleteProperty(name);
+ break;
+ }
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
ScopedFunctionObject f(scope, c->function);
if (f->needsActivation() || hasWith) {
@@ -227,13 +256,14 @@ bool ExecutionContext::deleteProperty(String *name)
// ### throw in strict mode?
return false;
}
- ScopedObject activation(scope, c->activation);
- if (activation && activation->hasProperty(name))
- return activation->deleteProperty(name);
- } else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
- ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
- if (global->hasProperty(name))
- return global->deleteProperty(name);
+ ScopedObject qml(scope, c->activation);
+ if (qml && qml->hasProperty(name))
+ return qml->deleteProperty(name);
+ break;
+ }
+ case Heap::ExecutionContext::Type_QmlContext:
+ // can't delete properties on qml objects
+ break;
}
}
@@ -254,7 +284,27 @@ void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine)
if (ctx->outer)
ctx->outer->mark(engine);
- if (ctx->type >= Heap::ExecutionContext::Type_CallContext) {
+ switch (ctx->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ CatchContext::Data *c = static_cast<CatchContext::Data *>(ctx);
+ c->exceptionVarName->mark(engine);
+ c->exceptionValue.mark(engine);
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
+ WithContext::Data *w = static_cast<WithContext::Data *>(ctx);
+ if (w->withObject)
+ w->withObject->mark(engine);
+ break;
+ }
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ GlobalContext::Data *g = static_cast<GlobalContext::Data *>(ctx);
+ g->global->mark(engine);
+ break;
+ }
+ case Heap::ExecutionContext::Type_SimpleCallContext:
+ break;
+ case Heap::ExecutionContext::Type_CallContext: {
QV4::Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx);
ctx->callData->thisObject.mark(engine);
for (int arg = 0; arg < qMax(ctx->callData->argc, (int)c->function->formalParameterCount()); ++arg)
@@ -264,17 +314,13 @@ void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine)
if (c->activation)
c->activation->mark(engine);
c->function->mark(engine);
- } else if (ctx->type == Heap::ExecutionContext::Type_WithContext) {
- WithContext::Data *w = static_cast<WithContext::Data *>(ctx);
- if (w->withObject)
- w->withObject->mark(engine);
- } else if (ctx->type == Heap::ExecutionContext::Type_CatchContext) {
- CatchContext::Data *c = static_cast<CatchContext::Data *>(ctx);
- c->exceptionVarName->mark(engine);
- c->exceptionValue.mark(engine);
- } else if (ctx->type == Heap::ExecutionContext::Type_GlobalContext) {
- GlobalContext::Data *g = static_cast<GlobalContext::Data *>(ctx);
- g->global->mark(engine);
+ break;
+ }
+ case Heap::ExecutionContext::Type_QmlContext: {
+ QmlContext::Data *g = static_cast<QmlContext::Data *>(ctx);
+ g->qml->mark(engine);
+ break;
+ }
}
}
@@ -282,57 +328,71 @@ void ExecutionContext::setProperty(String *name, const Value &value)
{
Scope scope(this);
ScopedContext ctx(scope, this);
+ ScopedObject activation(scope);
+
for (; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ activation = (Object *)0;
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name->d())) {
+ c->exceptionValue = value;
+ return;
+ }
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
if (w->hasProperty(name)) {
w->put(name, value);
return;
}
- } else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext && static_cast<Heap::CatchContext *>(ctx->d())->exceptionVarName->isEqualTo(name)) {
- static_cast<Heap::CatchContext *>(ctx->d())->exceptionValue = value;
- return;
- } else {
- ScopedObject activation(scope, (Object *)0);
- if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
- Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
- if (c->function->function) {
- uint index = c->function->function->internalClass->find(name);
- if (index < UINT_MAX) {
- if (index < c->function->formalParameterCount()) {
- c->callData->args[c->function->formalParameterCount() - index - 1] = value;
- } else {
- index -= c->function->formalParameterCount();
- c->locals[index] = value;
- }
- return;
+ break;
+ }
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ activation = static_cast<Heap::GlobalContext *>(ctx->d())->global;
+ break;
+ }
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
+ Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
+ if (c->function->function) {
+ uint index = c->function->function->internalClass->find(name);
+ if (index < UINT_MAX) {
+ if (index < c->function->formalParameterCount()) {
+ c->callData->args[c->function->formalParameterCount() - index - 1] = value;
+ } else {
+ index -= c->function->formalParameterCount();
+ c->locals[index] = value;
}
+ return;
}
- activation = c->activation;
- } else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
- activation = static_cast<Heap::GlobalContext *>(ctx->d())->global;
}
+ activation = c->activation;
+ break;
+ }
+ case Heap::ExecutionContext::Type_QmlContext: {
+ activation = static_cast<Heap::QmlContext *>(ctx->d())->qml;
+ activation->put(name, value);
+ return;
+ }
+ }
- if (activation) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_QmlContext) {
- activation->put(name, value);
- return;
- } else {
- uint member = activation->internalClass()->find(name);
- if (member < UINT_MAX) {
- activation->putValue(activation->propertyAt(member), activation->internalClass()->propertyData[member], value);
- return;
- }
- }
+ if (activation) {
+ uint member = activation->internalClass()->find(name);
+ if (member < UINT_MAX) {
+ activation->putValue(member, value);
+ return;
}
}
}
- if (d()->strictMode || name->equals(d()->engine->id_this)) {
+
+ if (d()->strictMode || name->equals(d()->engine->id_this())) {
ScopedValue n(scope, name->asReturnedValue());
engine()->throwReferenceError(n);
return;
}
- d()->engine->globalObject()->put(name, value);
+ d()->engine->globalObject->put(name, value);
}
ReturnedValue ExecutionContext::getProperty(String *name)
@@ -341,14 +401,22 @@ ReturnedValue ExecutionContext::getProperty(String *name)
ScopedValue v(scope);
name->makeIdentifier(scope.engine);
- if (name->equals(d()->engine->id_this))
+ if (name->equals(d()->engine->id_this()))
return thisObject().asReturnedValue();
bool hasWith = false;
bool hasCatchScope = false;
ScopedContext ctx(scope, this);
for (; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ hasCatchScope = true;
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name->d()))
+ return c->exceptionValue.asReturnedValue();
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
hasWith = true;
bool hasProperty = false;
@@ -356,17 +424,18 @@ ReturnedValue ExecutionContext::getProperty(String *name)
if (hasProperty) {
return v->asReturnedValue();
}
- continue;
+ break;
}
-
- else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) {
- hasCatchScope = true;
- Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
- if (c->exceptionVarName->isEqualTo(name))
- return c->exceptionValue.asReturnedValue();
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ bool hasProperty = false;
+ v = global->get(name, &hasProperty);
+ if (hasProperty)
+ return v->asReturnedValue();
+ break;
}
-
- else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
ScopedFunctionObject f(scope, c->function);
if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) {
@@ -387,85 +456,97 @@ ReturnedValue ExecutionContext::getProperty(String *name)
if (f->function() && f->function()->isNamedExpression()
&& name->equals(ScopedString(scope, f->function()->name())))
return f.asReturnedValue();
+ break;
}
-
- else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
- ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ case Heap::ExecutionContext::Type_QmlContext: {
+ ScopedObject qml(scope, static_cast<Heap::QmlContext *>(ctx->d())->qml);
bool hasProperty = false;
- v = global->get(name, &hasProperty);
+ v = qml->get(name, &hasProperty);
if (hasProperty)
return v->asReturnedValue();
+ break;
+ }
}
}
ScopedValue n(scope, name);
return engine()->throwReferenceError(n);
}
-ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Heap::Object **base)
+ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Value *base)
{
Scope scope(this);
ScopedValue v(scope);
- *base = (Heap::Object *)0;
+ base->setM(0);
name->makeIdentifier(scope.engine);
- if (name->equals(d()->engine->id_this))
+ if (name->equals(d()->engine->id_this()))
return thisObject().asReturnedValue();
bool hasWith = false;
bool hasCatchScope = false;
ScopedContext ctx(scope, this);
for (; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ hasCatchScope = true;
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name->d()))
+ return c->exceptionValue.asReturnedValue();
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
hasWith = true;
bool hasProperty = false;
v = w->get(name, &hasProperty);
if (hasProperty) {
- *base = w->d();
+ base->setM(w->d());
return v->asReturnedValue();
}
- continue;
+ break;
}
-
- else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) {
- hasCatchScope = true;
- Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
- if (c->exceptionVarName->isEqualTo(name))
- return c->exceptionValue.asReturnedValue();
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ bool hasProperty = false;
+ v = global->get(name, &hasProperty);
+ if (hasProperty)
+ return v->asReturnedValue();
+ break;
}
-
- else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
ScopedFunctionObject f(scope, c->function);
if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) {
uint index = f->function()->internalClass->find(name);
if (index < UINT_MAX) {
- if (index < f->formalParameterCount())
- return c->callData->args[f->formalParameterCount() - index - 1].asReturnedValue();
- return c->locals[index - f->formalParameterCount()].asReturnedValue();
+ if (index < c->function->formalParameterCount())
+ return c->callData->args[c->function->formalParameterCount() - index - 1].asReturnedValue();
+ return c->locals[index - c->function->formalParameterCount()].asReturnedValue();
}
}
ScopedObject activation(scope, c->activation);
if (activation) {
bool hasProperty = false;
v = activation->get(name, &hasProperty);
- if (hasProperty) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_QmlContext)
- *base = activation->d();
+ if (hasProperty)
return v->asReturnedValue();
- }
}
if (f->function() && f->function()->isNamedExpression()
&& name->equals(ScopedString(scope, f->function()->name())))
- return c->function->asReturnedValue();
+ return f.asReturnedValue();
+ break;
}
-
- else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
- ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ case Heap::ExecutionContext::Type_QmlContext: {
+ ScopedObject qml(scope, static_cast<Heap::QmlContext *>(ctx->d())->qml);
bool hasProperty = false;
- v = global->get(name, &hasProperty);
- if (hasProperty)
+ v = qml->get(name, &hasProperty);
+ if (hasProperty) {
+ base->setM(qml->d());
return v->asReturnedValue();
+ }
+ break;
+ }
}
}
ScopedValue n(scope, name);
@@ -476,7 +557,7 @@ Heap::FunctionObject *ExecutionContext::getFunctionObject() const
{
Scope scope(d()->engine);
ScopedContext it(scope, this->d());
- for (; it; it = it->d()->parent) {
+ for (; it; it = it->d()->outer) {
if (const CallContext *callCtx = it->asCallContext())
return callCtx->d()->function;
else if (it->asCatchContext() || it->asWithContext())
@@ -487,3 +568,19 @@ Heap::FunctionObject *ExecutionContext::getFunctionObject() const
return 0;
}
+
+
+QObject *QmlContext::qmlScope() const
+{
+ return d()->qml->scopeObject;
+}
+
+QQmlContextData *QmlContext::qmlContext() const
+{
+ return d()->qml->context;
+}
+
+void QmlContext::takeContextOwnership() {
+ d()->qml->ownsContext = true;
+}
+
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 8392dd836d..6c360e7dda 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -33,11 +33,25 @@
#ifndef QMLJS_ENVIRONMENT_H
#define QMLJS_ENVIRONMENT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4managed_p.h"
QT_BEGIN_NAMESPACE
+class QQmlContextData;
+class QObject;
+
namespace QV4 {
namespace CompiledData {
@@ -45,6 +59,8 @@ struct CompilationUnit;
struct Function;
}
+struct QmlContextWrapper;
+struct Identifier;
struct CallContext;
struct CatchContext;
struct WithContext;
@@ -74,9 +90,9 @@ struct ExecutionContext : Base {
Type_GlobalContext = 0x1,
Type_CatchContext = 0x2,
Type_WithContext = 0x3,
- Type_SimpleCallContext = 0x4,
- Type_CallContext = 0x5,
- Type_QmlContext = 0x6
+ Type_QmlContext = 0x4,
+ Type_SimpleCallContext = 0x5,
+ Type_CallContext = 0x6
};
inline ExecutionContext(ExecutionEngine *engine, ContextType t);
@@ -84,8 +100,7 @@ struct ExecutionContext : Base {
CallData *callData;
ExecutionEngine *engine;
- ExecutionContext *parent;
- ExecutionContext *outer;
+ Pointer<ExecutionContext> outer;
Lookup *lookups;
CompiledData::CompilationUnit *compilationUnit;
@@ -94,6 +109,18 @@ struct ExecutionContext : Base {
int lineNumber;
};
+inline
+ExecutionContext::ExecutionContext(ExecutionEngine *engine, ContextType t)
+ : engine(engine)
+ , outer(0)
+ , lookups(0)
+ , compilationUnit(0)
+ , type(t)
+ , strictMode(false)
+ , lineNumber(-1)
+{}
+
+
struct CallContext : ExecutionContext {
CallContext(ExecutionEngine *engine, ContextType t = Type_SimpleCallContext)
: ExecutionContext(engine, t)
@@ -102,29 +129,34 @@ struct CallContext : ExecutionContext {
locals = 0;
activation = 0;
}
- CallContext(ExecutionEngine *engine, QV4::Object *qml, QV4::FunctionObject *function);
- FunctionObject *function;
+ Pointer<FunctionObject> function;
Value *locals;
- Object *activation;
+ Pointer<Object> activation;
};
struct GlobalContext : ExecutionContext {
GlobalContext(ExecutionEngine *engine);
- Object *global;
+ Pointer<Object> global;
};
struct CatchContext : ExecutionContext {
- CatchContext(ExecutionEngine *engine, QV4::String *exceptionVarName, const Value &exceptionValue);
- StringValue exceptionVarName;
+ CatchContext(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue);
+ Pointer<String> exceptionVarName;
Value exceptionValue;
};
struct WithContext : ExecutionContext {
- WithContext(ExecutionEngine *engine, QV4::Object *with);
- Object *withObject;
+ WithContext(ExecutionContext *outerContext, Object *with);
+ Pointer<Object> withObject;
};
+struct QmlContextWrapper;
+
+struct QmlContext : ExecutionContext {
+ QmlContext(QV4::ExecutionContext *outerContext, QV4::QmlContextWrapper *qml);
+ Pointer<QmlContextWrapper> qml;
+};
}
@@ -139,16 +171,17 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
ExecutionEngine *engine() const { return d()->engine; }
- Heap::CallContext *newCallContext(FunctionObject *f, CallData *callData);
- Heap::WithContext *newWithContext(Object *with);
- Heap::CatchContext *newCatchContext(String *exceptionVarName, const Value &exceptionValue);
- Heap::CallContext *newQmlContext(FunctionObject *f, Object *qml);
+ Heap::CallContext *newCallContext(const FunctionObject *f, CallData *callData);
+ Heap::WithContext *newWithContext(Heap::Object *with);
+ Heap::CatchContext *newCatchContext(Heap::String *exceptionVarName, ReturnedValue exceptionValue);
+ Heap::QmlContext *newQmlContext(QmlContextWrapper *qml);
+ Heap::QmlContext *newQmlContext(QQmlContextData *context, QObject *scopeObject);
void createMutableBinding(String *name, bool deletable);
void setProperty(String *name, const Value &value);
ReturnedValue getProperty(String *name);
- ReturnedValue getPropertyAndBase(String *name, Heap::Object **base);
+ ReturnedValue getPropertyAndBase(String *name, Value *base);
bool deleteProperty(String *name);
inline CallContext *asCallContext();
@@ -160,7 +193,7 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
static void markObjects(Heap::Base *m, ExecutionEngine *e);
- const Value &thisObject() const {
+ Value &thisObject() const {
return d()->callData->thisObject;
}
int argc() const {
@@ -174,7 +207,7 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
}
};
-struct CallContext : public ExecutionContext
+struct Q_QML_EXPORT CallContext : public ExecutionContext
{
V4_MANAGED(CallContext, ExecutionContext)
@@ -208,6 +241,16 @@ struct WithContext : public ExecutionContext
V4_MANAGED(WithContext, ExecutionContext)
};
+struct QmlContext : public ExecutionContext
+{
+ V4_MANAGED(QmlContext, ExecutionContext)
+
+ QObject *qmlScope() const;
+ QQmlContextData *qmlContext() const;
+
+ void takeContextOwnership();
+};
+
inline CallContext *ExecutionContext::asCallContext()
{
return d()->type >= Heap::ExecutionContext::Type_SimpleCallContext ? static_cast<CallContext *>(this) : 0;
diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp
index 8a66c2cbfc..8901834e76 100644
--- a/src/qml/jsruntime/qv4dataview.cpp
+++ b/src/qml/jsruntime/qv4dataview.cpp
@@ -33,6 +33,7 @@
#include "qv4dataview_p.h"
#include "qv4arraybuffer_p.h"
+#include "qv4string_p.h"
#include "qendian.h"
@@ -46,9 +47,9 @@ Heap::DataViewCtor::DataViewCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue DataViewCtor::construct(Managed *m, CallData *callData)
+ReturnedValue DataViewCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<Object *>(m)->engine());
+ Scope scope(static_cast<const Object *>(m)->engine());
Scoped<ArrayBuffer> buffer(scope, callData->argument(0));
if (!buffer)
return scope.engine->throwTypeError();
@@ -61,7 +62,7 @@ ReturnedValue DataViewCtor::construct(Managed *m, CallData *callData)
if (bo != byteOffset || bl != byteLength || byteOffset + byteLength > bufferLength)
return scope.engine->throwRangeError(QStringLiteral("DataView: constructor arguments out of range"));
- Scoped<DataView> a(scope, scope.engine->memoryManager->alloc<DataView>(scope.engine));
+ Scoped<DataView> a(scope, scope.engine->memoryManager->allocObject<DataView>());
a->d()->buffer = buffer->d();
a->d()->byteLength = byteLength;
a->d()->byteOffset = byteOffset;
@@ -69,21 +70,12 @@ ReturnedValue DataViewCtor::construct(Managed *m, CallData *callData)
}
-ReturnedValue DataViewCtor::call(Managed *that, CallData *callData)
+ReturnedValue DataViewCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
-Heap::DataView::DataView(ExecutionEngine *e)
- : Heap::Object(e->emptyClass, e->dataViewPrototype.asObject()),
- buffer(0),
- byteLength(0),
- byteOffset(0)
-{
-}
-
-
void DataView::markObjects(Heap::Base *that, ExecutionEngine *e)
{
DataView::Data *v = static_cast<DataView::Data *>(that);
@@ -94,30 +86,38 @@ void DataViewPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(3));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- defineDefaultProperty(engine->id_constructor, (o = ctor));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(3));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ defineDefaultProperty(engine->id_constructor(), (o = ctor));
defineAccessorProperty(QStringLiteral("buffer"), method_get_buffer, 0);
defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, 0);
defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, 0);
defineDefaultProperty(QStringLiteral("getInt8"), method_getChar<signed char>, 0);
- defineDefaultProperty(QStringLiteral("getUInt8"), method_getChar<unsigned char>, 0);
+ defineDefaultProperty(QStringLiteral("getUint8"), method_getChar<unsigned char>, 0);
defineDefaultProperty(QStringLiteral("getInt16"), method_get<short>, 0);
- defineDefaultProperty(QStringLiteral("getUInt16"), method_get<unsigned short>, 0);
+ defineDefaultProperty(QStringLiteral("getUint16"), method_get<unsigned short>, 0);
defineDefaultProperty(QStringLiteral("getInt32"), method_get<int>, 0);
- defineDefaultProperty(QStringLiteral("getUInt32"), method_get<unsigned int>, 0);
+ defineDefaultProperty(QStringLiteral("getUint32"), method_get<unsigned int>, 0);
defineDefaultProperty(QStringLiteral("getFloat32"), method_getFloat<float>, 0);
defineDefaultProperty(QStringLiteral("getFloat64"), method_getFloat<double>, 0);
defineDefaultProperty(QStringLiteral("setInt8"), method_setChar<signed char>, 0);
- defineDefaultProperty(QStringLiteral("setUInt8"), method_setChar<unsigned char>, 0);
+ defineDefaultProperty(QStringLiteral("setUint8"), method_setChar<unsigned char>, 0);
defineDefaultProperty(QStringLiteral("setInt16"), method_set<short>, 0);
- defineDefaultProperty(QStringLiteral("setUInt16"), method_set<unsigned short>, 0);
+ defineDefaultProperty(QStringLiteral("setUint16"), method_set<unsigned short>, 0);
defineDefaultProperty(QStringLiteral("setInt32"), method_set<int>, 0);
- defineDefaultProperty(QStringLiteral("setUInt32"), method_set<unsigned int>, 0);
+ defineDefaultProperty(QStringLiteral("setUint32"), method_set<unsigned int>, 0);
defineDefaultProperty(QStringLiteral("setFloat32"), method_setFloat<float>, 0);
defineDefaultProperty(QStringLiteral("setFloat64"), method_setFloat<double>, 0);
+
+ // For backword compatibility
+ defineDefaultProperty(QStringLiteral("getUInt8"), method_getChar<unsigned char>, 0);
+ defineDefaultProperty(QStringLiteral("getUInt16"), method_get<unsigned short>, 0);
+ defineDefaultProperty(QStringLiteral("getUInt32"), method_get<unsigned int>, 0);
+ defineDefaultProperty(QStringLiteral("setUInt8"), method_setChar<unsigned char>, 0);
+ defineDefaultProperty(QStringLiteral("setUInt16"), method_set<unsigned short>, 0);
+ defineDefaultProperty(QStringLiteral("setUInt32"), method_set<unsigned int>, 0);
}
ReturnedValue DataViewPrototype::method_get_buffer(CallContext *ctx)
diff --git a/src/qml/jsruntime/qv4dataview_p.h b/src/qml/jsruntime/qv4dataview_p.h
index 3f0c1e9e23..26347766d3 100644
--- a/src/qml/jsruntime/qv4dataview_p.h
+++ b/src/qml/jsruntime/qv4dataview_p.h
@@ -33,6 +33,17 @@
#ifndef QV4DATAVIEW_H
#define QV4DATAVIEW_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
@@ -47,8 +58,8 @@ struct DataViewCtor : FunctionObject {
};
struct DataView : Object {
- DataView(ExecutionEngine *e);
- ArrayBuffer *buffer;
+ DataView() {}
+ Pointer<ArrayBuffer> buffer;
uint byteLength;
uint byteOffset;
};
@@ -59,13 +70,14 @@ struct DataViewCtor: FunctionObject
{
V4_OBJECT2(DataViewCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct DataView : Object
{
V4_OBJECT2(DataView, Object)
+ V4_PROTOTYPE(dataViewPrototype)
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 451ef2486d..a6e1f47d91 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -36,6 +36,7 @@
#include "qv4objectproto_p.h"
#include "qv4scopedvalue_p.h"
#include "qv4runtime_p.h"
+#include "qv4string_p.h"
#include <QtCore/QDebug>
#include <QtCore/QDateTime>
@@ -627,15 +628,14 @@ static double getLocalTZA()
DEFINE_OBJECT_VTABLE(DateObject);
-Heap::DateObject::DateObject(QV4::ExecutionEngine *engine, const QDateTime &date)
- : Heap::Object(engine->emptyClass, engine->datePrototype.asObject())
+Heap::DateObject::DateObject(const QDateTime &date)
{
- value.setDouble(date.isValid() ? date.toMSecsSinceEpoch() : qSNaN());
+ this->date = date.isValid() ? date.toMSecsSinceEpoch() : qSNaN();
}
QDateTime DateObject::toQDateTime() const
{
- return ToDateTime(date().asDouble(), Qt::LocalTime);
+ return ToDateTime(date(), Qt::LocalTime);
}
DEFINE_OBJECT_VTABLE(DateCtor);
@@ -645,9 +645,9 @@ Heap::DateCtor::DateCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue DateCtor::construct(Managed *m, CallData *callData)
+ReturnedValue DateCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<DateCtor *>(m)->engine());
+ Scope scope(static_cast<const DateCtor *>(m)->engine());
double t = 0;
if (callData->argc == 0)
@@ -655,15 +655,16 @@ ReturnedValue DateCtor::construct(Managed *m, CallData *callData)
else if (callData->argc == 1) {
ScopedValue arg(scope, callData->args[0]);
- if (DateObject *d = arg->asDateObject())
- arg = d->date();
- else
+ if (DateObject *d = arg->as<DateObject>()) {
+ t = d->date();
+ } else {
arg = RuntimeHelpers::toPrimitive(arg, PREFERREDTYPE_HINT);
- if (arg->isString())
- t = ParseString(arg->stringValue()->toQString());
- else
- t = TimeClip(arg->toNumber());
+ if (arg->isString())
+ t = ParseString(arg->stringValue()->toQString());
+ else
+ t = TimeClip(arg->toNumber());
+ }
}
else { // d.argc > 1
@@ -683,18 +684,18 @@ ReturnedValue DateCtor::construct(Managed *m, CallData *callData)
return Encode(scope.engine->newDateObject(Primitive::fromDouble(t)));
}
-ReturnedValue DateCtor::call(Managed *m, CallData *)
+ReturnedValue DateCtor::call(const Managed *m, CallData *)
{
double t = currentTime();
- return static_cast<DateCtor *>(m)->engine()->newString(ToString(t))->asReturnedValue();
+ return static_cast<const DateCtor *>(m)->engine()->newString(ToString(t))->asReturnedValue();
}
void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(7));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(7));
LocalTZA = getLocalTZA();
ctor->defineDefaultProperty(QStringLiteral("parse"), method_parse, 1);
@@ -702,13 +703,13 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
ctor->defineDefaultProperty(QStringLiteral("now"), method_now, 0);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString, 0);
+ defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("toDateString"), method_toDateString, 0);
defineDefaultProperty(QStringLiteral("toTimeString"), method_toTimeString, 0);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString, 0);
defineDefaultProperty(QStringLiteral("toLocaleDateString"), method_toLocaleDateString, 0);
defineDefaultProperty(QStringLiteral("toLocaleTimeString"), method_toLocaleTimeString, 0);
- defineDefaultProperty(engine->id_valueOf, method_valueOf, 0);
+ defineDefaultProperty(engine->id_valueOf(), method_valueOf, 0);
defineDefaultProperty(QStringLiteral("getTime"), method_getTime, 0);
defineDefaultProperty(QStringLiteral("getYear"), method_getYear, 0);
defineDefaultProperty(QStringLiteral("getFullYear"), method_getFullYear, 0);
@@ -752,8 +753,8 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
double DatePrototype::getThisDate(ExecutionContext *ctx)
{
- if (DateObject *thisObject = ctx->thisObject().asDateObject())
- return thisObject->date().asDouble();
+ if (DateObject *thisObject = ctx->thisObject().as<DateObject>())
+ return thisObject->date();
else {
ctx->engine()->throwTypeError();
return 0;
@@ -994,8 +995,8 @@ ReturnedValue DatePrototype::method_setTime(CallContext *ctx)
return ctx->engine()->throwTypeError();
double t = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
- self->date().setDouble(TimeClip(t));
- return self->date().asReturnedValue();
+ self->setDate(TimeClip(t));
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setMilliseconds(CallContext *ctx)
@@ -1005,175 +1006,175 @@ ReturnedValue DatePrototype::method_setMilliseconds(CallContext *ctx)
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double ms = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
- self->date().setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
- return self->date().asReturnedValue();
+ self->setDate(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCMilliseconds(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double ms = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
- self->date().setDouble(TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))));
- return self->date().asReturnedValue();
+ self->setDate(TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))));
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setSeconds(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double sec = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double ms = (ctx->argc() < 2) ? msFromTime(t) : ctx->args()[1].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCSeconds(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double sec = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double ms = (ctx->argc() < 2) ? msFromTime(t) : ctx->args()[1].toNumber();
t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setMinutes(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double min = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double sec = (ctx->argc() < 2) ? SecFromTime(t) : ctx->args()[1].toNumber();
double ms = (ctx->argc() < 3) ? msFromTime(t) : ctx->args()[2].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCMinutes(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double min = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double sec = (ctx->argc() < 2) ? SecFromTime(t) : ctx->args()[1].toNumber();
double ms = (ctx->argc() < 3) ? msFromTime(t) : ctx->args()[2].toNumber();
t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setHours(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double hour = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double min = (ctx->argc() < 2) ? MinFromTime(t) : ctx->args()[1].toNumber();
double sec = (ctx->argc() < 3) ? SecFromTime(t) : ctx->args()[2].toNumber();
double ms = (ctx->argc() < 4) ? msFromTime(t) : ctx->args()[3].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCHours(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double hour = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double min = (ctx->argc() < 2) ? MinFromTime(t) : ctx->args()[1].toNumber();
double sec = (ctx->argc() < 3) ? SecFromTime(t) : ctx->args()[2].toNumber();
double ms = (ctx->argc() < 4) ? msFromTime(t) : ctx->args()[3].toNumber();
t = TimeClip(MakeDate(Day(t), MakeTime(hour, min, sec, ms)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setDate(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double date = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCDate(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double date = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
t = TimeClip(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setMonth(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double month = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double date = (ctx->argc() < 2) ? DateFromTime(t) : ctx->args()[1].toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCMonth(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double month = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double date = (ctx->argc() < 2) ? DateFromTime(t) : ctx->args()[1].toNumber();
t = TimeClip(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setYear(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
if (std::isnan(t))
t = 0;
else
@@ -1189,49 +1190,49 @@ ReturnedValue DatePrototype::method_setYear(CallContext *ctx)
r = UTC(MakeDate(r, TimeWithinDay(t)));
r = TimeClip(r);
}
- self->date().setDouble(r);
- return self->date().asReturnedValue();
+ self->setDate(r);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCFullYear(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double year = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double month = (ctx->argc() < 2) ? MonthFromTime(t) : ctx->args()[1].toNumber();
double date = (ctx->argc() < 3) ? DateFromTime(t) : ctx->args()[2].toNumber();
t = TimeClip(MakeDate(MakeDay(year, month, date), TimeWithinDay(t)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setFullYear(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
if (std::isnan(t))
t = 0;
double year = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double month = (ctx->argc() < 2) ? MonthFromTime(t) : ctx->args()[1].toNumber();
double date = (ctx->argc() < 3) ? DateFromTime(t) : ctx->args()[2].toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_toUTCString(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
return ctx->d()->engine->newString(ToUTCString(t))->asReturnedValue();
}
@@ -1250,11 +1251,11 @@ static void addZeroPrefixedInt(QString &str, int num, int nDigits)
ReturnedValue DatePrototype::method_toISOString(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
if (!std::isfinite(t))
return ctx->engine()->throwRangeError(ctx->thisObject());
@@ -1297,7 +1298,7 @@ ReturnedValue DatePrototype::method_toJSON(CallContext *ctx)
ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toISOString")));
ScopedValue v(scope, O->objectValue()->get(s));
- FunctionObject *toIso = v->asFunctionObject();
+ FunctionObject *toIso = v->as<FunctionObject>();
if (!toIso)
return ctx->engine()->throwTypeError();
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index dad3689054..2eaa837666 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4DATEOBJECT_P_H
#define QV4DATEOBJECT_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include <QtCore/qnumeric.h>
@@ -46,21 +57,20 @@ namespace QV4 {
namespace Heap {
struct DateObject : Object {
- DateObject(InternalClass *ic, QV4::Object *prototype)
- : Object(ic, prototype)
+ DateObject()
{
- value = Encode(qSNaN());
+ date = qSNaN();
}
- DateObject(QV4::ExecutionEngine *engine, const Value &date)
- : Object(engine->emptyClass, engine->datePrototype.asObject())
+ DateObject(const Value &date)
{
- value = date;
+ this->date = date.toNumber();
}
- DateObject(QV4::ExecutionEngine *engine, const QDateTime &date);
- Value value;
+ DateObject(const QDateTime &date);
+ double date;
};
+
struct DateCtor : FunctionObject {
DateCtor(QV4::ExecutionContext *scope);
};
@@ -70,21 +80,26 @@ struct DateCtor : FunctionObject {
struct DateObject: Object {
V4_OBJECT2(DateObject, Object)
Q_MANAGED_TYPE(DateObject)
+ V4_PROTOTYPE(datePrototype)
- Value date() const { return d()->value; }
- Value &date() { return d()->value; }
- void setDate(const Value &date) { d()->value = date; }
+ double date() const { return d()->date; }
+ void setDate(double date) { d()->date = date; }
QDateTime toQDateTime() const;
};
+template<>
+inline const DateObject *Value::as() const {
+ return isManaged() && m() && m()->vtable()->type == Managed::Type_DateObject ? static_cast<const DateObject *>(this) : 0;
+}
+
struct DateCtor: FunctionObject
{
V4_OBJECT2(DateCtor, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *);
};
struct DatePrototype: DateObject
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 36e7a3558c..7706a40da6 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -38,69 +38,72 @@
#include "qv4instr_moth_p.h"
#include "qv4runtime_p.h"
#include "qv4script_p.h"
-#include "qv4objectiterator_p.h"
#include "qv4identifier_p.h"
-#include <iostream>
+#include "qv4string_p.h"
+#include "qv4objectiterator_p.h"
+#include <iostream>
#include <algorithm>
+#include <QtCore/QJsonArray>
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonValue>
+
+QT_BEGIN_NAMESPACE
+
using namespace QV4;
using namespace QV4::Debugging;
-namespace {
-class JavaScriptJob: public Debugger::Job
-{
- QV4::ExecutionEngine *engine;
- int frameNr;
- const QString &script;
+V4Debugger::JavaScriptJob::JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr,
+ const QString &script)
+ : engine(engine)
+ , frameNr(frameNr)
+ , script(script)
+ , resultIsException(false)
+{}
-public:
- JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr, const QString &script)
- : engine(engine)
- , frameNr(frameNr)
- , script(script)
- {}
-
- void run()
- {
- Scope scope(engine);
+void V4Debugger::JavaScriptJob::run()
+{
+ Scope scope(engine);
- ExecutionContextSaver saver(scope, engine->currentContext());
+ ExecutionContextSaver saver(scope);
- if (frameNr > 0) {
- Value *savedContexts = scope.alloc(frameNr);
- for (int i = 0; i < frameNr; ++i) {
- savedContexts[i] = engine->currentContext();
- engine->popContext();
- }
+ ExecutionContext *ctx = engine->currentContext;
+ if (frameNr > 0) {
+ for (int i = 0; i < frameNr; ++i) {
+ ctx = engine->parentContext(ctx);
}
+ engine->pushContext(ctx);
+ }
- ScopedContext ctx(scope, engine->currentContext());
- QV4::Script script(ctx, this->script);
- script.strictMode = ctx->d()->strictMode;
- // In order for property lookups in QML to work, we need to disable fast v4 lookups. That
- // is a side-effect of inheritContext.
- script.inheritContext = true;
- script.parse();
- QV4::ScopedValue result(scope);
- if (!scope.engine->hasException)
- result = script.run();
- if (scope.engine->hasException)
- result = scope.engine->catchException();
- handleResult(result);
+ QV4::Script script(ctx, this->script);
+ script.strictMode = ctx->d()->strictMode;
+ // In order for property lookups in QML to work, we need to disable fast v4 lookups. That
+ // is a side-effect of inheritContext.
+ script.inheritContext = true;
+ script.parse();
+ QV4::ScopedValue result(scope);
+ if (!scope.engine->hasException)
+ result = script.run();
+ if (scope.engine->hasException) {
+ result = scope.engine->catchException();
+ resultIsException = true;
}
+ handleResult(result);
+}
-protected:
- virtual void handleResult(QV4::ScopedValue &result) = 0;
-};
+bool V4Debugger::JavaScriptJob::hasExeption() const
+{
+ return resultIsException;
+}
-class EvalJob: public JavaScriptJob
+class EvalJob: public V4Debugger::JavaScriptJob
{
bool result;
public:
EvalJob(QV4::ExecutionEngine *engine, const QString &script)
- : JavaScriptJob(engine, /*frameNr*/-1, script)
+ : V4Debugger::JavaScriptJob(engine, /*frameNr*/-1, script)
, result(false)
{}
@@ -115,58 +118,8 @@ public:
}
};
-class ExpressionEvalJob: public JavaScriptJob
-{
- Debugger::Collector *collector;
-
-public:
- ExpressionEvalJob(ExecutionEngine *engine, int frameNr, const QString &expression, Debugger::Collector *collector)
- : JavaScriptJob(engine, frameNr, expression)
- , collector(collector)
- {
- }
-
- virtual void handleResult(QV4::ScopedValue &result)
- {
- collector->collect(QStringLiteral("body"), result);
- }
-};
-
-class GatherSourcesJob: public Debugger::Job
-{
- QV4::ExecutionEngine *engine;
- const int seq;
-
-public:
- GatherSourcesJob(QV4::ExecutionEngine *engine, int seq)
- : engine(engine)
- , seq(seq)
- {}
-
- ~GatherSourcesJob() {}
-
- void run()
- {
- QStringList sources;
-
- foreach (QV4::CompiledData::CompilationUnit *unit, engine->compilationUnits) {
- QString fileName = unit->fileName();
- if (!fileName.isEmpty())
- sources.append(fileName);
- }
-
- Debugger *debugger = engine->debugger;
- QMetaObject::invokeMethod(debugger->agent(), "sourcesCollected", Qt::QueuedConnection,
- Q_ARG(QV4::Debugging::Debugger*, debugger),
- Q_ARG(QStringList, sources),
- Q_ARG(int, seq));
- }
-};
-}
-
-Debugger::Debugger(QV4::ExecutionEngine *engine)
+V4Debugger::V4Debugger(QV4::ExecutionEngine *engine)
: m_engine(engine)
- , m_agent(0)
, m_state(Running)
, m_stepping(NotStepping)
, m_pauseRequested(false)
@@ -176,46 +129,11 @@ Debugger::Debugger(QV4::ExecutionEngine *engine)
, m_gatherSources(0)
, m_runningJob(0)
{
- qMetaTypeId<Debugger*>();
+ qMetaTypeId<V4Debugger*>();
qMetaTypeId<PauseReason>();
}
-Debugger::~Debugger()
-{
- detachFromAgent();
-}
-
-void Debugger::attachToAgent(DebuggerAgent *agent)
-{
- Q_ASSERT(!m_agent);
- m_agent = agent;
-}
-
-void Debugger::detachFromAgent()
-{
- DebuggerAgent *agent = 0;
- {
- QMutexLocker locker(&m_lock);
- agent = m_agent;
- m_agent = 0;
- }
- if (agent)
- agent->removeDebugger(this);
-}
-
-void Debugger::gatherSources(int requestSequenceNr)
-{
- QMutexLocker locker(&m_lock);
-
- m_gatherSources = new GatherSourcesJob(m_engine, requestSequenceNr);
- if (m_state == Paused) {
- runInEngine_havingLock(m_gatherSources);
- delete m_gatherSources;
- m_gatherSources = 0;
- }
-}
-
-void Debugger::pause()
+void V4Debugger::pause()
{
QMutexLocker locker(&m_lock);
if (m_state == Paused)
@@ -223,7 +141,7 @@ void Debugger::pause()
m_pauseRequested = true;
}
-void Debugger::resume(Speed speed)
+void V4Debugger::resume(Speed speed)
{
QMutexLocker locker(&m_lock);
if (m_state != Paused)
@@ -232,292 +150,47 @@ void Debugger::resume(Speed speed)
if (!m_returnedValue.isUndefined())
m_returnedValue.set(m_engine, Encode::undefined());
- m_currentContext.set(m_engine, m_engine->currentContext());
+ m_currentContext.set(m_engine, *m_engine->currentContext);
m_stepping = speed;
m_runningCondition.wakeAll();
}
-void Debugger::addBreakPoint(const QString &fileName, int lineNumber, const QString &condition)
+void V4Debugger::addBreakPoint(const QString &fileName, int lineNumber, const QString &condition)
{
QMutexLocker locker(&m_lock);
m_breakPoints.insert(DebuggerBreakPoint(fileName.mid(fileName.lastIndexOf('/') + 1), lineNumber), condition);
m_haveBreakPoints = true;
}
-void Debugger::removeBreakPoint(const QString &fileName, int lineNumber)
+void V4Debugger::removeBreakPoint(const QString &fileName, int lineNumber)
{
QMutexLocker locker(&m_lock);
m_breakPoints.remove(DebuggerBreakPoint(fileName.mid(fileName.lastIndexOf('/') + 1), lineNumber));
m_haveBreakPoints = !m_breakPoints.isEmpty();
}
-void Debugger::setBreakOnThrow(bool onoff)
+void V4Debugger::setBreakOnThrow(bool onoff)
{
QMutexLocker locker(&m_lock);
m_breakOnThrow = onoff;
}
-Debugger::ExecutionState Debugger::currentExecutionState() const
+V4Debugger::ExecutionState V4Debugger::currentExecutionState() const
{
ExecutionState state;
state.fileName = getFunction()->sourceFile();
- state.lineNumber = engine()->currentContext()->lineNumber;
+ state.lineNumber = engine()->current->lineNumber;
return state;
}
-QVector<StackFrame> Debugger::stackTrace(int frameLimit) const
+QVector<StackFrame> V4Debugger::stackTrace(int frameLimit) const
{
return m_engine->stackTrace(frameLimit);
}
-static inline Heap::CallContext *findContext(Heap::ExecutionContext *ctxt, int frame)
-{
- if (!ctxt)
- return 0;
-
- Scope scope(ctxt->engine);
- ScopedContext ctx(scope, ctxt);
- while (ctx) {
- CallContext *cCtxt = ctx->asCallContext();
- if (cCtxt && cCtxt->d()->function) {
- if (frame < 1)
- return cCtxt->d();
- --frame;
- }
- ctx = ctx->d()->parent;
- }
-
- return 0;
-}
-
-static inline Heap::CallContext *findScope(Heap::ExecutionContext *ctxt, int scope)
-{
- if (!ctxt)
- return 0;
-
- Scope s(ctxt->engine);
- ScopedContext ctx(s, ctxt);
- for (; scope > 0 && ctx; --scope)
- ctx = ctx->d()->outer;
-
- return (ctx && ctx->d()) ? ctx->asCallContext()->d() : 0;
-}
-
-void Debugger::collectArgumentsInContext(Collector *collector, int frameNr, int scopeNr)
-{
- if (state() != Paused)
- return;
-
- class ArgumentCollectJob: public Job
- {
- QV4::ExecutionEngine *engine;
- Collector *collector;
- int frameNr;
- int scopeNr;
-
- public:
- ArgumentCollectJob(QV4::ExecutionEngine *engine, Collector *collector, int frameNr, int scopeNr)
- : engine(engine)
- , collector(collector)
- , frameNr(frameNr)
- , scopeNr(scopeNr)
- {}
-
- ~ArgumentCollectJob() {}
-
- void run()
- {
- if (frameNr < 0)
- return;
-
- Scope scope(engine);
- Scoped<CallContext> ctxt(scope, findScope(findContext(engine->currentContext(), frameNr), scopeNr));
- if (!ctxt)
- return;
-
- ScopedValue v(scope);
- int nFormals = ctxt->formalCount();
- for (unsigned i = 0, ei = nFormals; i != ei; ++i) {
- QString qName;
- if (Identifier *name = ctxt->formals()[nFormals - i - 1])
- qName = name->string;
- v = ctxt->argument(i);
- collector->collect(qName, v);
- }
- }
- };
-
- ArgumentCollectJob job(m_engine, collector, frameNr, scopeNr);
- runInEngine(&job);
-}
-
-/// Same as \c retrieveArgumentsFromContext, but now for locals.
-void Debugger::collectLocalsInContext(Collector *collector, int frameNr, int scopeNr)
-{
- if (state() != Paused)
- return;
-
- class LocalCollectJob: public Job
- {
- QV4::ExecutionEngine *engine;
- Collector *collector;
- int frameNr;
- int scopeNr;
-
- public:
- LocalCollectJob(QV4::ExecutionEngine *engine, Collector *collector, int frameNr, int scopeNr)
- : engine(engine)
- , collector(collector)
- , frameNr(frameNr)
- , scopeNr(scopeNr)
- {}
-
- void run()
- {
- if (frameNr < 0)
- return;
-
- Scope scope(engine);
- Scoped<CallContext> ctxt(scope, findScope(findContext(engine->currentContext(), frameNr), scopeNr));
- if (!ctxt)
- return;
-
- ScopedValue v(scope);
- for (unsigned i = 0, ei = ctxt->variableCount(); i != ei; ++i) {
- QString qName;
- if (Identifier *name = ctxt->variables()[i])
- qName = name->string;
- v = ctxt->d()->locals[i];
- collector->collect(qName, v);
- }
- }
- };
-
- LocalCollectJob job(m_engine, collector, frameNr, scopeNr);
- runInEngine(&job);
-}
-
-bool Debugger::collectThisInContext(Debugger::Collector *collector, int frame)
-{
- if (state() != Paused)
- return false;
-
- class ThisCollectJob: public Job
- {
- QV4::ExecutionEngine *engine;
- Collector *collector;
- int frameNr;
- bool *foundThis;
-
- public:
- ThisCollectJob(QV4::ExecutionEngine *engine, Collector *collector, int frameNr, bool *foundThis)
- : engine(engine)
- , collector(collector)
- , frameNr(frameNr)
- , foundThis(foundThis)
- {}
-
- void run()
- {
- *foundThis = myRun();
- }
-
- bool myRun()
- {
- Scope scope(engine);
- ScopedContext ctxt(scope, findContext(engine->currentContext(), frameNr));
- while (ctxt) {
- if (CallContext *cCtxt = ctxt->asCallContext())
- if (cCtxt->d()->activation)
- break;
- ctxt = ctxt->d()->outer;
- }
-
- if (!ctxt)
- return false;
-
- ScopedObject o(scope, ctxt->asCallContext()->d()->activation);
- collector->collect(o);
- return true;
- }
- };
-
- bool foundThis = false;
- ThisCollectJob job(m_engine, collector, frame, &foundThis);
- runInEngine(&job);
- return foundThis;
-}
-
-void Debugger::collectThrownValue(Collector *collector)
-{
- if (state() != Paused || !m_engine->hasException)
- return;
-
- class ThisCollectJob: public Job
- {
- QV4::ExecutionEngine *engine;
- Collector *collector;
-
- public:
- ThisCollectJob(QV4::ExecutionEngine *engine, Collector *collector)
- : engine(engine)
- , collector(collector)
- {}
-
- void run()
- {
- Scope scope(engine);
- ScopedValue v(scope, engine->exceptionValue);
- collector->collect(QStringLiteral("exception"), v);
- }
- };
-
- ThisCollectJob job(m_engine, collector);
- runInEngine(&job);
-}
-
-void Debugger::collectReturnedValue(Collector *collector) const
-{
- if (state() != Paused)
- return;
-
- Scope scope(m_engine);
- ScopedObject o(scope, m_returnedValue.valueRef());
- collector->collect(o);
-}
-
-QVector<Heap::ExecutionContext::ContextType> Debugger::getScopeTypes(int frame) const
-{
- QVector<Heap::ExecutionContext::ContextType> types;
-
- if (state() != Paused)
- return types;
-
- Scope scope(m_engine);
- Scoped<CallContext> sctxt(scope, findContext(m_engine->currentContext(), frame));
- if (!sctxt || sctxt->d()->type < Heap::ExecutionContext::Type_SimpleCallContext)
- return types;
-
- ScopedContext it(scope, sctxt->d());
- for (; it; it = it->d()->outer)
- types.append(it->d()->type);
-
- return types;
-}
-
-
-void Debugger::evaluateExpression(int frameNr, const QString &expression, Debugger::Collector *resultsCollector)
-{
- Q_ASSERT(state() == Paused);
-
- Q_ASSERT(m_runningJob == 0);
- ExpressionEvalJob job(m_engine, frameNr, expression, resultsCollector);
- runInEngine(&job);
-}
-
-void Debugger::maybeBreakAtInstruction()
+void V4Debugger::maybeBreakAtInstruction()
{
if (m_runningJob) // do not re-enter when we're doing a job for the debugger.
return;
@@ -532,7 +205,7 @@ void Debugger::maybeBreakAtInstruction()
switch (m_stepping) {
case StepOver:
- if (m_currentContext.asManaged()->d() != m_engine->currentContext())
+ if (m_currentContext.asManaged()->d() != m_engine->current)
break;
// fall through
case StepIn:
@@ -548,25 +221,25 @@ void Debugger::maybeBreakAtInstruction()
pauseAndWait(PauseRequest);
} else if (m_haveBreakPoints) {
if (Function *f = getFunction()) {
- const int lineNumber = engine()->currentContext()->lineNumber;
+ const int lineNumber = engine()->current->lineNumber;
if (reallyHitTheBreakPoint(f->sourceFile(), lineNumber))
pauseAndWait(BreakPoint);
}
}
}
-void Debugger::enteringFunction()
+void V4Debugger::enteringFunction()
{
if (m_runningJob)
return;
QMutexLocker locker(&m_lock);
if (m_stepping == StepIn) {
- m_currentContext.set(m_engine, m_engine->currentContext());
+ m_currentContext.set(m_engine, *m_engine->currentContext);
}
}
-void Debugger::leavingFunction(const ReturnedValue &retVal)
+void V4Debugger::leavingFunction(const ReturnedValue &retVal)
{
if (m_runningJob)
return;
@@ -574,14 +247,14 @@ void Debugger::leavingFunction(const ReturnedValue &retVal)
QMutexLocker locker(&m_lock);
- if (m_stepping != NotStepping && m_currentContext.asManaged()->d() == m_engine->currentContext()) {
- m_currentContext.set(m_engine, m_engine->currentContext()->parent);
+ if (m_stepping != NotStepping && m_currentContext.asManaged()->d() == m_engine->current) {
+ m_currentContext.set(m_engine, *m_engine->parentContext(m_engine->currentContext));
m_stepping = StepOver;
m_returnedValue.set(m_engine, retVal);
}
}
-void Debugger::aboutToThrow()
+void V4Debugger::aboutToThrow()
{
if (!m_breakOnThrow)
return;
@@ -593,10 +266,10 @@ void Debugger::aboutToThrow()
pauseAndWait(Throwing);
}
-Function *Debugger::getFunction() const
+Function *V4Debugger::getFunction() const
{
Scope scope(m_engine);
- ScopedContext context(scope, m_engine->currentContext());
+ ExecutionContext *context = m_engine->currentContext;
ScopedFunctionObject function(scope, context->getFunctionObject());
if (function)
return function->function();
@@ -604,15 +277,13 @@ Function *Debugger::getFunction() const
return context->d()->engine->globalCode;
}
-void Debugger::pauseAndWait(PauseReason reason)
+void V4Debugger::pauseAndWait(PauseReason reason)
{
if (m_runningJob)
return;
m_state = Paused;
- QMetaObject::invokeMethod(m_agent, "debuggerPaused", Qt::QueuedConnection,
- Q_ARG(QV4::Debugging::Debugger*, this),
- Q_ARG(QV4::Debugging::PauseReason, reason));
+ emit debuggerPaused(this, reason);
while (true) {
m_runningCondition.wait(&m_lock);
@@ -627,7 +298,7 @@ void Debugger::pauseAndWait(PauseReason reason)
m_state = Running;
}
-bool Debugger::reallyHitTheBreakPoint(const QString &filename, int linenr)
+bool V4Debugger::reallyHitTheBreakPoint(const QString &filename, int linenr)
{
BreakPoints::iterator it = m_breakPoints.find(DebuggerBreakPoint(filename.mid(filename.lastIndexOf('/') + 1), linenr));
if (it == m_breakPoints.end())
@@ -645,13 +316,13 @@ bool Debugger::reallyHitTheBreakPoint(const QString &filename, int linenr)
return evilJob.resultAsBoolean();
}
-void Debugger::runInEngine(Debugger::Job *job)
+void V4Debugger::runInEngine(V4Debugger::Job *job)
{
QMutexLocker locker(&m_lock);
runInEngine_havingLock(job);
}
-void Debugger::runInEngine_havingLock(Debugger::Job *job)
+void V4Debugger::runInEngine_havingLock(V4Debugger::Job *job)
{
Q_ASSERT(job);
Q_ASSERT(m_runningJob == 0);
@@ -662,174 +333,8 @@ void Debugger::runInEngine_havingLock(Debugger::Job *job)
m_runningJob = 0;
}
-void DebuggerAgent::addDebugger(Debugger *debugger)
-{
- Q_ASSERT(!m_debuggers.contains(debugger));
- m_debuggers << debugger;
- debugger->attachToAgent(this);
-
- debugger->setBreakOnThrow(m_breakOnThrow);
-
- foreach (const BreakPoint &breakPoint, m_breakPoints.values())
- if (breakPoint.enabled)
- debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
-}
-
-void DebuggerAgent::removeDebugger(Debugger *debugger)
-{
- m_debuggers.removeAll(debugger);
- debugger->detachFromAgent();
-}
-
-void DebuggerAgent::pause(Debugger *debugger) const
-{
- debugger->pause();
-}
-
-void DebuggerAgent::pauseAll() const
+V4Debugger::Job::~Job()
{
- foreach (Debugger *debugger, m_debuggers)
- pause(debugger);
}
-void DebuggerAgent::resumeAll() const
-{
- foreach (Debugger *debugger, m_debuggers)
- if (debugger->state() == Debugger::Paused)
- debugger->resume(Debugger::FullThrottle);
-}
-
-int DebuggerAgent::addBreakPoint(const QString &fileName, int lineNumber, bool enabled, const QString &condition)
-{
- if (enabled)
- foreach (Debugger *debugger, m_debuggers)
- debugger->addBreakPoint(fileName, lineNumber, condition);
-
- int id = m_breakPoints.size();
- m_breakPoints.insert(id, BreakPoint(fileName, lineNumber, enabled, condition));
- return id;
-}
-
-void DebuggerAgent::removeBreakPoint(int id)
-{
- BreakPoint breakPoint = m_breakPoints.value(id);
- if (!breakPoint.isValid())
- return;
-
- m_breakPoints.remove(id);
-
- if (breakPoint.enabled)
- foreach (Debugger *debugger, m_debuggers)
- debugger->removeBreakPoint(breakPoint.fileName, breakPoint.lineNr);
-}
-
-void DebuggerAgent::removeAllBreakPoints()
-{
- QList<int> ids = m_breakPoints.keys();
- foreach (int id, ids)
- removeBreakPoint(id);
-}
-
-void DebuggerAgent::enableBreakPoint(int id, bool onoff)
-{
- BreakPoint &breakPoint = m_breakPoints[id];
- if (!breakPoint.isValid() || breakPoint.enabled == onoff)
- return;
- breakPoint.enabled = onoff;
-
- foreach (Debugger *debugger, m_debuggers) {
- if (onoff)
- debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
- else
- debugger->removeBreakPoint(breakPoint.fileName, breakPoint.lineNr);
- }
-}
-
-QList<int> DebuggerAgent::breakPointIds(const QString &fileName, int lineNumber) const
-{
- QList<int> ids;
-
- for (QHash<int, BreakPoint>::const_iterator i = m_breakPoints.begin(), ei = m_breakPoints.end(); i != ei; ++i)
- if (i->lineNr == lineNumber && fileName.endsWith(i->fileName))
- ids.push_back(i.key());
-
- return ids;
-}
-
-void DebuggerAgent::setBreakOnThrow(bool onoff)
-{
- if (onoff != m_breakOnThrow) {
- m_breakOnThrow = onoff;
- foreach (Debugger *debugger, m_debuggers)
- debugger->setBreakOnThrow(onoff);
- }
-}
-
-DebuggerAgent::~DebuggerAgent()
-{
- foreach (Debugger *debugger, m_debuggers)
- debugger->detachFromAgent();
-
- Q_ASSERT(m_debuggers.isEmpty());
-}
-
-Debugger::Collector::~Collector()
-{
-}
-
-void Debugger::Collector::collect(const QString &name, const ScopedValue &value)
-{
- switch (value->type()) {
- case Value::Empty_Type:
- Q_ASSERT(!"empty Value encountered");
- break;
- case Value::Undefined_Type:
- addUndefined(name);
- break;
- case Value::Null_Type:
- addNull(name);
- break;
- case Value::Boolean_Type:
- addBoolean(name, value->booleanValue());
- break;
- case Value::Managed_Type:
- if (String *s = value->asString())
- addString(name, s->toQString());
- else
- addObject(name, value);
- break;
- case Value::Integer_Type:
- addInteger(name, value->int_32);
- break;
- default: // double
- addDouble(name, value->doubleValue());
- break;
- }
-}
-
-void Debugger::Collector::collect(Object *object)
-{
- bool property = true;
- qSwap(property, m_isProperty);
-
- Scope scope(m_engine);
- ObjectIterator it(scope, object, ObjectIterator::EnumerableOnly);
- ScopedValue name(scope);
- ScopedValue value(scope);
- while (true) {
- Value v;
- name = it.nextPropertyNameAsString(&v);
- if (name->isNull())
- break;
- QString key = name->toQStringNoThrow();
- value = v;
- collect(key, value);
- }
-
- qSwap(property, m_isProperty);
-}
-
-
-Debugger::Job::~Job()
-{
-}
+QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4debugging_p.h b/src/qml/jsruntime/qv4debugging_p.h
index e6a9750351..fdc9cac24f 100644
--- a/src/qml/jsruntime/qv4debugging_p.h
+++ b/src/qml/jsruntime/qv4debugging_p.h
@@ -34,6 +34,17 @@
#ifndef DEBUGGING_H
#define DEBUGGING_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4engine_p.h"
#include "qv4context_p.h"
@@ -44,6 +55,8 @@
#include <QMutex>
#include <QWaitCondition>
+#include <QtCore/QJsonObject>
+
QT_BEGIN_NAMESPACE
namespace QV4 {
@@ -59,8 +72,6 @@ enum PauseReason {
Step
};
-class DebuggerAgent;
-
struct DebuggerBreakPoint {
DebuggerBreakPoint(const QString &fileName, int line)
: fileName(fileName), lineNumber(line)
@@ -79,43 +90,44 @@ inline bool operator==(const DebuggerBreakPoint &a, const DebuggerBreakPoint &b)
typedef QHash<DebuggerBreakPoint, QString> BreakPoints;
+class Q_QML_EXPORT Debugger : public QObject
+{
+ Q_OBJECT
-class Q_QML_EXPORT Debugger
+public:
+ virtual ~Debugger() {}
+ virtual bool pauseAtNextOpportunity() const = 0;
+ virtual void maybeBreakAtInstruction() = 0;
+ virtual void enteringFunction() = 0;
+ virtual void leavingFunction(const ReturnedValue &retVal) = 0;
+ virtual void aboutToThrow() = 0;
+};
+
+class Q_QML_EXPORT V4Debugger : public Debugger
{
+ Q_OBJECT
public:
- class Job
+ class Q_QML_EXPORT Job
{
public:
virtual ~Job() = 0;
virtual void run() = 0;
};
- class Q_QML_EXPORT Collector
+ class Q_QML_EXPORT JavaScriptJob: public Job
{
- public:
- Collector(ExecutionEngine *engine): m_engine(engine), m_isProperty(false) {}
- virtual ~Collector();
+ QV4::ExecutionEngine *engine;
+ int frameNr;
+ const QString &script;
+ bool resultIsException;
- void collect(const QString &name, const ScopedValue &value);
- void collect(Object *object);
+ public:
+ JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr, const QString &script);
+ void run();
+ bool hasExeption() const;
protected:
- virtual void addUndefined(const QString &name) = 0;
- virtual void addNull(const QString &name) = 0;
- virtual void addBoolean(const QString &name, bool value) = 0;
- virtual void addString(const QString &name, const QString &value) = 0;
- virtual void addObject(const QString &name, const Value &value) = 0;
- virtual void addInteger(const QString &name, int value) = 0;
- virtual void addDouble(const QString &name, double value) = 0;
-
- QV4::ExecutionEngine *engine() const { return m_engine; }
-
- bool isProperty() const { return m_isProperty; }
- void setIsProperty(bool onoff) { m_isProperty = onoff; }
-
- private:
- QV4::ExecutionEngine *m_engine;
- bool m_isProperty;
+ virtual void handleResult(QV4::ScopedValue &result) = 0;
};
enum State {
@@ -132,17 +144,11 @@ public:
NotStepping = FullThrottle
};
- Debugger(ExecutionEngine *engine);
- ~Debugger();
+ V4Debugger(ExecutionEngine *engine);
ExecutionEngine *engine() const
{ return m_engine; }
- void attachToAgent(DebuggerAgent *agent);
- void detachFromAgent();
- DebuggerAgent *agent() const { return m_agent; }
-
- void gatherSources(int requestSequenceNr);
void pause();
void resume(Speed speed);
@@ -166,14 +172,10 @@ public:
}
QVector<StackFrame> stackTrace(int frameLimit = -1) const;
- void collectArgumentsInContext(Collector *collector, int frameNr = 0, int scopeNr = 0);
- void collectLocalsInContext(Collector *collector, int frameNr = 0, int scopeNr = 0);
- bool collectThisInContext(Collector *collector, int frame = 0);
- void collectThrownValue(Collector *collector);
- void collectReturnedValue(Collector *collector) const;
QVector<Heap::ExecutionContext::ContextType> getScopeTypes(int frame = 0) const;
- void evaluateExpression(int frameNr, const QString &expression, Collector *resultsCollector);
+ Function *getFunction() const;
+ void runInEngine(Job *job);
public: // compile-time interface
void maybeBreakAtInstruction();
@@ -183,21 +185,19 @@ public: // execution hooks
void leavingFunction(const ReturnedValue &retVal);
void aboutToThrow();
-private:
- Function *getFunction() const;
+signals:
+ void sourcesCollected(QV4::Debugging::V4Debugger *self, const QStringList &sources, int seq);
+ void debuggerPaused(QV4::Debugging::V4Debugger *self, QV4::Debugging::PauseReason reason);
+private:
// requires lock to be held
void pauseAndWait(PauseReason reason);
-
bool reallyHitTheBreakPoint(const QString &filename, int linenr);
-
- void runInEngine(Job *job);
- void runInEngine_havingLock(Debugger::Job *job);
+ void runInEngine_havingLock(V4Debugger::Job *job);
private:
QV4::ExecutionEngine *m_engine;
QV4::PersistentValue m_currentContext;
- DebuggerAgent *m_agent;
QMutex m_lock;
QWaitCondition m_runningCondition;
State m_state;
@@ -214,54 +214,6 @@ private:
QWaitCondition m_jobIsRunning;
};
-class Q_QML_EXPORT DebuggerAgent : public QObject
-{
- Q_OBJECT
-public:
- DebuggerAgent(): m_breakOnThrow(false) {}
- ~DebuggerAgent();
-
- void addDebugger(Debugger *debugger);
- void removeDebugger(Debugger *debugger);
-
- void pause(Debugger *debugger) const;
- void pauseAll() const;
- void resumeAll() const;
- int addBreakPoint(const QString &fileName, int lineNumber, bool enabled = true, const QString &condition = QString());
- void removeBreakPoint(int id);
- void removeAllBreakPoints();
- void enableBreakPoint(int id, bool onoff);
- QList<int> breakPointIds(const QString &fileName, int lineNumber) const;
-
- bool breakOnThrow() const { return m_breakOnThrow; }
- void setBreakOnThrow(bool onoff);
-
- Q_INVOKABLE virtual void debuggerPaused(QV4::Debugging::Debugger *debugger,
- QV4::Debugging::PauseReason reason) = 0;
- Q_INVOKABLE virtual void sourcesCollected(QV4::Debugging::Debugger *debugger,
- QStringList sources, int requestSequenceNr) = 0;
-
-protected:
- QList<Debugger *> m_debuggers;
-
- struct BreakPoint {
- QString fileName;
- int lineNr;
- bool enabled;
- QString condition;
-
- BreakPoint(): lineNr(-1), enabled(false) {}
- BreakPoint(const QString &fileName, int lineNr, bool enabled, const QString &condition)
- : fileName(fileName), lineNr(lineNr), enabled(enabled), condition(condition)
- {}
-
- bool isValid() const { return lineNr >= 0 && !fileName.isEmpty(); }
- };
-
- QHash<int, BreakPoint> m_breakPoints;
- bool m_breakOnThrow;
-};
-
} // namespace Debugging
} // namespace QV4
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index e1282eeca9..2560f065cf 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -32,7 +32,7 @@
****************************************************************************/
#include <qv4engine_p.h>
#include <qv4context_p.h>
-#include <qv4value_inl_p.h>
+#include <qv4value_p.h>
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
#include <qv4objectiterator_p.h>
@@ -48,7 +48,7 @@
#include <qv4regexp_p.h>
#include <qv4variantobject_p.h>
#include <qv4runtime_p.h>
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include <qv4argumentsobject_p.h>
#include <qv4dateobject_p.h>
#include <qv4jsonobject_p.h>
@@ -59,7 +59,6 @@
#include "qv4executableallocator_p.h"
#include "qv4sequenceobject_p.h"
#include "qv4qobjectwrapper_p.h"
-#include "qv4qmlextensions_p.h"
#include "qv4memberdata_p.h"
#include "qv4arraybuffer_p.h"
#include "qv4dataview_p.h"
@@ -197,9 +196,11 @@ QQmlEngine *ExecutionEngine::qmlEngine() const
ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
: current(0)
+ , hasException(false)
, memoryManager(new QV4::MemoryManager(this))
, executableAllocator(new QV4::ExecutableAllocator)
, regExpAllocator(new QV4::ExecutableAllocator)
+ , currentContext(0)
, bumperPointerAllocator(new WTF::BumpPointerAllocator)
, jsStack(new WTF::PageAllocation)
, debugger(0)
@@ -211,17 +212,13 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
, m_engineId(engineSerial.fetchAndAddOrdered(1))
, regExpCache(0)
, m_multiplyWrappedQObjects(0)
- , m_qmlExtensions(0)
{
MemoryManager::GCBlocker gcBlocker(memoryManager);
- exceptionValue = Encode::undefined();
- hasException = false;
-
if (!factory) {
#ifdef V4_ENABLE_JIT
- static const bool forceMoth = !qgetenv("QV4_FORCE_INTERPRETER").isEmpty();
+ static const bool forceMoth = !qEnvironmentVariableIsEmpty("QV4_FORCE_INTERPRETER");
if (forceMoth)
factory = new Moth::ISelFactory;
else
@@ -241,6 +238,13 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
jsStackBase = (Value *)jsStack->base();
jsStackTop = jsStackBase;
+ exceptionValue = jsAlloca(1);
+ globalObject = static_cast<Object *>(jsAlloca(1));
+ jsObjects = jsAlloca(NJSObjects);
+ typedArrayPrototype = static_cast<Object *>(jsAlloca(NTypedArrayTypes));
+ typedArrayCtors = static_cast<FunctionObject *>(jsAlloca(NTypedArrayTypes));
+ jsStrings = jsAlloca(NJSStrings);
+
#ifdef V4_USE_VALGRIND
VALGRIND_MAKE_MEM_UNDEFINED(jsStackBase, 2*JSStackLimit);
#endif
@@ -251,208 +255,240 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
if (!recheckCStackLimits())
qFatal("Fatal: Not enough stack space available for QML. Please increase the process stack size to more than %d KBytes.", MinimumStackSize);
- Scope scope(this);
-
identifierTable = new IdentifierTable(this);
classPool = new InternalClassPool;
emptyClass = new (classPool) InternalClass(this);
- id_empty = newIdentifier(QString());
- id_undefined = newIdentifier(QStringLiteral("undefined"));
- id_null = newIdentifier(QStringLiteral("null"));
- id_true = newIdentifier(QStringLiteral("true"));
- id_false = newIdentifier(QStringLiteral("false"));
- id_boolean = newIdentifier(QStringLiteral("boolean"));
- id_number = newIdentifier(QStringLiteral("number"));
- id_string = newIdentifier(QStringLiteral("string"));
- id_object = newIdentifier(QStringLiteral("object"));
- id_function = newIdentifier(QStringLiteral("function"));
- id_length = newIdentifier(QStringLiteral("length"));
- id_prototype = newIdentifier(QStringLiteral("prototype"));
- id_constructor = newIdentifier(QStringLiteral("constructor"));
- id_arguments = newIdentifier(QStringLiteral("arguments"));
- id_caller = newIdentifier(QStringLiteral("caller"));
- id_callee = newIdentifier(QStringLiteral("callee"));
- id_this = newIdentifier(QStringLiteral("this"));
- id___proto__ = newIdentifier(QStringLiteral("__proto__"));
- id_enumerable = newIdentifier(QStringLiteral("enumerable"));
- id_configurable = newIdentifier(QStringLiteral("configurable"));
- id_writable = newIdentifier(QStringLiteral("writable"));
- id_value = newIdentifier(QStringLiteral("value"));
- id_get = newIdentifier(QStringLiteral("get"));
- id_set = newIdentifier(QStringLiteral("set"));
- id_eval = newIdentifier(QStringLiteral("eval"));
- id_uintMax = newIdentifier(QStringLiteral("4294967295"));
- id_name = newIdentifier(QStringLiteral("name"));
- id_index = newIdentifier(QStringLiteral("index"));
- id_input = newIdentifier(QStringLiteral("input"));
- id_toString = newIdentifier(QStringLiteral("toString"));
- id_destroy = newIdentifier(QStringLiteral("destroy"));
- id_valueOf = newIdentifier(QStringLiteral("valueOf"));
- id_byteLength = newIdentifier(QStringLiteral("byteLength"));
- id_byteOffset = newIdentifier(QStringLiteral("byteOffset"));
- id_buffer = newIdentifier(QStringLiteral("buffer"));
- id_lastIndex = newIdentifier(QStringLiteral("lastIndex"));
-
- objectPrototype = memoryManager->alloc<ObjectPrototype>(emptyClass, (QV4::Object *)0);
-
- arrayClass = emptyClass->addMember(id_length, Attr_NotConfigurable|Attr_NotEnumerable);
- arrayPrototype = memoryManager->alloc<ArrayPrototype>(arrayClass, objectPrototype.asObject());
-
- InternalClass *argsClass = emptyClass->addMember(id_length, Attr_NotEnumerable);
- argumentsObjectClass = argsClass->addMember(id_callee, Attr_Data|Attr_NotEnumerable);
- strictArgumentsObjectClass = argsClass->addMember(id_callee, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- strictArgumentsObjectClass = strictArgumentsObjectClass->addMember(id_caller, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
-
- m_globalObject = newObject();
- Q_ASSERT(globalObject()->d()->vtable);
+ jsStrings[String_Empty] = newIdentifier(QString());
+ jsStrings[String_undefined] = newIdentifier(QStringLiteral("undefined"));
+ jsStrings[String_null] = newIdentifier(QStringLiteral("null"));
+ jsStrings[String_true] = newIdentifier(QStringLiteral("true"));
+ jsStrings[String_false] = newIdentifier(QStringLiteral("false"));
+ jsStrings[String_boolean] = newIdentifier(QStringLiteral("boolean"));
+ jsStrings[String_number] = newIdentifier(QStringLiteral("number"));
+ jsStrings[String_string] = newIdentifier(QStringLiteral("string"));
+ jsStrings[String_object] = newIdentifier(QStringLiteral("object"));
+ jsStrings[String_function] = newIdentifier(QStringLiteral("function"));
+ jsStrings[String_length] = newIdentifier(QStringLiteral("length"));
+ jsStrings[String_prototype] = newIdentifier(QStringLiteral("prototype"));
+ jsStrings[String_constructor] = newIdentifier(QStringLiteral("constructor"));
+ jsStrings[String_arguments] = newIdentifier(QStringLiteral("arguments"));
+ jsStrings[String_caller] = newIdentifier(QStringLiteral("caller"));
+ jsStrings[String_callee] = newIdentifier(QStringLiteral("callee"));
+ jsStrings[String_this] = newIdentifier(QStringLiteral("this"));
+ jsStrings[String___proto__] = newIdentifier(QStringLiteral("__proto__"));
+ jsStrings[String_enumerable] = newIdentifier(QStringLiteral("enumerable"));
+ jsStrings[String_configurable] = newIdentifier(QStringLiteral("configurable"));
+ jsStrings[String_writable] = newIdentifier(QStringLiteral("writable"));
+ jsStrings[String_value] = newIdentifier(QStringLiteral("value"));
+ jsStrings[String_get] = newIdentifier(QStringLiteral("get"));
+ jsStrings[String_set] = newIdentifier(QStringLiteral("set"));
+ jsStrings[String_eval] = newIdentifier(QStringLiteral("eval"));
+ jsStrings[String_uintMax] = newIdentifier(QStringLiteral("4294967295"));
+ jsStrings[String_name] = newIdentifier(QStringLiteral("name"));
+ jsStrings[String_index] = newIdentifier(QStringLiteral("index"));
+ jsStrings[String_input] = newIdentifier(QStringLiteral("input"));
+ jsStrings[String_toString] = newIdentifier(QStringLiteral("toString"));
+ jsStrings[String_destroy] = newIdentifier(QStringLiteral("destroy"));
+ jsStrings[String_valueOf] = newIdentifier(QStringLiteral("valueOf"));
+ jsStrings[String_byteLength] = newIdentifier(QStringLiteral("byteLength"));
+ jsStrings[String_byteOffset] = newIdentifier(QStringLiteral("byteOffset"));
+ jsStrings[String_buffer] = newIdentifier(QStringLiteral("buffer"));
+ jsStrings[String_lastIndex] = newIdentifier(QStringLiteral("lastIndex"));
+
+ jsObjects[ObjectProto] = memoryManager->allocObject<ObjectPrototype>(emptyClass);
+
+ arrayClass = emptyClass->addMember(id_length(), Attr_NotConfigurable|Attr_NotEnumerable);
+ jsObjects[ArrayProto] = memoryManager->allocObject<ArrayPrototype>(arrayClass, objectPrototype());
+
+ InternalClass *argsClass = emptyClass->addMember(id_length(), Attr_NotEnumerable);
+ argumentsObjectClass = argsClass->addMember(id_callee(), Attr_Data|Attr_NotEnumerable);
+ strictArgumentsObjectClass = argsClass->addMember(id_callee(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ strictArgumentsObjectClass = strictArgumentsObjectClass->addMember(id_caller(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+
+ *static_cast<Value *>(globalObject) = newObject();
+ Q_ASSERT(globalObject->d()->vtable());
initRootContext();
- stringPrototype = memoryManager->alloc<StringPrototype>(emptyClass, objectPrototype.asObject());
- numberPrototype = memoryManager->alloc<NumberPrototype>(emptyClass, objectPrototype.asObject());
- booleanPrototype = memoryManager->alloc<BooleanPrototype>(emptyClass, objectPrototype.asObject());
- datePrototype = memoryManager->alloc<DatePrototype>(emptyClass, objectPrototype.asObject());
+ stringClass = emptyClass->addMember(id_length(), Attr_ReadOnly);
+ Q_ASSERT(stringClass->find(id_length()) == Heap::StringObject::LengthPropertyIndex);
+ jsObjects[StringProto] = memoryManager->allocObject<StringPrototype>(stringClass, objectPrototype());
+ jsObjects[NumberProto] = memoryManager->allocObject<NumberPrototype>(emptyClass, objectPrototype());
+ jsObjects[BooleanProto] = memoryManager->allocObject<BooleanPrototype>(emptyClass, objectPrototype());
+ jsObjects[DateProto] = memoryManager->allocObject<DatePrototype>(emptyClass, objectPrototype());
uint index;
- InternalClass *functionProtoClass = emptyClass->addMember(id_prototype, Attr_NotEnumerable, &index);
+ InternalClass *functionProtoClass = emptyClass->addMember(id_prototype(), Attr_NotEnumerable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_Prototype);
- functionPrototype = memoryManager->alloc<FunctionPrototype>(functionProtoClass, objectPrototype.asObject());
- functionClass = emptyClass->addMember(id_prototype, Attr_NotEnumerable|Attr_NotConfigurable, &index);
+ jsObjects[FunctionProto] = memoryManager->allocObject<FunctionPrototype>(functionProtoClass, objectPrototype());
+ functionClass = emptyClass->addMember(id_prototype(), Attr_NotEnumerable|Attr_NotConfigurable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_Prototype);
- simpleScriptFunctionClass = functionClass->addMember(id_name, Attr_ReadOnly, &index);
+ simpleScriptFunctionClass = functionClass->addMember(id_name(), Attr_ReadOnly, &index);
Q_ASSERT(index == Heap::SimpleScriptFunction::Index_Name);
- simpleScriptFunctionClass = simpleScriptFunctionClass->addMember(id_length, Attr_ReadOnly, &index);
+ simpleScriptFunctionClass = simpleScriptFunctionClass->addMember(id_length(), Attr_ReadOnly, &index);
Q_ASSERT(index == Heap::SimpleScriptFunction::Index_Length);
- protoClass = emptyClass->addMember(id_constructor, Attr_NotEnumerable, &index);
+ protoClass = emptyClass->addMember(id_constructor(), Attr_NotEnumerable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_ProtoConstructor);
- regExpPrototype = memoryManager->alloc<RegExpPrototype>(this);
- regExpExecArrayClass = arrayClass->addMember(id_index, Attr_Data, &index);
+ Scope scope(this);
+ ScopedString str(scope);
+ regExpObjectClass = emptyClass->addMember(id_lastIndex(), Attr_NotEnumerable|Attr_NotConfigurable, &index);
+ Q_ASSERT(index == RegExpObject::Index_LastIndex);
+ regExpObjectClass = regExpObjectClass->addMember((str = newIdentifier(QStringLiteral("source"))), Attr_ReadOnly, &index);
+ Q_ASSERT(index == RegExpObject::Index_Source);
+ regExpObjectClass = regExpObjectClass->addMember((str = newIdentifier(QStringLiteral("global"))), Attr_ReadOnly, &index);
+ Q_ASSERT(index == RegExpObject::Index_Global);
+ regExpObjectClass = regExpObjectClass->addMember((str = newIdentifier(QStringLiteral("ignoreCase"))), Attr_ReadOnly, &index);
+ Q_ASSERT(index == RegExpObject::Index_IgnoreCase);
+ regExpObjectClass = regExpObjectClass->addMember((str = newIdentifier(QStringLiteral("multiline"))), Attr_ReadOnly, &index);
+ Q_ASSERT(index == RegExpObject::Index_Multiline);
+
+ jsObjects[RegExpProto] = memoryManager->allocObject<RegExpPrototype>(regExpObjectClass, objectPrototype());
+ regExpExecArrayClass = arrayClass->addMember(id_index(), Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayIndex);
- regExpExecArrayClass = regExpExecArrayClass->addMember(id_input, Attr_Data, &index);
+ regExpExecArrayClass = regExpExecArrayClass->addMember(id_input(), Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayInput);
- errorPrototype = memoryManager->alloc<ErrorPrototype>(emptyClass, objectPrototype.asObject());
- evalErrorPrototype = memoryManager->alloc<EvalErrorPrototype>(emptyClass, errorPrototype.asObject());
- rangeErrorPrototype = memoryManager->alloc<RangeErrorPrototype>(emptyClass, errorPrototype.asObject());
- referenceErrorPrototype = memoryManager->alloc<ReferenceErrorPrototype>(emptyClass, errorPrototype.asObject());
- syntaxErrorPrototype = memoryManager->alloc<SyntaxErrorPrototype>(emptyClass, errorPrototype.asObject());
- typeErrorPrototype = memoryManager->alloc<TypeErrorPrototype>(emptyClass, errorPrototype.asObject());
- uRIErrorPrototype = memoryManager->alloc<URIErrorPrototype>(emptyClass, errorPrototype.asObject());
-
- variantPrototype = memoryManager->alloc<VariantPrototype>(emptyClass, objectPrototype.asObject());
- Q_ASSERT(variantPrototype.asObject()->prototype() == objectPrototype.asObject()->d());
-
- sequencePrototype = ScopedValue(scope, memoryManager->alloc<SequencePrototype>(arrayClass, arrayPrototype.asObject()));
-
- ScopedContext global(scope, rootContext());
- objectCtor = memoryManager->alloc<ObjectCtor>(global);
- stringCtor = memoryManager->alloc<StringCtor>(global);
- numberCtor = memoryManager->alloc<NumberCtor>(global);
- booleanCtor = memoryManager->alloc<BooleanCtor>(global);
- arrayCtor = memoryManager->alloc<ArrayCtor>(global);
- functionCtor = memoryManager->alloc<FunctionCtor>(global);
- dateCtor = memoryManager->alloc<DateCtor>(global);
- regExpCtor = memoryManager->alloc<RegExpCtor>(global);
- errorCtor = memoryManager->alloc<ErrorCtor>(global);
- evalErrorCtor = memoryManager->alloc<EvalErrorCtor>(global);
- rangeErrorCtor = memoryManager->alloc<RangeErrorCtor>(global);
- referenceErrorCtor = memoryManager->alloc<ReferenceErrorCtor>(global);
- syntaxErrorCtor = memoryManager->alloc<SyntaxErrorCtor>(global);
- typeErrorCtor = memoryManager->alloc<TypeErrorCtor>(global);
- uRIErrorCtor = memoryManager->alloc<URIErrorCtor>(global);
-
- static_cast<ObjectPrototype *>(objectPrototype.asObject())->init(this, objectCtor.asObject());
- static_cast<StringPrototype *>(stringPrototype.asObject())->init(this, stringCtor.asObject());
- static_cast<NumberPrototype *>(numberPrototype.asObject())->init(this, numberCtor.asObject());
- static_cast<BooleanPrototype *>(booleanPrototype.asObject())->init(this, booleanCtor.asObject());
- static_cast<ArrayPrototype *>(arrayPrototype.asObject())->init(this, arrayCtor.asObject());
- static_cast<DatePrototype *>(datePrototype.asObject())->init(this, dateCtor.asObject());
- static_cast<FunctionPrototype *>(functionPrototype.asObject())->init(this, functionCtor.asObject());
- static_cast<RegExpPrototype *>(regExpPrototype.asObject())->init(this, regExpCtor.asObject());
- static_cast<ErrorPrototype *>(errorPrototype.asObject())->init(this, errorCtor.asObject());
- static_cast<EvalErrorPrototype *>(evalErrorPrototype.asObject())->init(this, evalErrorCtor.asObject());
- static_cast<RangeErrorPrototype *>(rangeErrorPrototype.asObject())->init(this, rangeErrorCtor.asObject());
- static_cast<ReferenceErrorPrototype *>(referenceErrorPrototype.asObject())->init(this, referenceErrorCtor.asObject());
- static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype.asObject())->init(this, syntaxErrorCtor.asObject());
- static_cast<TypeErrorPrototype *>(typeErrorPrototype.asObject())->init(this, typeErrorCtor.asObject());
- static_cast<URIErrorPrototype *>(uRIErrorPrototype.asObject())->init(this, uRIErrorCtor.asObject());
-
- static_cast<VariantPrototype *>(variantPrototype.asObject())->init();
- sequencePrototype.cast<SequencePrototype>()->init();
+ errorClass = emptyClass->addMember((str = newIdentifier(QStringLiteral("stack"))), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorObject::Index_Stack);
+ errorClass = errorClass->addMember((str = newIdentifier(QStringLiteral("fileName"))), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorObject::Index_FileName);
+ errorClass = errorClass->addMember((str = newIdentifier(QStringLiteral("lineNumber"))), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorObject::Index_LineNumber);
+ errorClassWithMessage = errorClass->addMember((str = newIdentifier(QStringLiteral("message"))), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorObject::Index_Message);
+ errorProtoClass = emptyClass->addMember(id_constructor(), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorPrototype::Index_Constructor);
+ errorProtoClass = errorProtoClass->addMember((str = newIdentifier(QStringLiteral("message"))), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorPrototype::Index_Message);
+ errorProtoClass = errorProtoClass->addMember(id_name(), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorPrototype::Index_Name);
+
+ jsObjects[GetStack_Function] = BuiltinFunction::create(rootContext(), str = newIdentifier(QStringLiteral("stack")), ErrorObject::method_get_stack);
+ getStackFunction()->defineReadonlyProperty(id_length(), Primitive::fromInt32(0));
+
+ jsObjects[ErrorProto] = memoryManager->allocObject<ErrorPrototype>(errorProtoClass, objectPrototype());
+ jsObjects[EvalErrorProto] = memoryManager->allocObject<EvalErrorPrototype>(errorProtoClass, errorPrototype());
+ jsObjects[RangeErrorProto] = memoryManager->allocObject<RangeErrorPrototype>(errorProtoClass, errorPrototype());
+ jsObjects[ReferenceErrorProto] = memoryManager->allocObject<ReferenceErrorPrototype>(errorProtoClass, errorPrototype());
+ jsObjects[SyntaxErrorProto] = memoryManager->allocObject<SyntaxErrorPrototype>(errorProtoClass, errorPrototype());
+ jsObjects[TypeErrorProto] = memoryManager->allocObject<TypeErrorPrototype>(errorProtoClass, errorPrototype());
+ jsObjects[URIErrorProto] = memoryManager->allocObject<URIErrorPrototype>(errorProtoClass, errorPrototype());
+
+ jsObjects[VariantProto] = memoryManager->allocObject<VariantPrototype>(emptyClass, objectPrototype());
+ Q_ASSERT(variantPrototype()->prototype() == objectPrototype()->d());
+
+ jsObjects[SequenceProto] = ScopedValue(scope, memoryManager->allocObject<SequencePrototype>(arrayClass, arrayPrototype()));
+
+ ExecutionContext *global = rootContext();
+ jsObjects[Object_Ctor] = memoryManager->allocObject<ObjectCtor>(global);
+ jsObjects[String_Ctor] = memoryManager->allocObject<StringCtor>(global);
+ jsObjects[Number_Ctor] = memoryManager->allocObject<NumberCtor>(global);
+ jsObjects[Boolean_Ctor] = memoryManager->allocObject<BooleanCtor>(global);
+ jsObjects[Array_Ctor] = memoryManager->allocObject<ArrayCtor>(global);
+ jsObjects[Function_Ctor] = memoryManager->allocObject<FunctionCtor>(global);
+ jsObjects[Date_Ctor] = memoryManager->allocObject<DateCtor>(global);
+ jsObjects[RegExp_Ctor] = memoryManager->allocObject<RegExpCtor>(global);
+ jsObjects[Error_Ctor] = memoryManager->allocObject<ErrorCtor>(global);
+ jsObjects[EvalError_Ctor] = memoryManager->allocObject<EvalErrorCtor>(global);
+ jsObjects[RangeError_Ctor] = memoryManager->allocObject<RangeErrorCtor>(global);
+ jsObjects[ReferenceError_Ctor] = memoryManager->allocObject<ReferenceErrorCtor>(global);
+ jsObjects[SyntaxError_Ctor] = memoryManager->allocObject<SyntaxErrorCtor>(global);
+ jsObjects[TypeError_Ctor] = memoryManager->allocObject<TypeErrorCtor>(global);
+ jsObjects[URIError_Ctor] = memoryManager->allocObject<URIErrorCtor>(global);
+
+ static_cast<ObjectPrototype *>(objectPrototype())->init(this, objectCtor());
+ static_cast<StringPrototype *>(stringPrototype())->init(this, stringCtor());
+ static_cast<NumberPrototype *>(numberPrototype())->init(this, numberCtor());
+ static_cast<BooleanPrototype *>(booleanPrototype())->init(this, booleanCtor());
+ static_cast<ArrayPrototype *>(arrayPrototype())->init(this, arrayCtor());
+ static_cast<DatePrototype *>(datePrototype())->init(this, dateCtor());
+ static_cast<FunctionPrototype *>(functionPrototype())->init(this, functionCtor());
+ static_cast<RegExpPrototype *>(regExpPrototype())->init(this, regExpCtor());
+ static_cast<ErrorPrototype *>(errorPrototype())->init(this, errorCtor());
+ static_cast<EvalErrorPrototype *>(evalErrorPrototype())->init(this, evalErrorCtor());
+ static_cast<RangeErrorPrototype *>(rangeErrorPrototype())->init(this, rangeErrorCtor());
+ static_cast<ReferenceErrorPrototype *>(referenceErrorPrototype())->init(this, referenceErrorCtor());
+ static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype())->init(this, syntaxErrorCtor());
+ static_cast<TypeErrorPrototype *>(typeErrorPrototype())->init(this, typeErrorCtor());
+ static_cast<URIErrorPrototype *>(uRIErrorPrototype())->init(this, uRIErrorCtor());
+
+ static_cast<VariantPrototype *>(variantPrototype())->init();
+ sequencePrototype()->cast<SequencePrototype>()->init();
// typed arrays
- arrayBufferCtor = memoryManager->alloc<ArrayBufferCtor>(global);
- arrayBufferPrototype = memoryManager->alloc<ArrayBufferPrototype>(emptyClass, objectPrototype.asObject());
- static_cast<ArrayBufferPrototype *>(arrayBufferPrototype.asObject())->init(this, arrayBufferCtor.asObject());
+ jsObjects[ArrayBuffer_Ctor] = memoryManager->allocObject<ArrayBufferCtor>(global);
+ jsObjects[ArrayBufferProto] = memoryManager->allocObject<ArrayBufferPrototype>();
+ static_cast<ArrayBufferPrototype *>(arrayBufferPrototype())->init(this, arrayBufferCtor());
- dataViewCtor = memoryManager->alloc<DataViewCtor>(global);
- dataViewPrototype = memoryManager->alloc<DataViewPrototype>(emptyClass, objectPrototype.asObject());
- static_cast<DataViewPrototype *>(dataViewPrototype.asObject())->init(this, dataViewCtor.asObject());
+ jsObjects[DataView_Ctor] = memoryManager->allocObject<DataViewCtor>(global);
+ jsObjects[DataViewProto] = memoryManager->allocObject<DataViewPrototype>();
+ static_cast<DataViewPrototype *>(dataViewPrototype())->init(this, dataViewCtor());
+ jsObjects[ValueTypeProto] = (Heap::Base *) 0;
+ jsObjects[SignalHandlerProto] = (Heap::Base *) 0;
for (int i = 0; i < Heap::TypedArray::NTypes; ++i) {
- typedArrayCtors[i] = memoryManager->alloc<TypedArrayCtor>(global, Heap::TypedArray::Type(i));
- typedArrayPrototype[i] = memoryManager->alloc<TypedArrayPrototype>(this, Heap::TypedArray::Type(i));
- typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].asObject()));
+ static_cast<Value &>(typedArrayCtors[i]) = memoryManager->allocObject<TypedArrayCtor>(global, Heap::TypedArray::Type(i));
+ static_cast<Value &>(typedArrayPrototype[i]) = memoryManager->allocObject<TypedArrayPrototype>(Heap::TypedArray::Type(i));
+ typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].as<Object>()));
}
//
// set up the global object
//
- rootContext()->global = globalObject()->d();
- rootContext()->callData->thisObject = globalObject();
- Q_ASSERT(globalObject()->d()->vtable);
-
- globalObject()->defineDefaultProperty(QStringLiteral("Object"), objectCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("String"), stringCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Number"), numberCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Boolean"), booleanCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Array"), arrayCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Function"), functionCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Date"), dateCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("RegExp"), regExpCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Error"), errorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("EvalError"), evalErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("RangeError"), rangeErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("ReferenceError"), referenceErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("SyntaxError"), syntaxErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("TypeError"), typeErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("URIError"), uRIErrorCtor);
-
- globalObject()->defineDefaultProperty(QStringLiteral("ArrayBuffer"), arrayBufferCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("DataView"), dataViewCtor);
- ScopedString str(scope);
+ rootContext()->d()->global = globalObject->d();
+ rootContext()->d()->callData->thisObject = globalObject;
+ Q_ASSERT(globalObject->d()->vtable());
+
+ globalObject->defineDefaultProperty(QStringLiteral("Object"), *objectCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("String"), *stringCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Number"), *numberCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Boolean"), *booleanCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Array"), *arrayCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Function"), *functionCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Date"), *dateCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("RegExp"), *regExpCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Error"), *errorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("EvalError"), *evalErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("RangeError"), *rangeErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("ReferenceError"), *referenceErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("SyntaxError"), *syntaxErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("TypeError"), *typeErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("URIError"), *uRIErrorCtor());
+
+ globalObject->defineDefaultProperty(QStringLiteral("ArrayBuffer"), *arrayBufferCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("DataView"), *dataViewCtor());
for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
- globalObject()->defineDefaultProperty((str = typedArrayCtors[i].asFunctionObject()->name())->toQString(), typedArrayCtors[i]);
+ globalObject->defineDefaultProperty((str = typedArrayCtors[i].as<FunctionObject>()->name())->toQString(), typedArrayCtors[i]);
ScopedObject o(scope);
- globalObject()->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->alloc<MathObject>(this)));
- globalObject()->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->alloc<JsonObject>(this)));
+ globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->allocObject<MathObject>()));
+ globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->allocObject<JsonObject>()));
- globalObject()->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue());
- globalObject()->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN()));
- globalObject()->defineReadonlyProperty(QStringLiteral("Infinity"), Primitive::fromDouble(Q_INFINITY));
+ globalObject->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue());
+ globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN()));
+ globalObject->defineReadonlyProperty(QStringLiteral("Infinity"), Primitive::fromDouble(Q_INFINITY));
- evalFunction = memoryManager->alloc<EvalFunction>(global);
- globalObject()->defineDefaultProperty(QStringLiteral("eval"), (o = evalFunction));
+ jsObjects[Eval_Function] = memoryManager->allocObject<EvalFunction>(global);
+ globalObject->defineDefaultProperty(QStringLiteral("eval"), *evalFunction());
- globalObject()->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2);
- globalObject()->defineDefaultProperty(QStringLiteral("parseFloat"), GlobalFunctions::method_parseFloat, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("isNaN"), GlobalFunctions::method_isNaN, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("isFinite"), GlobalFunctions::method_isFinite, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("decodeURI"), GlobalFunctions::method_decodeURI, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("decodeURIComponent"), GlobalFunctions::method_decodeURIComponent, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("encodeURI"), GlobalFunctions::method_encodeURI, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("encodeURIComponent"), GlobalFunctions::method_encodeURIComponent, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("escape"), GlobalFunctions::method_escape, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2);
+ globalObject->defineDefaultProperty(QStringLiteral("parseFloat"), GlobalFunctions::method_parseFloat, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("isNaN"), GlobalFunctions::method_isNaN, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("isFinite"), GlobalFunctions::method_isFinite, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("decodeURI"), GlobalFunctions::method_decodeURI, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("decodeURIComponent"), GlobalFunctions::method_decodeURIComponent, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("encodeURI"), GlobalFunctions::method_encodeURI, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("encodeURIComponent"), GlobalFunctions::method_encodeURIComponent, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("escape"), GlobalFunctions::method_escape, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1);
ScopedString name(scope, newString(QStringLiteral("thrower")));
- thrower = BuiltinFunction::create(global, name, ::throwTypeError);
+ jsObjects[ThrowerObject] = BuiltinFunction::create(global, name, ::throwTypeError);
}
ExecutionEngine::~ExecutionEngine()
@@ -471,7 +507,6 @@ ExecutionEngine::~ExecutionEngine()
foreach (QV4::CompiledData::CompilationUnit *unit, remainingUnits)
unit->unlink();
- delete m_qmlExtensions;
emptyClass->destroy();
delete classPool;
delete bumperPointerAllocator;
@@ -483,11 +518,10 @@ ExecutionEngine::~ExecutionEngine()
delete [] argumentsAccessors;
}
-void ExecutionEngine::enableDebugger()
+void ExecutionEngine::setDebugger(Debugging::Debugger *debugger_)
{
Q_ASSERT(!debugger);
- debugger = new Debugging::Debugger(this);
- iselFactory.reset(new Moth::ISelFactory);
+ debugger = debugger_;
}
void ExecutionEngine::enableProfiler()
@@ -502,12 +536,15 @@ void ExecutionEngine::initRootContext()
Scoped<GlobalContext> r(scope, memoryManager->allocManaged<GlobalContext>(sizeof(GlobalContext::Data) + sizeof(CallData)));
new (r->d()) GlobalContext::Data(this);
r->d()->callData = reinterpret_cast<CallData *>(r->d() + 1);
- r->d()->callData->tag = QV4::Value::_Integer_Type;
+ r->d()->callData->tag = QV4::Value::Integer_Type_Internal;
r->d()->callData->argc = 0;
- r->d()->callData->thisObject = globalObject();
+ r->d()->callData->thisObject = globalObject;
r->d()->callData->args[0] = Encode::undefined();
+ jsObjects[RootContext] = r;
+ jsObjects[IntegerNull] = Encode((int)0);
- m_rootContext = r->d();
+ currentContext = static_cast<ExecutionContext *>(jsObjects + RootContext);
+ current = currentContext->d();
}
InternalClass *ExecutionEngine::newClass(const InternalClass &other)
@@ -515,29 +552,31 @@ InternalClass *ExecutionEngine::newClass(const InternalClass &other)
return new (classPool) InternalClass(other);
}
-Heap::ExecutionContext *ExecutionEngine::pushGlobalContext()
+ExecutionContext *ExecutionEngine::pushGlobalContext()
{
- Scope scope(this);
- Scoped<GlobalContext> g(scope, memoryManager->alloc<GlobalContext>(this));
- g->d()->callData = rootContext()->callData;
+ pushContext(rootContext()->d());
+
+ Q_ASSERT(current == rootContext()->d());
+ return currentContext;
+}
- Q_ASSERT(currentContext() == g->d());
- return g->d();
+ExecutionContext *ExecutionEngine::parentContext(ExecutionContext *context) const
+{
+ Value *offset = static_cast<Value *>(context) + 1;
+ Q_ASSERT(offset->isInteger());
+ int o = offset->integerValue();
+ return o ? context - o : 0;
}
Heap::Object *ExecutionEngine::newObject()
{
- Scope scope(this);
- ScopedObject object(scope, memoryManager->alloc<Object>(this));
- return object->d();
+ return memoryManager->allocObject<Object>();
}
Heap::Object *ExecutionEngine::newObject(InternalClass *internalClass, QV4::Object *prototype)
{
- Scope scope(this);
- ScopedObject object(scope, memoryManager->alloc<Object>(internalClass, prototype));
- return object->d();
+ return memoryManager->allocObject<Object>(internalClass, prototype);
}
Heap::String *ExecutionEngine::newString(const QString &s)
@@ -551,31 +590,25 @@ Heap::String *ExecutionEngine::newIdentifier(const QString &text)
return identifierTable->insertString(text);
}
-Heap::Object *ExecutionEngine::newStringObject(const Value &value)
+Heap::Object *ExecutionEngine::newStringObject(const String *string)
{
- Scope scope(this);
- Scoped<StringObject> object(scope, memoryManager->alloc<StringObject>(this, value));
- return object->d();
+ return memoryManager->allocObject<StringObject>(string);
}
Heap::Object *ExecutionEngine::newNumberObject(double value)
{
- Scope scope(this);
- Scoped<NumberObject> object(scope, memoryManager->alloc<NumberObject>(this, value));
- return object->d();
+ return memoryManager->allocObject<NumberObject>(value);
}
Heap::Object *ExecutionEngine::newBooleanObject(bool b)
{
- Scope scope(this);
- ScopedObject object(scope, memoryManager->alloc<BooleanObject>(this, b));
- return object->d();
+ return memoryManager->allocObject<BooleanObject>(b);
}
Heap::ArrayObject *ExecutionEngine::newArrayObject(int count)
{
Scope scope(this);
- ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(this));
+ ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>());
if (count) {
if (count < 0x1000)
@@ -585,39 +618,60 @@ Heap::ArrayObject *ExecutionEngine::newArrayObject(int count)
return object->d();
}
+Heap::ArrayObject *ExecutionEngine::newArrayObject(const Value *values, int length)
+{
+ Scope scope(this);
+ ScopedArrayObject a(scope, memoryManager->allocObject<ArrayObject>());
+
+ if (length) {
+ size_t size = sizeof(Heap::ArrayData) + (length-1)*sizeof(Value);
+ Heap::SimpleArrayData *d = scope.engine->memoryManager->allocManaged<SimpleArrayData>(size);
+ new (d) Heap::SimpleArrayData;
+ d->alloc = length;
+ d->type = Heap::ArrayData::Simple;
+ d->offset = 0;
+ d->len = length;
+ memcpy(&d->arrayData, values, length*sizeof(Value));
+ a->d()->arrayData = d;
+ a->setArrayLengthUnchecked(length);
+ }
+ return a->d();
+}
+
Heap::ArrayObject *ExecutionEngine::newArrayObject(const QStringList &list)
{
Scope scope(this);
- ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(this, list));
+ ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>(list));
return object->d();
}
-Heap::ArrayObject *ExecutionEngine::newArrayObject(InternalClass *ic, Object *prototype)
+Heap::ArrayObject *ExecutionEngine::newArrayObject(InternalClass *internalClass, Object *prototype)
{
Scope scope(this);
- ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(ic, prototype));
+ ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>(internalClass, prototype));
return object->d();
}
Heap::ArrayBuffer *ExecutionEngine::newArrayBuffer(const QByteArray &array)
{
- Scope scope(this);
- Scoped<ArrayBuffer> object(scope, memoryManager->alloc<ArrayBuffer>(this, array));
- return object->d();
+ return memoryManager->allocObject<ArrayBuffer>(array);
+}
+
+Heap::ArrayBuffer *ExecutionEngine::newArrayBuffer(size_t length)
+{
+ return memoryManager->allocObject<ArrayBuffer>(length);
}
Heap::DateObject *ExecutionEngine::newDateObject(const Value &value)
{
- Scope scope(this);
- Scoped<DateObject> object(scope, memoryManager->alloc<DateObject>(this, value));
- return object->d();
+ return memoryManager->allocObject<DateObject>(value);
}
Heap::DateObject *ExecutionEngine::newDateObject(const QDateTime &dt)
{
Scope scope(this);
- Scoped<DateObject> object(scope, memoryManager->alloc<DateObject>(this, dt));
+ Scoped<DateObject> object(scope, memoryManager->allocObject<DateObject>(dt));
return object->d();
}
@@ -638,97 +692,75 @@ Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QString &pattern, int
Heap::RegExpObject *ExecutionEngine::newRegExpObject(RegExp *re, bool global)
{
- Scope scope(this);
- Scoped<RegExpObject> object(scope, memoryManager->alloc<RegExpObject>(this, re, global));
- return object->d();
+ return memoryManager->allocObject<RegExpObject>(re, global);
}
Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re)
{
- Scope scope(this);
- Scoped<RegExpObject> object(scope, memoryManager->alloc<RegExpObject>(this, re));
- return object->d();
+ return memoryManager->allocObject<RegExpObject>(re);
}
Heap::Object *ExecutionEngine::newErrorObject(const Value &value)
{
- Scope scope(this);
- ScopedObject object(scope, memoryManager->alloc<ErrorObject>(emptyClass, errorPrototype.asObject(), value));
- return object->d();
+ return ErrorObject::create<ErrorObject>(this, value);
}
Heap::Object *ExecutionEngine::newSyntaxErrorObject(const QString &message)
{
- Scope scope(this);
- ScopedString s(scope, newString(message));
- ScopedObject error(scope, memoryManager->alloc<SyntaxErrorObject>(this, s));
- return error->d();
+ return ErrorObject::create<SyntaxErrorObject>(this, message);
}
Heap::Object *ExecutionEngine::newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column)
{
- Scope scope(this);
- ScopedObject error(scope, memoryManager->alloc<SyntaxErrorObject>(this, message, fileName, line, column));
- return error->d();
+ return ErrorObject::create<SyntaxErrorObject>(this, message, fileName, line, column);
}
Heap::Object *ExecutionEngine::newReferenceErrorObject(const QString &message)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<ReferenceErrorObject>(this, message));
- return o->d();
+ return ErrorObject::create<ReferenceErrorObject>(this, message);
}
-Heap::Object *ExecutionEngine::newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber, int columnNumber)
+Heap::Object *ExecutionEngine::newReferenceErrorObject(const QString &message, const QString &fileName, int line, int column)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<ReferenceErrorObject>(this, message, fileName, lineNumber, columnNumber));
- return o->d();
+ return ErrorObject::create<ReferenceErrorObject>(this, message, fileName, line, column);
}
Heap::Object *ExecutionEngine::newTypeErrorObject(const QString &message)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<TypeErrorObject>(this, message));
- return o->d();
+ return ErrorObject::create<TypeErrorObject>(this, message);
}
Heap::Object *ExecutionEngine::newRangeErrorObject(const QString &message)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<RangeErrorObject>(this, message));
- return o->d();
+ return ErrorObject::create<RangeErrorObject>(this, message);
}
Heap::Object *ExecutionEngine::newURIErrorObject(const Value &message)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<URIErrorObject>(this, message));
- return o->d();
+ return ErrorObject::create<URIErrorObject>(this, message);
}
Heap::Object *ExecutionEngine::newVariantObject(const QVariant &v)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<VariantObject>(this, v));
- return o->d();
+ return memoryManager->allocObject<VariantObject>(v);
}
Heap::Object *ExecutionEngine::newForEachIteratorObject(Object *o)
{
Scope scope(this);
- ScopedObject obj(scope, memoryManager->alloc<ForEachIteratorObject>(this, o));
+ ScopedObject obj(scope, memoryManager->allocObject<ForEachIteratorObject>(o));
return obj->d();
}
-Heap::Object *ExecutionEngine::qmlContextObject() const
+Heap::QmlContext *ExecutionEngine::qmlContext() const
{
- Heap::ExecutionContext *ctx = currentContext();
+ Heap::ExecutionContext *ctx = current;
+ // get the correct context when we're within a builtin function
if (ctx->type == Heap::ExecutionContext::Type_SimpleCallContext && !ctx->outer)
- ctx = ctx->parent;
+ ctx = parentContext(currentContext)->d();
if (!ctx->outer)
return 0;
@@ -740,8 +772,46 @@ Heap::Object *ExecutionEngine::qmlContextObject() const
if (ctx->type != Heap::ExecutionContext::Type_QmlContext)
return 0;
- Q_ASSERT(static_cast<Heap::CallContext *>(ctx)->activation);
- return static_cast<Heap::CallContext *>(ctx)->activation;
+ return static_cast<Heap::QmlContext *>(ctx);
+}
+
+QObject *ExecutionEngine::qmlScopeObject() const
+{
+ Heap::QmlContext *ctx = qmlContext();
+ if (!ctx)
+ return 0;
+
+ return ctx->qml->scopeObject;
+}
+
+ReturnedValue ExecutionEngine::qmlSingletonWrapper(String *name)
+{
+ QQmlContextData *ctx = callingQmlContext();
+ if (!ctx->imports)
+ return Encode::undefined();
+ // Search for attached properties, enums and imported scripts
+ QQmlTypeNameCache::Result r = ctx->imports->query(name);
+
+ Q_ASSERT(r.isValid());
+ Q_ASSERT(r.type);
+ Q_ASSERT(r.type->isSingleton());
+
+ QQmlType::SingletonInstanceInfo *siinfo = r.type->singletonInstanceInfo();
+ QQmlEngine *e = qmlEngine();
+ siinfo->init(e);
+
+ if (QObject *qobjectSingleton = siinfo->qobjectApi(e))
+ return QV4::QObjectWrapper::wrap(this, qobjectSingleton);
+ return QJSValuePrivate::convertedToValue(this, siinfo->scriptApi(e));
+}
+
+QQmlContextData *ExecutionEngine::callingQmlContext() const
+{
+ Heap::QmlContext *ctx = qmlContext();
+ if (!ctx)
+ return 0;
+
+ return ctx->qml->context.contextData();
}
QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
@@ -750,7 +820,7 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
ScopedString name(scope);
QVector<StackFrame> stack;
- ScopedContext c(scope, currentContext());
+ ExecutionContext *c = currentContext;
ScopedFunctionObject function(scope);
while (c && frameLimit) {
function = c->getFunctionObject();
@@ -770,14 +840,14 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
stack.append(frame);
--frameLimit;
}
- c = c->d()->parent;
+ c = parentContext(c);
}
if (frameLimit && globalCode) {
StackFrame frame;
frame.source = globalCode->sourceFile();
frame.function = globalCode->name()->toQString();
- frame.line = rootContext()->lineNumber;
+ frame.line = rootContext()->d()->lineNumber;
frame.column = -1;
stack.append(frame);
@@ -838,8 +908,7 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file)
return src;
QUrl base;
- Scope scope(this);
- ScopedContext c(scope, currentContext());
+ ExecutionContext *c = currentContext;
while (c) {
CallContext *callCtx = c->asCallContext();
if (callCtx && callCtx->d()->function) {
@@ -847,7 +916,7 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file)
base.setUrl(callCtx->d()->function->function->sourceFile());
break;
}
- c = c->d()->parent;
+ c = parentContext(c);
}
if (base.isEmpty() && globalCode)
@@ -877,10 +946,10 @@ void ExecutionEngine::requireArgumentsAccessors(int n)
memcpy(argumentsAccessors, oldAccessors, oldSize*sizeof(Property));
delete [] oldAccessors;
}
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = rootContext();
for (int i = oldSize; i < nArgumentsAccessors; ++i) {
- argumentsAccessors[i].value = ScopedValue(scope, memoryManager->alloc<ArgumentsGetterFunction>(global, i));
- argumentsAccessors[i].set = ScopedValue(scope, memoryManager->alloc<ArgumentsSetterFunction>(global, i));
+ argumentsAccessors[i].value = ScopedValue(scope, memoryManager->allocObject<ArgumentsGetterFunction>(global, i));
+ argumentsAccessors[i].set = ScopedValue(scope, memoryManager->allocObject<ArgumentsSetterFunction>(global, i));
}
}
}
@@ -889,8 +958,6 @@ void ExecutionEngine::markObjects()
{
identifierTable->mark(this);
- globalObject()->mark(this);
-
for (int i = 0; i < nArgumentsAccessors; ++i) {
const Property &pd = argumentsAccessors[i];
if (Heap::FunctionObject *getter = pd.getter())
@@ -899,103 +966,6 @@ void ExecutionEngine::markObjects()
setter->mark(this);
}
- Heap::ExecutionContext *c = currentContext();
- while (c) {
- Q_ASSERT(c->inUse());
- if (!c->isMarked()) {
- c->setMarkBit();
- c->gcGetVtable()->markObjects(c, this);
- }
- c = c->parent;
- }
-
- id_empty->mark(this);
- id_undefined->mark(this);
- id_null->mark(this);
- id_true->mark(this);
- id_false->mark(this);
- id_boolean->mark(this);
- id_number->mark(this);
- id_string->mark(this);
- id_object->mark(this);
- id_function->mark(this);
- id_length->mark(this);
- id_prototype->mark(this);
- id_constructor->mark(this);
- id_arguments->mark(this);
- id_caller->mark(this);
- id_callee->mark(this);
- id_this->mark(this);
- id___proto__->mark(this);
- id_enumerable->mark(this);
- id_configurable->mark(this);
- id_writable->mark(this);
- id_value->mark(this);
- id_get->mark(this);
- id_set->mark(this);
- id_eval->mark(this);
- id_uintMax->mark(this);
- id_name->mark(this);
- id_index->mark(this);
- id_input->mark(this);
- id_toString->mark(this);
- id_destroy->mark(this);
- id_valueOf->mark(this);
- id_byteLength->mark(this);
- id_byteOffset->mark(this);
- id_buffer->mark(this);
- id_lastIndex->mark(this);
-
- objectCtor.mark(this);
- stringCtor.mark(this);
- numberCtor.mark(this);
- booleanCtor.mark(this);
- arrayCtor.mark(this);
- functionCtor.mark(this);
- dateCtor.mark(this);
- regExpCtor.mark(this);
- errorCtor.mark(this);
- evalErrorCtor.mark(this);
- rangeErrorCtor.mark(this);
- referenceErrorCtor.mark(this);
- syntaxErrorCtor.mark(this);
- typeErrorCtor.mark(this);
- uRIErrorCtor.mark(this);
- arrayBufferCtor.mark(this);
- dataViewCtor.mark(this);
- for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
- typedArrayCtors[i].mark(this);
-
- objectPrototype.mark(this);
- arrayPrototype.mark(this);
- stringPrototype.mark(this);
- numberPrototype.mark(this);
- booleanPrototype.mark(this);
- datePrototype.mark(this);
- functionPrototype.mark(this);
- regExpPrototype.mark(this);
- errorPrototype.mark(this);
- evalErrorPrototype.mark(this);
- rangeErrorPrototype.mark(this);
- referenceErrorPrototype.mark(this);
- syntaxErrorPrototype.mark(this);
- typeErrorPrototype.mark(this);
- uRIErrorPrototype.mark(this);
- variantPrototype.mark(this);
- sequencePrototype.mark(this);
-
- arrayBufferPrototype.mark(this);
- dataViewPrototype.mark(this);
- for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
- typedArrayPrototype[i].mark(this);
-
- exceptionValue.mark(this);
-
- thrower->mark(this);
-
- if (m_qmlExtensions)
- m_qmlExtensions->markObjects(this);
-
classPool->markObjects(this);
for (QSet<CompiledData::CompilationUnit*>::ConstIterator it = compilationUnits.constBegin(), end = compilationUnits.constEnd();
@@ -1003,13 +973,6 @@ void ExecutionEngine::markObjects()
(*it)->markObjects(this);
}
-QmlExtensions *ExecutionEngine::qmlExtensions()
-{
- if (!m_qmlExtensions)
- m_qmlExtensions = new QmlExtensions;
- return m_qmlExtensions;
-}
-
ReturnedValue ExecutionEngine::throwError(const Value &value)
{
// we can get in here with an exception already set, as the runtime
@@ -1020,7 +983,7 @@ ReturnedValue ExecutionEngine::throwError(const Value &value)
return Encode::undefined();
hasException = true;
- exceptionValue = value;
+ *exceptionValue = value;
QV4::Scope scope(this);
QV4::Scoped<ErrorObject> error(scope, value);
if (!!error)
@@ -1041,8 +1004,8 @@ ReturnedValue ExecutionEngine::catchException(StackTrace *trace)
*trace = exceptionStackTrace;
exceptionStackTrace.clear();
hasException = false;
- ReturnedValue res = exceptionValue.asReturnedValue();
- exceptionValue = Primitive::emptyValue();
+ ReturnedValue res = exceptionValue->asReturnedValue();
+ *exceptionValue = Primitive::emptyValue();
return res;
}
@@ -1139,7 +1102,7 @@ QQmlError ExecutionEngine::catchExceptionAsQmlError()
QV4::ScopedValue exception(scope, catchException(&trace));
QQmlError error;
if (!trace.isEmpty()) {
- QV4::StackFrame frame = trace.first();
+ QV4::StackFrame frame = trace.constFirst();
error.setUrl(QUrl(frame.source));
error.setLine(frame.line);
error.setColumn(frame.column);
@@ -1175,7 +1138,7 @@ bool ExecutionEngine::recheckCStackLimits()
typedef QSet<QV4::Heap::Object *> V4ObjectSet;
static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int typeHint, bool createJSValueForObjects, V4ObjectSet *visitedObjects);
static QObject *qtObjectFromJS(QV4::ExecutionEngine *engine, const QV4::Value &value);
-static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4ObjectSet *visitedObjects = 0);
+static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V4ObjectSet *visitedObjects = 0);
static bool convertToNativeQObject(QV4::ExecutionEngine *e, const QV4::Value &value,
const QByteArray &targetType,
void **result);
@@ -1198,7 +1161,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
Q_ASSERT (!value.isEmpty());
QV4::Scope scope(e);
- if (QV4::VariantObject *v = value.as<QV4::VariantObject>())
+ if (const QV4::VariantObject *v = value.as<QV4::VariantObject>())
return v->d()->data;
if (typeHint == QVariant::Bool)
@@ -1210,10 +1173,10 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
if (typeHint == qMetaTypeId<QJSValue>())
return QVariant::fromValue(QJSValue(e, value.asReturnedValue()));
- if (value.asObject()) {
+ if (value.as<Object>()) {
QV4::ScopedObject object(scope, value);
if (typeHint == QMetaType::QJsonObject
- && !value.asArrayObject() && !value.asFunctionObject()) {
+ && !value.as<ArrayObject>() && !value.as<FunctionObject>()) {
return QVariant::fromValue(QV4::JsonObject::toJsonObject(object));
} else if (QV4::QObjectWrapper *wrapper = object->as<QV4::QObjectWrapper>()) {
return qVariantFromValue<QObject *>(wrapper->object());
@@ -1229,7 +1192,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return QV4::SequencePrototype::toVariant(object);
}
- if (value.asArrayObject()) {
+ if (value.as<ArrayObject>()) {
QV4::ScopedArrayObject a(scope, value);
if (typeHint == qMetaTypeId<QList<QObject *> >()) {
QList<QObject *> list;
@@ -1267,11 +1230,11 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return value.asDouble();
if (value.isString())
return value.stringValue()->toQString();
- if (QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>())
+ if (const QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>())
return ld->d()->locale;
- if (QV4::DateObject *d = value.asDateObject())
+ if (const QV4::DateObject *d = value.as<DateObject>())
return d->toQDateTime();
- if (QV4::ArrayBuffer *d = value.as<ArrayBuffer>())
+ if (const QV4::ArrayBuffer *d = value.as<ArrayBuffer>())
return d->asByteArray();
// NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)!
@@ -1287,7 +1250,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return objectToVariant(e, o, visitedObjects);
}
-static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4ObjectSet *visitedObjects)
+static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V4ObjectSet *visitedObjects)
{
Q_ASSERT(o);
@@ -1298,7 +1261,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4Objec
// Avoid recursion.
// For compatibility with QVariant{List,Map} conversion, we return an
// empty object (and no error is thrown).
- if (o->asArrayObject())
+ if (o->as<ArrayObject>())
return QVariantList();
return QVariantMap();
}
@@ -1306,7 +1269,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4Objec
QVariant result;
- if (o->asArrayObject()) {
+ if (o->as<ArrayObject>()) {
QV4::Scope scope(e);
QV4::ScopedArrayObject a(scope, o->asReturnedValue());
QV4::ScopedValue v(scope);
@@ -1319,7 +1282,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4Objec
}
result = list;
- } else if (!o->asFunctionObject()) {
+ } else if (!o->as<FunctionObject>()) {
QVariantMap map;
QV4::Scope scope(e);
QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
@@ -1497,7 +1460,7 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
return QV4::Encode(newVariantObject(variant));
}
-QVariantMap ExecutionEngine::variantMapFromJS(Object *o)
+QVariantMap ExecutionEngine::variantMapFromJS(const Object *o)
{
return objectToVariant(this, o).toMap();
}
@@ -1630,93 +1593,90 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data)
return 0;
}
-void ExecutionEngine::assertObjectBelongsToEngine(const Value &v)
+void ExecutionEngine::assertObjectBelongsToEngine(const Heap::Base &baseObject)
{
- Q_UNUSED(v);
- Q_ASSERT(!v.isObject() || v.objectValue()->engine() == this);
- Q_UNUSED(v);
+ Q_ASSERT(!baseObject.vtable()->isObject || static_cast<const Heap::Object&>(baseObject).internalClass->engine == this);
+ Q_UNUSED(baseObject);
}
// 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 QV4::Value &value, int type, void *data)
+bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
{
- QV4::Scope scope(this);
-
// check if it's one of the types we know
switch (QMetaType::Type(type)) {
case QMetaType::Bool:
- *reinterpret_cast<bool*>(data) = value.toBoolean();
+ *reinterpret_cast<bool*>(data) = value->toBoolean();
return true;
case QMetaType::Int:
- *reinterpret_cast<int*>(data) = value.toInt32();
+ *reinterpret_cast<int*>(data) = value->toInt32();
return true;
case QMetaType::UInt:
- *reinterpret_cast<uint*>(data) = value.toUInt32();
+ *reinterpret_cast<uint*>(data) = value->toUInt32();
return true;
case QMetaType::LongLong:
- *reinterpret_cast<qlonglong*>(data) = qlonglong(value.toInteger());
+ *reinterpret_cast<qlonglong*>(data) = qlonglong(value->toInteger());
return true;
case QMetaType::ULongLong:
- *reinterpret_cast<qulonglong*>(data) = qulonglong(value.toInteger());
+ *reinterpret_cast<qulonglong*>(data) = qulonglong(value->toInteger());
return true;
case QMetaType::Double:
- *reinterpret_cast<double*>(data) = value.toNumber();
+ *reinterpret_cast<double*>(data) = value->toNumber();
return true;
case QMetaType::QString:
- if (value.isUndefined() || value.isNull())
+ if (value->isUndefined() || value->isNull())
*reinterpret_cast<QString*>(data) = QString();
else
- *reinterpret_cast<QString*>(data) = value.toQString();
+ *reinterpret_cast<QString*>(data) = value->toQString();
return true;
case QMetaType::Float:
- *reinterpret_cast<float*>(data) = value.toNumber();
+ *reinterpret_cast<float*>(data) = value->toNumber();
return true;
case QMetaType::Short:
- *reinterpret_cast<short*>(data) = short(value.toInt32());
+ *reinterpret_cast<short*>(data) = short(value->toInt32());
return true;
case QMetaType::UShort:
- *reinterpret_cast<unsigned short*>(data) = value.toUInt16();
+ *reinterpret_cast<unsigned short*>(data) = value->toUInt16();
return true;
case QMetaType::Char:
- *reinterpret_cast<char*>(data) = char(value.toInt32());
+ *reinterpret_cast<char*>(data) = char(value->toInt32());
return true;
case QMetaType::UChar:
- *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value.toInt32());
+ *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value->toInt32());
return true;
case QMetaType::QChar:
- if (value.isString()) {
- QString str = value.stringValue()->toQString();
+ if (value->isString()) {
+ QString str = value->stringValue()->toQString();
*reinterpret_cast<QChar*>(data) = str.isEmpty() ? QChar() : str.at(0);
} else {
- *reinterpret_cast<QChar*>(data) = QChar(ushort(value.toUInt16()));
+ *reinterpret_cast<QChar*>(data) = QChar(ushort(value->toUInt16()));
}
return true;
case QMetaType::QDateTime:
- if (QV4::DateObject *d = value.asDateObject()) {
+ if (const QV4::DateObject *d = value->as<DateObject>()) {
*reinterpret_cast<QDateTime *>(data) = d->toQDateTime();
return true;
} break;
case QMetaType::QDate:
- if (QV4::DateObject *d = value.asDateObject()) {
+ if (const QV4::DateObject *d = value->as<DateObject>()) {
*reinterpret_cast<QDate *>(data) = d->toQDateTime().date();
return true;
} break;
case QMetaType::QRegExp:
- if (QV4::RegExpObject *r = value.as<QV4::RegExpObject>()) {
+ if (const QV4::RegExpObject *r = value->as<QV4::RegExpObject>()) {
*reinterpret_cast<QRegExp *>(data) = r->toQRegExp();
return true;
} break;
case QMetaType::QObjectStar: {
- QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>();
- if (qobjectWrapper || value.isNull()) {
- *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(scope.engine, value);
+ const QV4::QObjectWrapper *qobjectWrapper = value->as<QV4::QObjectWrapper>();
+ if (qobjectWrapper || value->isNull()) {
+ *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(this, *value);
return true;
} break;
}
case QMetaType::QStringList: {
- QV4::ScopedArrayObject a(scope, value);
+ const QV4::ArrayObject *a = value->as<QV4::ArrayObject>();
if (a) {
*reinterpret_cast<QStringList *>(data) = a->toQStringList();
return true;
@@ -1724,15 +1684,15 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
break;
}
case QMetaType::QVariantList: {
- QV4::ScopedArrayObject a(scope, value);
+ const QV4::ArrayObject *a = value->as<QV4::ArrayObject>();
if (a) {
- *reinterpret_cast<QVariantList *>(data) = scope.engine->toVariant(a, /*typeHint*/-1, /*createJSValueForObjects*/false).toList();
+ *reinterpret_cast<QVariantList *>(data) = toVariant(*a, /*typeHint*/-1, /*createJSValueForObjects*/false).toList();
return true;
}
break;
}
case QMetaType::QVariantMap: {
- QV4::ScopedObject o(scope, value);
+ const QV4::Object *o = value->as<QV4::Object>();
if (o) {
*reinterpret_cast<QVariantMap *>(data) = variantMapFromJS(o);
return true;
@@ -1740,20 +1700,19 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
break;
}
case QMetaType::QVariant:
- *reinterpret_cast<QVariant*>(data) = scope.engine->toVariant(value, /*typeHint*/-1, /*createJSValueForObjects*/false);
+ *reinterpret_cast<QVariant*>(data) = toVariant(*value, /*typeHint*/-1, /*createJSValueForObjects*/false);
return true;
case QMetaType::QJsonValue:
- *reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(value);
+ *reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(*value);
return true;
case QMetaType::QJsonObject: {
- QV4::ScopedObject o(scope, value);
- *reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(o);
+ *reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(value->as<Object>());
return true;
}
case QMetaType::QJsonArray: {
- QV4::ScopedArrayObject a(scope, value);
+ const QV4::ArrayObject *a = value->as<ArrayObject>();
if (a) {
- *reinterpret_cast<QJsonArray *>(data) = QV4::JsonObject::toJsonArray(a);
+ *reinterpret_cast<QJsonArray *>(data) = JsonObject::toJsonArray(a);
return true;
}
break;
@@ -1763,7 +1722,7 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
}
{
- QV4::Scoped<QV4::QQmlValueTypeWrapper> vtw(scope, value);
+ const QQmlValueTypeWrapper *vtw = value->as<QQmlValueTypeWrapper>();
if (vtw && vtw->typeId() == type) {
return vtw->toGadget(data);
}
@@ -1788,21 +1747,22 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
}
#endif
- // Try to use magic; for compatibility with qscriptvalue_cast.
+ // Try to use magic; for compatibility with qjsvalue_cast.
QByteArray name = QMetaType::typeName(type);
- if (convertToNativeQObject(this, value, name, reinterpret_cast<void* *>(data)))
+ if (convertToNativeQObject(this, *value, name, reinterpret_cast<void* *>(data)))
return true;
- if (value.as<QV4::VariantObject>() && name.endsWith('*')) {
+ if (value->as<QV4::VariantObject>() && name.endsWith('*')) {
int valueType = QMetaType::type(name.left(name.size()-1));
- QVariant &var = value.as<QV4::VariantObject>()->d()->data;
+ QVariant &var = value->as<QV4::VariantObject>()->d()->data;
if (valueType == var.userType()) {
// We have T t, T* is requested, so return &t.
*reinterpret_cast<void* *>(data) = var.data();
return true;
- } else if (value.isObject()) {
+ } else if (value->isObject()) {
// Look in the prototype chain.
- QV4::ScopedObject proto(scope, value.objectValue()->prototype());
+ QV4::Scope scope(this);
+ QV4::ScopedObject proto(scope, value->objectValue()->prototype());
while (proto) {
bool canCast = false;
if (QV4::VariantObject *vo = proto->as<QV4::VariantObject>()) {
@@ -1812,7 +1772,7 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
else if (proto->as<QV4::QObjectWrapper>()) {
QByteArray className = name.left(name.size()-1);
QV4::ScopedObject p(scope, proto.getPointer());
- if (QObject *qobject = qtObjectFromJS(scope.engine, p))
+ if (QObject *qobject = qtObjectFromJS(this, p))
canCast = qobject->qt_metacast(className) != 0;
}
if (canCast) {
@@ -1826,11 +1786,11 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
proto = proto->prototype();
}
}
- } else if (value.isNull() && name.endsWith('*')) {
+ } else if (value->isNull() && name.endsWith('*')) {
*reinterpret_cast<void* *>(data) = 0;
return true;
} else if (type == qMetaTypeId<QJSValue>()) {
- *reinterpret_cast<QJSValue*>(data) = QJSValue(this, value.asReturnedValue());
+ *reinterpret_cast<QJSValue*>(data) = QJSValue(this, value->asReturnedValue());
return true;
}
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index c0c88abaa5..4640f3f4cc 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -33,10 +33,22 @@
#ifndef QV4ENGINE_H
#define QV4ENGINE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "private/qv4isel_p.h"
#include "qv4managed_p.h"
#include "qv4context_p.h"
+#include "qv4internalclass_p.h"
#include <private/qintrusivelist_p.h>
namespace WTF {
@@ -50,6 +62,7 @@ class QV8Engine;
class QQmlError;
class QJSEngine;
class QQmlEngine;
+class QQmlContextData;
namespace QV4 {
namespace Debugging {
@@ -76,18 +89,16 @@ private:
friend struct Heap::ExecutionContext;
public:
Heap::ExecutionContext *current;
- Heap::ExecutionContext *currentContext() const { return current; }
Value *jsStackTop;
quint32 hasException;
- Heap::GlobalContext *m_rootContext;
- Heap::GlobalContext *rootContext() const { return m_rootContext; }
MemoryManager *memoryManager;
ExecutableAllocator *executableAllocator;
ExecutableAllocator *regExpAllocator;
QScopedPointer<EvalISelFactory> iselFactory;
+ ExecutionContext *currentContext;
Value *jsStackLimit;
quintptr cStackLimit;
@@ -106,14 +117,19 @@ public:
--jsStackTop;
return jsStackTop->heapObject();
}
+ Value *jsAlloca(int nValues) {
+ Value *ptr = jsStackTop;
+ jsStackTop = ptr + nValues;
+ memset(ptr, 0, nValues*sizeof(Value));
+ return ptr;
+ }
IdentifierTable *identifierTable;
QV4::Debugging::Debugger *debugger;
QV4::Profiling::Profiler *profiler;
- Value m_globalObject;
- Object *globalObject() { return reinterpret_cast<Object *>(&m_globalObject); }
+ Object *globalObject;
Function *globalCode;
@@ -121,104 +137,206 @@ public:
QQmlEngine *qmlEngine() const;
QV8Engine *v8Engine;
- Value objectCtor;
- Value stringCtor;
- Value numberCtor;
- Value booleanCtor;
- Value arrayCtor;
- Value functionCtor;
- Value dateCtor;
- Value regExpCtor;
- Value errorCtor;
- Value evalErrorCtor;
- Value rangeErrorCtor;
- Value referenceErrorCtor;
- Value syntaxErrorCtor;
- Value typeErrorCtor;
- Value uRIErrorCtor;
- Value arrayBufferCtor;
- Value dataViewCtor;
- enum { NTypedArrayTypes = 9 }; // avoid header dependency
- Value typedArrayCtors[NTypedArrayTypes];
-
- Value objectPrototype;
- Value arrayPrototype;
- Value stringPrototype;
- Value numberPrototype;
- Value booleanPrototype;
- Value datePrototype;
- Value functionPrototype;
- Value regExpPrototype;
- Value errorPrototype;
- Value evalErrorPrototype;
- Value rangeErrorPrototype;
- Value referenceErrorPrototype;
- Value syntaxErrorPrototype;
- Value typeErrorPrototype;
- Value uRIErrorPrototype;
- Value variantPrototype;
- Value sequencePrototype;
-
- Value arrayBufferPrototype;
- Value dataViewPrototype;
- Value typedArrayPrototype[NTypedArrayTypes]; // TypedArray::NValues, avoid including the header here
+ enum JSObjects {
+ RootContext,
+ IntegerNull, // Has to come after the RootContext to make the context stack safe
+ ObjectProto,
+ ArrayProto,
+ StringProto,
+ NumberProto,
+ BooleanProto,
+ DateProto,
+ FunctionProto,
+ RegExpProto,
+ ErrorProto,
+ EvalErrorProto,
+ RangeErrorProto,
+ ReferenceErrorProto,
+ SyntaxErrorProto,
+ TypeErrorProto,
+ URIErrorProto,
+ VariantProto,
+ SequenceProto,
+ ArrayBufferProto,
+ DataViewProto,
+ ValueTypeProto,
+ SignalHandlerProto,
+
+ Object_Ctor,
+ String_Ctor,
+ Number_Ctor,
+ Boolean_Ctor,
+ Array_Ctor,
+ Function_Ctor,
+ Date_Ctor,
+ RegExp_Ctor,
+ Error_Ctor,
+ EvalError_Ctor,
+ RangeError_Ctor,
+ ReferenceError_Ctor,
+ SyntaxError_Ctor,
+ TypeError_Ctor,
+ URIError_Ctor,
+ ArrayBuffer_Ctor,
+ DataView_Ctor,
+
+ Eval_Function,
+ GetStack_Function,
+ ThrowerObject,
+ NJSObjects
+ };
+ Value *jsObjects;
+ enum { NTypedArrayTypes = 9 }; // == TypedArray::NValues, avoid header dependency
+
+ GlobalContext *rootContext() const { return reinterpret_cast<GlobalContext *>(jsObjects + RootContext); }
+ FunctionObject *objectCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Object_Ctor); }
+ FunctionObject *stringCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + String_Ctor); }
+ FunctionObject *numberCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Number_Ctor); }
+ FunctionObject *booleanCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Boolean_Ctor); }
+ FunctionObject *arrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Array_Ctor); }
+ FunctionObject *functionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Function_Ctor); }
+ FunctionObject *dateCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Date_Ctor); }
+ FunctionObject *regExpCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RegExp_Ctor); }
+ FunctionObject *errorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Error_Ctor); }
+ FunctionObject *evalErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + EvalError_Ctor); }
+ FunctionObject *rangeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RangeError_Ctor); }
+ FunctionObject *referenceErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ReferenceError_Ctor); }
+ FunctionObject *syntaxErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SyntaxError_Ctor); }
+ FunctionObject *typeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + TypeError_Ctor); }
+ FunctionObject *uRIErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + URIError_Ctor); }
+ FunctionObject *arrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ArrayBuffer_Ctor); }
+ FunctionObject *dataViewCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + DataView_Ctor); }
+ FunctionObject *typedArrayCtors;
+
+ Object *objectPrototype() const { return reinterpret_cast<Object *>(jsObjects + ObjectProto); }
+ Object *arrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayProto); }
+ Object *stringPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringProto); }
+ Object *numberPrototype() const { return reinterpret_cast<Object *>(jsObjects + NumberProto); }
+ Object *booleanPrototype() const { return reinterpret_cast<Object *>(jsObjects + BooleanProto); }
+ Object *datePrototype() const { return reinterpret_cast<Object *>(jsObjects + DateProto); }
+ Object *functionPrototype() const { return reinterpret_cast<Object *>(jsObjects + FunctionProto); }
+ Object *regExpPrototype() const { return reinterpret_cast<Object *>(jsObjects + RegExpProto); }
+ Object *errorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ErrorProto); }
+ Object *evalErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + EvalErrorProto); }
+ Object *rangeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + RangeErrorProto); }
+ Object *referenceErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ReferenceErrorProto); }
+ Object *syntaxErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SyntaxErrorProto); }
+ Object *typeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeErrorProto); }
+ Object *uRIErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + URIErrorProto); }
+ Object *variantPrototype() const { return reinterpret_cast<Object *>(jsObjects + VariantProto); }
+ Object *sequencePrototype() const { return reinterpret_cast<Object *>(jsObjects + SequenceProto); }
+
+ Object *arrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayBufferProto); }
+ Object *dataViewPrototype() const { return reinterpret_cast<Object *>(jsObjects + DataViewProto); }
+ Object *typedArrayPrototype;
+
+ Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); }
+ Object *signalHandlerPrototype() const { return reinterpret_cast<Object *>(jsObjects + SignalHandlerProto); }
InternalClassPool *classPool;
InternalClass *emptyClass;
InternalClass *arrayClass;
+ InternalClass *stringClass;
InternalClass *functionClass;
InternalClass *simpleScriptFunctionClass;
InternalClass *protoClass;
InternalClass *regExpExecArrayClass;
+ InternalClass *regExpObjectClass;
InternalClass *argumentsObjectClass;
InternalClass *strictArgumentsObjectClass;
- Heap::EvalFunction *evalFunction;
- Heap::FunctionObject *thrower;
+ InternalClass *errorClass;
+ InternalClass *errorClassWithMessage;
+ InternalClass *errorProtoClass;
+
+ EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); }
+ FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); }
+ FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); }
Property *argumentsAccessors;
int nArgumentsAccessors;
- StringValue id_empty;
- StringValue id_undefined;
- StringValue id_null;
- StringValue id_true;
- StringValue id_false;
- StringValue id_boolean;
- StringValue id_number;
- StringValue id_string;
- StringValue id_object;
- StringValue id_function;
- StringValue id_length;
- StringValue id_prototype;
- StringValue id_constructor;
- StringValue id_arguments;
- StringValue id_caller;
- StringValue id_callee;
- StringValue id_this;
- StringValue id___proto__;
- StringValue id_enumerable;
- StringValue id_configurable;
- StringValue id_writable;
- StringValue id_value;
- StringValue id_get;
- StringValue id_set;
- StringValue id_eval;
- StringValue id_uintMax;
- StringValue id_name;
- StringValue id_index;
- StringValue id_input;
- StringValue id_toString;
- StringValue id_destroy;
- StringValue id_valueOf;
- StringValue id_byteLength;
- StringValue id_byteOffset;
- StringValue id_buffer;
- StringValue id_lastIndex;
+ enum JSStrings {
+ String_Empty,
+ String_undefined,
+ String_null,
+ String_true,
+ String_false,
+ String_boolean,
+ String_number,
+ String_string,
+ String_object,
+ String_function,
+ String_length,
+ String_prototype,
+ String_constructor,
+ String_arguments,
+ String_caller,
+ String_callee,
+ String_this,
+ String___proto__,
+ String_enumerable,
+ String_configurable,
+ String_writable,
+ String_value,
+ String_get,
+ String_set,
+ String_eval,
+ String_uintMax,
+ String_name,
+ String_index,
+ String_input,
+ String_toString,
+ String_destroy,
+ String_valueOf,
+ String_byteLength,
+ String_byteOffset,
+ String_buffer,
+ String_lastIndex,
+ NJSStrings
+ };
+ Value *jsStrings;
+
+ String *id_empty() const { return reinterpret_cast<String *>(jsStrings + String_Empty); }
+ String *id_undefined() const { return reinterpret_cast<String *>(jsStrings + String_undefined); }
+ String *id_null() const { return reinterpret_cast<String *>(jsStrings + String_null); }
+ String *id_true() const { return reinterpret_cast<String *>(jsStrings + String_true); }
+ String *id_false() const { return reinterpret_cast<String *>(jsStrings + String_false); }
+ String *id_boolean() const { return reinterpret_cast<String *>(jsStrings + String_boolean); }
+ String *id_number() const { return reinterpret_cast<String *>(jsStrings + String_number); }
+ String *id_string() const { return reinterpret_cast<String *>(jsStrings + String_string); }
+ String *id_object() const { return reinterpret_cast<String *>(jsStrings + String_object); }
+ String *id_function() const { return reinterpret_cast<String *>(jsStrings + String_function); }
+ String *id_length() const { return reinterpret_cast<String *>(jsStrings + String_length); }
+ String *id_prototype() const { return reinterpret_cast<String *>(jsStrings + String_prototype); }
+ String *id_constructor() const { return reinterpret_cast<String *>(jsStrings + String_constructor); }
+ String *id_arguments() const { return reinterpret_cast<String *>(jsStrings + String_arguments); }
+ String *id_caller() const { return reinterpret_cast<String *>(jsStrings + String_caller); }
+ String *id_callee() const { return reinterpret_cast<String *>(jsStrings + String_callee); }
+ String *id_this() const { return reinterpret_cast<String *>(jsStrings + String_this); }
+ String *id___proto__() const { return reinterpret_cast<String *>(jsStrings + String___proto__); }
+ String *id_enumerable() const { return reinterpret_cast<String *>(jsStrings + String_enumerable); }
+ String *id_configurable() const { return reinterpret_cast<String *>(jsStrings + String_configurable); }
+ String *id_writable() const { return reinterpret_cast<String *>(jsStrings + String_writable); }
+ String *id_value() const { return reinterpret_cast<String *>(jsStrings + String_value); }
+ String *id_get() const { return reinterpret_cast<String *>(jsStrings + String_get); }
+ String *id_set() const { return reinterpret_cast<String *>(jsStrings + String_set); }
+ String *id_eval() const { return reinterpret_cast<String *>(jsStrings + String_eval); }
+ String *id_uintMax() const { return reinterpret_cast<String *>(jsStrings + String_uintMax); }
+ String *id_name() const { return reinterpret_cast<String *>(jsStrings + String_name); }
+ String *id_index() const { return reinterpret_cast<String *>(jsStrings + String_index); }
+ String *id_input() const { return reinterpret_cast<String *>(jsStrings + String_input); }
+ String *id_toString() const { return reinterpret_cast<String *>(jsStrings + String_toString); }
+ String *id_destroy() const { return reinterpret_cast<String *>(jsStrings + String_destroy); }
+ String *id_valueOf() const { return reinterpret_cast<String *>(jsStrings + String_valueOf); }
+ String *id_byteLength() const { return reinterpret_cast<String *>(jsStrings + String_byteLength); }
+ String *id_byteOffset() const { return reinterpret_cast<String *>(jsStrings + String_byteOffset); }
+ String *id_buffer() const { return reinterpret_cast<String *>(jsStrings + String_buffer); }
+ String *id_lastIndex() const { return reinterpret_cast<String *>(jsStrings + String_lastIndex); }
QSet<CompiledData::CompilationUnit*> compilationUnits;
@@ -248,12 +366,14 @@ public:
ExecutionEngine(EvalISelFactory *iselFactory = 0);
~ExecutionEngine();
- void enableDebugger();
+ void setDebugger(Debugging::Debugger *debugger);
void enableProfiler();
- Heap::ExecutionContext *pushGlobalContext();
- void pushContext(CallContext *context);
- Heap::ExecutionContext *popContext();
+ ExecutionContext *pushGlobalContext();
+ void pushContext(Heap::ExecutionContext *context);
+ void pushContext(ExecutionContext *context);
+ void popContext();
+ ExecutionContext *parentContext(ExecutionContext *context) const;
Heap::Object *newObject();
Heap::Object *newObject(InternalClass *internalClass, Object *prototype);
@@ -261,15 +381,17 @@ public:
Heap::String *newString(const QString &s = QString());
Heap::String *newIdentifier(const QString &text);
- Heap::Object *newStringObject(const Value &value);
+ Heap::Object *newStringObject(const String *string);
Heap::Object *newNumberObject(double value);
Heap::Object *newBooleanObject(bool b);
Heap::ArrayObject *newArrayObject(int count = 0);
+ Heap::ArrayObject *newArrayObject(const Value *values, int length);
Heap::ArrayObject *newArrayObject(const QStringList &list);
Heap::ArrayObject *newArrayObject(InternalClass *ic, Object *prototype);
Heap::ArrayBuffer *newArrayBuffer(const QByteArray &array);
+ Heap::ArrayBuffer *newArrayBuffer(size_t length);
Heap::DateObject *newDateObject(const Value &value);
Heap::DateObject *newDateObject(const QDateTime &dt);
@@ -282,7 +404,7 @@ public:
Heap::Object *newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column);
Heap::Object *newSyntaxErrorObject(const QString &message);
Heap::Object *newReferenceErrorObject(const QString &message);
- Heap::Object *newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber, int columnNumber);
+ Heap::Object *newReferenceErrorObject(const QString &message, const QString &fileName, int line, int column);
Heap::Object *newTypeErrorObject(const QString &message);
Heap::Object *newRangeErrorObject(const QString &message);
Heap::Object *newURIErrorObject(const Value &message);
@@ -291,7 +413,11 @@ public:
Heap::Object *newForEachIteratorObject(Object *o);
- Heap::Object *qmlContextObject() const;
+ Heap::QmlContext *qmlContext() const;
+ QObject *qmlScopeObject() const;
+ ReturnedValue qmlSingletonWrapper(String *name);
+ QQmlContextData *callingQmlContext() const;
+
StackTrace stackTrace(int frameLimit = -1) const;
StackFrame currentStackFrame() const;
@@ -305,12 +431,10 @@ public:
InternalClass *newClass(const InternalClass &other);
- QmlExtensions *qmlExtensions();
-
bool recheckCStackLimits();
// Exception handling
- Value exceptionValue;
+ Value *exceptionValue;
StackTrace exceptionStackTrace;
ReturnedValue throwError(const Value &value);
@@ -335,70 +459,62 @@ public:
QVariant toVariant(const QV4::Value &value, int typeHint, bool createJSValueForObjects = true);
QV4::ReturnedValue fromVariant(const QVariant &);
- QVariantMap variantMapFromJS(QV4::Object *o);
+ QVariantMap variantMapFromJS(const QV4::Object *o);
- bool metaTypeFromJS(const Value &value, int type, void *data);
+ bool metaTypeFromJS(const Value *value, int type, void *data);
QV4::ReturnedValue metaTypeToJS(int type, const void *data);
- void assertObjectBelongsToEngine(const Value &v);
-
-private:
- QmlExtensions *m_qmlExtensions;
+ void assertObjectBelongsToEngine(const Heap::Base &baseObject);
};
-inline void ExecutionEngine::pushContext(CallContext *context)
+inline void ExecutionEngine::pushContext(Heap::ExecutionContext *context)
{
- Q_ASSERT(current && context && context->d());
- context->d()->parent = current;
- current = context->d();
+ Q_ASSERT(currentContext && context);
+ Value *v = jsAlloca(2);
+ v[0] = Encode(context);
+ v[1] = Encode((int)(v - static_cast<Value *>(currentContext)));
+ currentContext = static_cast<ExecutionContext *>(v);
+ current = currentContext->d();
}
-inline Heap::ExecutionContext *ExecutionEngine::popContext()
+inline void ExecutionEngine::pushContext(ExecutionContext *context)
{
- Q_ASSERT(current->parent);
- current = current->parent;
- Q_ASSERT(current);
- return current;
+ pushContext(context->d());
}
-inline
-Heap::ExecutionContext::ExecutionContext(ExecutionEngine *engine, ContextType t)
- : engine(engine)
- , parent(engine->currentContext())
- , outer(0)
- , lookups(0)
- , compilationUnit(0)
- , type(t)
- , strictMode(false)
- , lineNumber(-1)
+
+inline void ExecutionEngine::popContext()
{
- engine->current = this;
+ Q_ASSERT(jsStackTop > currentContext);
+ QV4::Value *offset = (currentContext + 1);
+ Q_ASSERT(offset->isInteger());
+ int o = offset->integerValue();
+ Q_ASSERT(o);
+ currentContext -= o;
+ current = currentContext->d();
}
-
-// ### Remove me
inline
-void Managed::mark(QV4::ExecutionEngine *engine)
+void Heap::Base::mark(QV4::ExecutionEngine *engine)
{
Q_ASSERT(inUse());
- if (markBit())
+ if (isMarked())
return;
#ifndef QT_NO_DEBUG
engine->assertObjectBelongsToEngine(*this);
#endif
- d()->setMarkBit();
- engine->pushForGC(d());
+ setMarkBit();
+ engine->pushForGC(this);
}
-
-inline
-void Heap::Base::mark(QV4::ExecutionEngine *engine)
+inline void Value::mark(ExecutionEngine *e)
{
- Q_ASSERT(inUse());
- if (isMarked())
+ if (!isManaged())
return;
- setMarkBit();
- engine->pushForGC(this);
+
+ Heap::Base *o = heapObject();
+ if (o)
+ o->mark(e);
}
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index 9034dee6a0..87b7a88a2b 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -33,11 +33,14 @@
#include "qv4errorobject_p.h"
-#include "qv4mm_p.h"
+#include <QtCore/qnumeric.h>
+#include <QtCore/qmath.h>
#include <QtCore/QDateTime>
#include <QtCore/QStringList>
#include <QtCore/QDebug>
+#include "qv4string_p.h"
+#include <private/qv4mm_p.h>
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
#include <private/qqmljsparser_p.h>
@@ -58,72 +61,49 @@
using namespace QV4;
-Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype)
- : Heap::Object(ic, prototype)
- , stack(Q_NULLPTR)
+Heap::ErrorObject::ErrorObject()
{
- Scope scope(ic->engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::ErrorObject> e(scope, this);
- ScopedString s(scope, scope.engine->newString(QStringLiteral("Error")));
- e->defineDefaultProperty(QStringLiteral("name"), s);
-}
-
-Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const Value &message, ErrorType t)
- : Heap::Object(ic, prototype)
-{
- errorType = t;
+ if (internalClass == scope.engine->errorProtoClass)
+ return;
- Scope scope(ic->engine);
- Scoped<QV4::ErrorObject> e(scope, this);
-
- e->defineAccessorProperty(QStringLiteral("stack"), QV4::ErrorObject::method_get_stack, 0);
-
- if (!message.isUndefined())
- e->defineDefaultProperty(QStringLiteral("message"), message);
- ScopedString s(scope);
- e->defineDefaultProperty(QStringLiteral("name"), (s = scope.engine->newString(e->className())));
-
- e->d()->stackTrace = scope.engine->stackTrace();
- if (!e->d()->stackTrace.isEmpty()) {
- e->defineDefaultProperty(QStringLiteral("fileName"), (s = scope.engine->newString(e->d()->stackTrace.at(0).source)));
- e->defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(e->d()->stackTrace.at(0).line));
- }
+ *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction();
+ *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined();
+ *propertyData(QV4::ErrorObject::Index_FileName) = Encode::undefined();
+ *propertyData(QV4::ErrorObject::Index_LineNumber) = Encode::undefined();
}
-Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, ErrorObject::ErrorType t)
- : Heap::Object(ic, prototype)
+Heap::ErrorObject::ErrorObject(const Value &message, ErrorType t)
{
errorType = t;
- Scope scope(ic->engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::ErrorObject> e(scope, this);
- ScopedString s(scope);
-
- e->defineAccessorProperty(QStringLiteral("stack"), QV4::ErrorObject::method_get_stack, 0);
- ScopedValue v(scope, scope.engine->newString(message));
- e->defineDefaultProperty(QStringLiteral("message"), v);
- e->defineDefaultProperty(QStringLiteral("name"), (s = scope.engine->newString(e->className())));
+ *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction();
+ *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined();
e->d()->stackTrace = scope.engine->stackTrace();
if (!e->d()->stackTrace.isEmpty()) {
- e->defineDefaultProperty(QStringLiteral("fileName"), (s = scope.engine->newString(e->d()->stackTrace.at(0).source)));
- e->defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(e->d()->stackTrace.at(0).line));
+ *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace.at(0).source);
+ *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace.at(0).line);
}
+
+ if (!message.isUndefined())
+ *propertyData(QV4::ErrorObject::Index_Message) = message;
}
-Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t)
- : Heap::Object(ic, prototype)
+Heap::ErrorObject::ErrorObject(const Value &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t)
{
errorType = t;
- Scope scope(ic->engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::ErrorObject> e(scope, this);
- ScopedString s(scope);
- e->defineAccessorProperty(QStringLiteral("stack"), QV4::ErrorObject::method_get_stack, 0);
- e->defineDefaultProperty(QStringLiteral("name"), (s = scope.engine->newString(e->className())));
+ *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction();
+ *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined();
e->d()->stackTrace = scope.engine->stackTrace();
StackFrame frame;
@@ -133,12 +113,33 @@ Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const
e->d()->stackTrace.prepend(frame);
if (!e->d()->stackTrace.isEmpty()) {
- e->defineDefaultProperty(QStringLiteral("fileName"), (s = scope.engine->newString(e->d()->stackTrace.at(0).source)));
- e->defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(e->d()->stackTrace.at(0).line));
+ *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace.at(0).source);
+ *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace.at(0).line);
}
- ScopedValue v(scope, scope.engine->newString(message));
- e->defineDefaultProperty(QStringLiteral("message"), v);
+ if (!message.isUndefined())
+ *propertyData(QV4::ErrorObject::Index_Message) = message;
+}
+
+const char *ErrorObject::className(Heap::ErrorObject::ErrorType t)
+{
+ switch (t) {
+ case Heap::ErrorObject::Error:
+ return "Error";
+ case Heap::ErrorObject::EvalError:
+ return "EvalError";
+ case Heap::ErrorObject::RangeError:
+ return "RangeError";
+ case Heap::ErrorObject::ReferenceError:
+ return "ReferenceError";
+ case Heap::ErrorObject::SyntaxError:
+ return "SyntaxError";
+ case Heap::ErrorObject::TypeError:
+ return "TypeError";
+ case Heap::ErrorObject::URIError:
+ return "URIError";
+ }
+ Q_UNREACHABLE();
}
ReturnedValue ErrorObject::method_get_stack(CallContext *ctx)
@@ -178,58 +179,43 @@ DEFINE_OBJECT_VTABLE(ErrorObject);
DEFINE_OBJECT_VTABLE(SyntaxErrorObject);
-Heap::SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const Value &msg)
- : Heap::ErrorObject(engine->emptyClass, engine->syntaxErrorPrototype.asObject(), msg, SyntaxError)
-{
-}
-
-Heap::SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
- : Heap::ErrorObject(engine->emptyClass, engine->syntaxErrorPrototype.asObject(), msg, fileName, lineNumber, columnNumber, SyntaxError)
-{
-}
-
-Heap::EvalErrorObject::EvalErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->evalErrorPrototype.asObject(), message, EvalError)
-{
-}
-
-Heap::RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype.asObject(), message, RangeError)
+Heap::SyntaxErrorObject::SyntaxErrorObject(const Value &msg)
+ : Heap::ErrorObject(msg, SyntaxError)
{
}
-Heap::RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const QString &message)
- : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype.asObject(), message, RangeError)
+Heap::SyntaxErrorObject::SyntaxErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber)
+ : Heap::ErrorObject(msg, fileName, lineNumber, columnNumber, SyntaxError)
{
}
-Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype.asObject(), message, ReferenceError)
+Heap::EvalErrorObject::EvalErrorObject(const Value &message)
+ : Heap::ErrorObject(message, EvalError)
{
}
-Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &message)
- : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype.asObject(), message, ReferenceError)
+Heap::RangeErrorObject::RangeErrorObject(const Value &message)
+ : Heap::ErrorObject(message, RangeError)
{
}
-Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
- : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype.asObject(), msg, fileName, lineNumber, columnNumber, ReferenceError)
+Heap::ReferenceErrorObject::ReferenceErrorObject(const Value &message)
+ : Heap::ErrorObject(message, ReferenceError)
{
}
-Heap::TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype.asObject(), message, TypeError)
+Heap::ReferenceErrorObject::ReferenceErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber)
+ : Heap::ErrorObject(msg, fileName, lineNumber, columnNumber, ReferenceError)
{
}
-Heap::TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const QString &message)
- : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype.asObject(), message, TypeError)
+Heap::TypeErrorObject::TypeErrorObject(const Value &message)
+ : Heap::ErrorObject(message, TypeError)
{
}
-Heap::URIErrorObject::URIErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->uRIErrorPrototype.asObject(), message, URIError)
+Heap::URIErrorObject::URIErrorObject(const Value &message)
+ : Heap::ErrorObject(message, URIError)
{
}
@@ -251,16 +237,16 @@ Heap::ErrorCtor::ErrorCtor(QV4::ExecutionContext *scope, const QString &name)
{
}
-ReturnedValue ErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<ErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const ErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return Encode(scope.engine->newErrorObject(v));
+ return ErrorObject::create<ErrorObject>(scope.engine, v)->asReturnedValue();
}
-ReturnedValue ErrorCtor::call(Managed *that, CallData *callData)
+ReturnedValue ErrorCtor::call(const Managed *that, CallData *callData)
{
- return static_cast<Object *>(that)->construct(callData);
+ return static_cast<const Object *>(that)->construct(callData);
}
Heap::EvalErrorCtor::EvalErrorCtor(QV4::ExecutionContext *scope)
@@ -268,11 +254,11 @@ Heap::EvalErrorCtor::EvalErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue EvalErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue EvalErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<EvalErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const EvalErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<EvalErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<EvalErrorObject>(scope.engine, v)->asReturnedValue();
}
Heap::RangeErrorCtor::RangeErrorCtor(QV4::ExecutionContext *scope)
@@ -280,11 +266,11 @@ Heap::RangeErrorCtor::RangeErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue RangeErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue RangeErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<RangeErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const RangeErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<RangeErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<RangeErrorObject>(scope.engine, v)->asReturnedValue();
}
Heap::ReferenceErrorCtor::ReferenceErrorCtor(QV4::ExecutionContext *scope)
@@ -292,11 +278,11 @@ Heap::ReferenceErrorCtor::ReferenceErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue ReferenceErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ReferenceErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<ReferenceErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const ReferenceErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<ReferenceErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<ReferenceErrorObject>(scope.engine, v)->asReturnedValue();
}
Heap::SyntaxErrorCtor::SyntaxErrorCtor(QV4::ExecutionContext *scope)
@@ -304,11 +290,11 @@ Heap::SyntaxErrorCtor::SyntaxErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue SyntaxErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue SyntaxErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<SyntaxErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const SyntaxErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<SyntaxErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<SyntaxErrorObject>(scope.engine, v)->asReturnedValue();
}
Heap::TypeErrorCtor::TypeErrorCtor(QV4::ExecutionContext *scope)
@@ -316,11 +302,11 @@ Heap::TypeErrorCtor::TypeErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue TypeErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue TypeErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<TypeErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const TypeErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<TypeErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<TypeErrorObject>(scope.engine, v)->asReturnedValue();
}
Heap::URIErrorCtor::URIErrorCtor(QV4::ExecutionContext *scope)
@@ -328,41 +314,43 @@ Heap::URIErrorCtor::URIErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue URIErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue URIErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<URIErrorCtor *>(m)->engine());
+ Scope scope(static_cast<const URIErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<URIErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<URIErrorObject>(scope.engine, v)->asReturnedValue();
}
-void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj)
+void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj, Heap::ErrorObject::ErrorType t)
{
Scope scope(engine);
ScopedString s(scope);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = obj));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
- obj->defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- obj->defineDefaultProperty(engine->id_toString, method_toString, 0);
- obj->defineDefaultProperty(QStringLiteral("message"), (s = engine->newString()));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = obj));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ *obj->propertyData(Index_Constructor) = ctor;
+ *obj->propertyData(Index_Message) = engine->id_empty();
+ *obj->propertyData(Index_Name) = engine->newString(QString::fromLatin1(ErrorObject::className(t)));
+ if (t == Heap::ErrorObject::Error)
+ obj->defineDefaultProperty(engine->id_toString(), method_toString, 0);
}
ReturnedValue ErrorPrototype::method_toString(CallContext *ctx)
{
Scope scope(ctx);
- Object *o = ctx->thisObject().asObject();
+ Object *o = ctx->thisObject().as<Object>();
if (!o)
return ctx->engine()->throwTypeError();
- ScopedValue name(scope, o->get(ctx->d()->engine->id_name));
+ ScopedValue name(scope, o->get(ctx->d()->engine->id_name()));
QString qname;
if (name->isUndefined())
- qname = QString::fromLatin1("Error");
+ qname = QStringLiteral("Error");
else
qname = name->toQString();
- ScopedString s(scope, ctx->d()->engine->newString(QString::fromLatin1("message")));
+ ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("message")));
ScopedValue message(scope, o->get(s));
QString qmessage;
if (!message->isUndefined())
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index 071f5b8c9a..336050ab2b 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -33,8 +33,20 @@
#ifndef QV4ERROROBJECT_H
#define QV4ERROROBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
+#include "qv4string_p.h"
QT_BEGIN_NAMESPACE
@@ -55,43 +67,39 @@ struct ErrorObject : Object {
URIError
};
- ErrorObject(InternalClass *ic, QV4::Object *prototype);
- ErrorObject(InternalClass *ic, QV4::Object *prototype, const Value &message, ErrorType t = Error);
- ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, ErrorType t = Error);
- ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, const QString &fileName, int line, int column, ErrorType t = Error);
+ ErrorObject();
+ ErrorObject(const Value &message, ErrorType t = Error);
+ ErrorObject(const Value &message, const QString &fileName, int line, int column, ErrorType t = Error);
ErrorType errorType;
StackTrace stackTrace;
- String *stack;
+ Pointer<String> stack;
};
struct EvalErrorObject : ErrorObject {
- EvalErrorObject(ExecutionEngine *engine, const Value &message);
+ EvalErrorObject(const Value &message);
};
struct RangeErrorObject : ErrorObject {
- RangeErrorObject(ExecutionEngine *engine, const Value &message);
- RangeErrorObject(ExecutionEngine *engine, const QString &msg);
+ RangeErrorObject(const Value &message);
};
struct ReferenceErrorObject : ErrorObject {
- ReferenceErrorObject(ExecutionEngine *engine, const Value &message);
- ReferenceErrorObject(ExecutionEngine *engine, const QString &msg);
- ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber);
+ ReferenceErrorObject(const Value &message);
+ ReferenceErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber);
};
struct SyntaxErrorObject : ErrorObject {
- SyntaxErrorObject(ExecutionEngine *engine, const Value &message);
- SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber);
+ SyntaxErrorObject(const Value &message);
+ SyntaxErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber);
};
struct TypeErrorObject : ErrorObject {
- TypeErrorObject(ExecutionEngine *engine, const Value &message);
- TypeErrorObject(ExecutionEngine *engine, const QString &msg);
+ TypeErrorObject(const Value &message);
};
struct URIErrorObject : ErrorObject {
- URIErrorObject(ExecutionEngine *engine, const Value &message);
+ URIErrorObject(const Value &message);
};
struct ErrorCtor : Heap::FunctionObject {
@@ -130,51 +138,75 @@ struct ErrorObject: Object {
IsErrorObject = true
};
+ enum {
+ Index_Stack = 0, // Accessor Property
+ Index_FileName = 2,
+ Index_LineNumber = 3,
+ Index_Message = 4
+ };
+
V4_OBJECT2(ErrorObject, Object)
Q_MANAGED_TYPE(ErrorObject)
+ V4_INTERNALCLASS(errorClass)
+ V4_PROTOTYPE(errorPrototype)
V4_NEEDS_DESTROY
+ template <typename T>
+ static Heap::Object *create(ExecutionEngine *e, const Value &message);
+ template <typename T>
+ static Heap::Object *create(ExecutionEngine *e, const QString &message);
+ template <typename T>
+ static Heap::Object *create(ExecutionEngine *e, const QString &message, const QString &filename, int line, int column);
+
SyntaxErrorObject *asSyntaxError();
+ static const char *className(Heap::ErrorObject::ErrorType t);
+
static ReturnedValue method_get_stack(CallContext *ctx);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
template<>
-inline ErrorObject *value_cast(const Value &v) {
- return v.asErrorObject();
+inline const ErrorObject *Value::as() const {
+ return isManaged() && m() && m()->vtable()->isErrorObject ? reinterpret_cast<const ErrorObject *>(this) : 0;
}
struct EvalErrorObject: ErrorObject {
typedef Heap::EvalErrorObject Data;
+ V4_PROTOTYPE(evalErrorPrototype)
const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
struct RangeErrorObject: ErrorObject {
typedef Heap::RangeErrorObject Data;
+ V4_PROTOTYPE(rangeErrorPrototype)
const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
struct ReferenceErrorObject: ErrorObject {
typedef Heap::ReferenceErrorObject Data;
+ V4_PROTOTYPE(referenceErrorPrototype)
const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
struct SyntaxErrorObject: ErrorObject {
V4_OBJECT2(SyntaxErrorObject, ErrorObject)
+ V4_PROTOTYPE(syntaxErrorPrototype)
};
struct TypeErrorObject: ErrorObject {
typedef Heap::TypeErrorObject Data;
+ V4_PROTOTYPE(typeErrorPrototype)
const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
struct URIErrorObject: ErrorObject {
typedef Heap::URIErrorObject Data;
+ V4_PROTOTYPE(uRIErrorPrototype)
const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
@@ -183,89 +215,94 @@ struct ErrorCtor: FunctionObject
{
V4_OBJECT2(ErrorCtor, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct EvalErrorCtor: ErrorCtor
{
V4_OBJECT2(EvalErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct RangeErrorCtor: ErrorCtor
{
V4_OBJECT2(RangeErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct ReferenceErrorCtor: ErrorCtor
{
V4_OBJECT2(ReferenceErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct SyntaxErrorCtor: ErrorCtor
{
V4_OBJECT2(SyntaxErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct TypeErrorCtor: ErrorCtor
{
V4_OBJECT2(TypeErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct URIErrorCtor: ErrorCtor
{
V4_OBJECT2(URIErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct ErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { init(engine, ctor, this); }
+ enum {
+ Index_Constructor = 0,
+ Index_Message = 1,
+ Index_Name = 2
+ };
+ void init(ExecutionEngine *engine, Object *ctor) { init(engine, ctor, this, Heap::ErrorObject::Error); }
- static void init(ExecutionEngine *engine, Object *ctor, Object *obj);
+ static void init(ExecutionEngine *engine, Object *ctor, Object *obj, Heap::ErrorObject::ErrorType t);
static ReturnedValue method_toString(CallContext *ctx);
};
struct EvalErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::EvalError); }
};
struct RangeErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::RangeError); }
};
struct ReferenceErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::ReferenceError); }
};
struct SyntaxErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::SyntaxError); }
};
struct TypeErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::TypeError); }
};
struct URIErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::URIError); }
};
@@ -274,6 +311,25 @@ inline SyntaxErrorObject *ErrorObject::asSyntaxError()
return d()->errorType == QV4::Heap::ErrorObject::SyntaxError ? static_cast<SyntaxErrorObject *>(this) : 0;
}
+
+template <typename T>
+Heap::Object *ErrorObject::create(ExecutionEngine *e, const Value &message) {
+ return e->memoryManager->allocObject<T>(message.isUndefined() ? e->errorClass : e->errorClassWithMessage, T::defaultPrototype(e), message);
+}
+template <typename T>
+Heap::Object *ErrorObject::create(ExecutionEngine *e, const QString &message) {
+ Scope scope(e);
+ ScopedValue v(scope, message.isEmpty() ? Encode::undefined() : e->newString(message)->asReturnedValue());
+ return e->memoryManager->allocObject<T>(v->isUndefined() ? e->errorClass : e->errorClassWithMessage, T::defaultPrototype(e), v);
+}
+template <typename T>
+Heap::Object *ErrorObject::create(ExecutionEngine *e, const QString &message, const QString &filename, int line, int column) {
+ Scope scope(e);
+ ScopedValue v(scope, message.isEmpty() ? Encode::undefined() : e->newString(message)->asReturnedValue());
+ return e->memoryManager->allocObject<T>(v->isUndefined() ? e->errorClass : e->errorClassWithMessage, T::defaultPrototype(e), v, filename, line, column);
+}
+
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4executableallocator_p.h b/src/qml/jsruntime/qv4executableallocator_p.h
index 0d07e3c1bd..bb63d423a6 100644
--- a/src/qml/jsruntime/qv4executableallocator_p.h
+++ b/src/qml/jsruntime/qv4executableallocator_p.h
@@ -34,6 +34,17 @@
#ifndef QV4EXECUTABLEALLOCATOR_H
#define QV4EXECUTABLEALLOCATOR_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include <QMultiMap>
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index be63b31e1e..66b2125a4f 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -34,10 +34,10 @@
#include "qv4function_p.h"
#include "qv4managed_p.h"
#include "qv4string_p.h"
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#include "qv4engine_p.h"
#include "qv4lookup_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
QT_BEGIN_NAMESPACE
@@ -70,14 +70,45 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit,
arg = mm->alloc<String>(mm, arg->d(), engine->newString(QString(0xfffe)));
}
}
+ nFormals = compiledFunction->nFormals;
const quint32 *localsIndices = compiledFunction->localsTable();
for (quint32 i = 0; i < compiledFunction->nLocals; ++i)
internalClass = internalClass->addMember(compilationUnit->runtimeStrings[localsIndices[i]]->identifier, Attr_NotConfigurable);
+
+ activationRequired = compiledFunction->nInnerFunctions > 0 || (compiledFunction->flags & (CompiledData::Function::HasDirectEval | CompiledData::Function::UsesArgumentsObject));
}
Function::~Function()
{
}
+void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArray> &parameters)
+{
+ internalClass = engine->emptyClass;
+
+ // iterate backwards, so we get the right ordering for duplicate names
+ Scope scope(engine);
+ ScopedString arg(scope);
+ for (int i = parameters.size() - 1; i >= 0; --i) {
+ arg = engine->newString(QString::fromUtf8(parameters.at(i)));
+ while (1) {
+ InternalClass *newClass = internalClass->addMember(arg, Attr_NotConfigurable);
+ if (newClass != internalClass) {
+ internalClass = newClass;
+ break;
+ }
+ // duplicate arguments, need some trick to store them
+ arg = engine->memoryManager->alloc<String>(engine->memoryManager, arg->d(), engine->newString(QString(0xfffe)));
+ }
+ }
+ nFormals = parameters.size();
+
+ const quint32 *localsIndices = compiledFunction->localsTable();
+ for (quint32 i = 0; i < compiledFunction->nLocals; ++i)
+ internalClass = internalClass->addMember(compilationUnit->runtimeStrings[localsIndices[i]]->identifier, Attr_NotConfigurable);
+
+ activationRequired = true;
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index 10a03bca94..0e1216a45b 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -33,6 +33,17 @@
#ifndef QV4FUNCTION_H
#define QV4FUNCTION_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include <private/qv4compileddata_p.h>
@@ -49,11 +60,16 @@ struct Q_QML_EXPORT Function {
// first nArguments names in internalClass are the actual arguments
InternalClass *internalClass;
+ uint nFormals;
+ bool activationRequired;
Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function,
ReturnedValue (*codePtr)(ExecutionEngine *, const uchar *));
~Function();
+ // used when dynamically assigning signal handlers (QQmlConnection)
+ void updateInternalClass(ExecutionEngine *engine, const QList<QByteArray> &parameters);
+
inline Heap::String *name() {
return compilationUnit->runtimeStrings[compiledFunction->nameIndex];
}
@@ -64,7 +80,7 @@ struct Q_QML_EXPORT Function {
inline bool isNamedExpression() const { return compiledFunction->flags & CompiledData::Function::IsNamedExpression; }
inline bool needsActivation() const
- { return compiledFunction->nInnerFunctions > 0 || (compiledFunction->flags & (CompiledData::Function::HasDirectEval | CompiledData::Function::UsesArgumentsObject)); }
+ { return activationRequired; }
};
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 0a12d013ac..1194033872 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -37,7 +37,7 @@
#include "qv4objectproto_p.h"
#include "qv4stringobject_p.h"
#include "qv4function_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4arrayobject_p.h"
#include "qv4scopedvalue_p.h"
@@ -46,7 +46,7 @@
#include <private/qqmljslexer_p.h>
#include <private/qqmljsparser_p.h>
#include <private/qqmljsast_p.h>
-#include <private/qqmlcontextwrapper_p.h>
+#include <private/qqmljavascriptexpression_p.h>
#include <private/qqmlengine_p.h>
#include <qv4codegen_p.h>
#include "private/qlocale_tools_p.h"
@@ -63,8 +63,7 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(FunctionObject);
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *name, bool createProto)
- : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject())
- , scope(scope->d())
+ : scope(scope->d())
, function(Q_NULLPTR)
{
Scope s(scope->engine());
@@ -73,8 +72,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *
}
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *function, bool createProto)
- : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject())
- , scope(scope->d())
+ : scope(scope->d())
, function(Q_NULLPTR)
{
Scope s(scope->engine());
@@ -84,8 +82,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *fun
}
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString &name, bool createProto)
- : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject())
- , scope(scope->d())
+ : scope(scope->d())
, function(Q_NULLPTR)
{
Scope s(scope->engine());
@@ -95,8 +92,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString
}
Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto)
- : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype.asObject())
- , scope(scope)
+ : scope(scope)
, function(Q_NULLPTR)
{
Scope s(scope->engine);
@@ -106,8 +102,7 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &nam
}
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name)
- : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject())
- , scope(scope->d())
+ : scope(scope->d())
, function(Q_NULLPTR)
{
Scope s(scope);
@@ -117,8 +112,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const Returne
}
Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValue name)
- : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype.asObject())
- , scope(scope)
+ : scope(scope)
, function(Q_NULLPTR)
{
Scope s(scope->engine);
@@ -127,15 +121,12 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValu
f->init(n, false);
}
-Heap::FunctionObject::FunctionObject(InternalClass *ic, QV4::Object *prototype)
- : Heap::Object(ic, prototype)
- , scope(ic->engine->rootContext())
+Heap::FunctionObject::FunctionObject()
+ : scope(internalClass->engine->rootContext()->d())
, function(Q_NULLPTR)
{
- Scope scope(ic->engine);
- ScopedObject o(scope, this);
- o->ensureMemberIndex(ic->engine, Index_Prototype);
- memberData->data[Index_Prototype] = Encode::undefined();
+ Q_ASSERT(internalClass && internalClass->find(internalClass->engine->id_prototype()) == Index_Prototype);
+ *propertyData(Index_Prototype) = Encode::undefined();
}
@@ -150,23 +141,23 @@ void FunctionObject::init(String *n, bool createProto)
Scope s(internalClass()->engine);
ScopedValue protectThis(s, this);
- ensureMemberIndex(s.engine, Heap::FunctionObject::Index_Prototype);
+ Q_ASSERT(internalClass() && internalClass()->find(s.engine->id_prototype()) == Heap::FunctionObject::Index_Prototype);
if (createProto) {
- ScopedObject proto(s, scope()->engine->newObject(s.engine->protoClass, s.engine->objectPrototype.asObject()));
- proto->ensureMemberIndex(s.engine, Heap::FunctionObject::Index_ProtoConstructor);
- proto->memberData()->data[Heap::FunctionObject::Index_ProtoConstructor] = this->asReturnedValue();
- memberData()->data[Heap::FunctionObject::Index_Prototype] = proto.asReturnedValue();
+ ScopedObject proto(s, scope()->engine->newObject(s.engine->protoClass, s.engine->objectPrototype()));
+ Q_ASSERT(s.engine->protoClass->find(s.engine->id_constructor()) == Heap::FunctionObject::Index_ProtoConstructor);
+ *proto->propertyData(Heap::FunctionObject::Index_ProtoConstructor) = this->asReturnedValue();
+ *propertyData(Heap::FunctionObject::Index_Prototype) = proto.asReturnedValue();
} else {
- memberData()->data[Heap::FunctionObject::Index_Prototype] = Encode::undefined();
+ *propertyData(Heap::FunctionObject::Index_Prototype) = Encode::undefined();
}
ScopedValue v(s, n);
- defineReadonlyProperty(s.engine->id_name, v);
+ defineReadonlyProperty(s.engine->id_name(), v);
}
-ReturnedValue FunctionObject::name()
+ReturnedValue FunctionObject::name() const
{
- return get(scope()->engine->id_name);
+ return get(scope()->engine->id_name());
}
@@ -177,13 +168,12 @@ ReturnedValue FunctionObject::newInstance()
return construct(callData);
}
-ReturnedValue FunctionObject::construct(Managed *that, CallData *)
+ReturnedValue FunctionObject::construct(const Managed *that, CallData *)
{
- static_cast<FunctionObject *>(that)->internalClass()->engine->throwTypeError();
- return Encode::undefined();
+ return static_cast<const FunctionObject *>(that)->engine()->throwTypeError();
}
-ReturnedValue FunctionObject::call(Managed *, CallData *)
+ReturnedValue FunctionObject::call(const Managed *, CallData *)
{
return Encode::undefined();
}
@@ -203,18 +193,36 @@ Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *sco
function->compiledFunction->flags & CompiledData::Function::HasCatchOrWith ||
function->compiledFunction->nFormals > QV4::Global::ReservedArgumentCount ||
function->isNamedExpression())
- return scope->d()->engine->memoryManager->alloc<ScriptFunction>(scope, function);
- return scope->d()->engine->memoryManager->alloc<SimpleScriptFunction>(scope, function, createProto);
+ return scope->d()->engine->memoryManager->allocObject<ScriptFunction>(scope, function);
+ return scope->d()->engine->memoryManager->allocObject<SimpleScriptFunction>(scope, function, createProto);
+}
+
+Heap::FunctionObject *FunctionObject::createQmlFunction(QQmlContextData *qmlContext, QObject *scopeObject, Function *runtimeFunction, const QList<QByteArray> &signalParameters, QString *error)
+{
+ ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(qmlContext->engine);
+ QV4::Scope valueScope(engine);
+ ExecutionContext *global = valueScope.engine->rootContext();
+ QV4::Scoped<QmlContext> wrapperContext(valueScope, global->newQmlContext(qmlContext, scopeObject));
+
+ if (!signalParameters.isEmpty()) {
+ if (error)
+ QQmlPropertyCache::signalParameterStringForJS(engine, signalParameters, error);
+ runtimeFunction->updateInternalClass(engine, signalParameters);
+ }
+
+ QV4::ScopedFunctionObject function(valueScope, QV4::FunctionObject::createScriptFunction(wrapperContext, runtimeFunction));
+ return function->d();
}
+
bool FunctionObject::isBinding() const
{
- return d()->vtable == QQmlBindingFunction::staticVTable();
+ return d()->vtable() == QQmlBindingFunction::staticVTable();
}
bool FunctionObject::isBoundFunction() const
{
- return d()->vtable == BoundFunction::staticVTable();
+ return d()->vtable() == BoundFunction::staticVTable();
}
QQmlSourceLocation FunctionObject::sourceLocation() const
@@ -237,11 +245,11 @@ Heap::FunctionCtor::FunctionCtor(QV4::ExecutionContext *scope)
}
// 15.3.2
-ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData)
+ReturnedValue FunctionCtor::construct(const Managed *that, CallData *callData)
{
- Scope scope(static_cast<Object *>(that)->engine());
- Scoped<FunctionCtor> f(scope, static_cast<FunctionCtor *>(that));
- ScopedContext ctx(scope, scope.engine->currentContext());
+ Scope scope(static_cast<const Object *>(that)->engine());
+ Scoped<FunctionCtor> f(scope, static_cast<const FunctionCtor *>(that));
+
QString arguments;
QString body;
if (callData->argc > 0) {
@@ -252,10 +260,10 @@ ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData)
}
body = callData->args[callData->argc - 1].toQString();
}
- if (ctx->d()->engine->hasException)
+ if (scope.engine->hasException)
return Encode::undefined();
- QString function = QLatin1String("function(") + arguments + QLatin1String("){") + body + QLatin1String("}");
+ QString function = QLatin1String("function(") + arguments + QLatin1String("){") + body + QLatin1Char('}');
QQmlJS::Engine ee, *engine = &ee;
QQmlJS::Lexer lexer(engine);
@@ -282,20 +290,19 @@ ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData)
QQmlRefPointer<CompiledData::CompilationUnit> compilationUnit = isel->compile();
Function *vmf = compilationUnit->linkToEngine(scope.engine);
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = scope.engine->rootContext();
return FunctionObject::createScriptFunction(global, vmf)->asReturnedValue();
}
// 15.3.1: This is equivalent to new Function(...)
-ReturnedValue FunctionCtor::call(Managed *that, CallData *callData)
+ReturnedValue FunctionCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
DEFINE_OBJECT_VTABLE(FunctionPrototype);
-Heap::FunctionPrototype::FunctionPrototype(InternalClass *ic, QV4::Object *prototype)
- : Heap::FunctionObject(ic, prototype)
+Heap::FunctionPrototype::FunctionPrototype()
{
}
@@ -304,12 +311,12 @@ void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor)
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
- defineReadonlyProperty(engine->id_length, Primitive::fromInt32(0));
+ defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(0));
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString, 0);
+ defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("apply"), method_apply, 2);
defineDefaultProperty(QStringLiteral("call"), method_call, 1);
defineDefaultProperty(QStringLiteral("bind"), method_bind, 1);
@@ -318,7 +325,7 @@ void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor)
ReturnedValue FunctionPrototype::method_toString(CallContext *ctx)
{
- FunctionObject *fun = ctx->thisObject().asFunctionObject();
+ FunctionObject *fun = ctx->thisObject().as<FunctionObject>();
if (!fun)
return ctx->engine()->throwTypeError();
@@ -328,7 +335,7 @@ ReturnedValue FunctionPrototype::method_toString(CallContext *ctx)
ReturnedValue FunctionPrototype::method_apply(CallContext *ctx)
{
Scope scope(ctx);
- ScopedFunctionObject o(scope, ctx->thisObject().asFunctionObject());
+ ScopedFunctionObject o(scope, ctx->thisObject().as<FunctionObject>());
if (!o)
return ctx->engine()->throwTypeError();
@@ -370,7 +377,7 @@ ReturnedValue FunctionPrototype::method_call(CallContext *ctx)
{
Scope scope(ctx);
- ScopedFunctionObject o(scope, ctx->thisObject().asFunctionObject());
+ ScopedFunctionObject o(scope, ctx->thisObject().as<FunctionObject>());
if (!o)
return ctx->engine()->throwTypeError();
@@ -393,12 +400,12 @@ ReturnedValue FunctionPrototype::method_bind(CallContext *ctx)
ScopedValue boundThis(scope, ctx->argument(0));
Scoped<MemberData> boundArgs(scope, (Heap::MemberData *)0);
if (ctx->argc() > 1) {
- boundArgs = MemberData::reallocate(scope.engine, 0, ctx->argc() - 1);
+ boundArgs = MemberData::allocate(scope.engine, ctx->argc() - 1);
boundArgs->d()->size = ctx->argc() - 1;
memcpy(boundArgs->data(), ctx->args() + 1, (ctx->argc() - 1)*sizeof(Value));
}
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = scope.engine->rootContext();
return BoundFunction::create(global, target, boundThis, boundArgs)->asReturnedValue();
}
@@ -409,29 +416,30 @@ Heap::ScriptFunction::ScriptFunction(QV4::ExecutionContext *scope, Function *fun
{
}
-ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
+ReturnedValue ScriptFunction::construct(const Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(that)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<ScriptFunction> f(scope, static_cast<ScriptFunction *>(that));
+ ExecutionContextSaver ctxSaver(scope);
+
+ Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that));
InternalClass *ic = scope.engine->emptyClass;
ScopedObject proto(scope, f->protoForConstructor());
ScopedObject obj(scope, v4->newObject(ic, proto));
- ScopedContext context(scope, v4->currentContext());
callData->thisObject = obj.asReturnedValue();
- Scoped<CallContext> ctx(scope, context->newCallContext(f, callData));
+ Scoped<CallContext> ctx(scope, v4->currentContext->newCallContext(f, callData));
+ v4->pushContext(ctx);
- ExecutionContextSaver ctxSaver(scope, context);
ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
- QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
+ QQmlPropertyCapture::registerQmlDependencies(v4, f->function()->compiledFunction);
if (v4->hasException)
return Encode::undefined();
@@ -441,24 +449,24 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
return obj.asReturnedValue();
}
-ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
+ReturnedValue ScriptFunction::call(const Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(that)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<ScriptFunction> f(scope, static_cast<ScriptFunction *>(that));
- ScopedContext context(scope, v4->currentContext());
+ ExecutionContextSaver ctxSaver(scope);
- Scoped<CallContext> ctx(scope, context->newCallContext(f, callData));
+ Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that));
+ Scoped<CallContext> ctx(scope, v4->currentContext->newCallContext(f, callData));
+ v4->pushContext(ctx);
- ExecutionContextSaver ctxSaver(scope, context);
ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
- QmlContextWrapper::registerQmlDependencies(ctx->d()->engine, f->function()->compiledFunction);
+ QQmlPropertyCapture::registerQmlDependencies(scope.engine, f->function()->compiledFunction);
return result->asReturnedValue();
}
@@ -466,7 +474,6 @@ ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
DEFINE_OBJECT_VTABLE(SimpleScriptFunction);
Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto)
- : Heap::FunctionObject(function->compilationUnit->engine->simpleScriptFunctionClass, function->compilationUnit->engine->functionPrototype.asObject())
{
this->scope = scope->d();
@@ -481,40 +488,42 @@ Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, F
if (createProto) {
ScopedString name(s, function->name());
f->init(name, createProto);
- f->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(f->formalParameterCount()));
+ f->defineReadonlyProperty(scope->d()->engine->id_length(), Primitive::fromInt32(f->formalParameterCount()));
} else {
- f->ensureMemberIndex(s.engine, Index_Length);
- memberData->data[Index_Name] = function->name();
- memberData->data[Index_Length] = Primitive::fromInt32(f->formalParameterCount());
+ Q_ASSERT(internalClass && internalClass->find(s.engine->id_length()) == Index_Length);
+ Q_ASSERT(internalClass && internalClass->find(s.engine->id_name()) == Index_Name);
+ *propertyData(Index_Name) = function->name();
+ *propertyData(Index_Length) = Primitive::fromInt32(f->formalParameterCount());
}
if (scope->d()->strictMode) {
ScopedProperty pd(s);
- pd->value = s.engine->thrower;
- pd->set = s.engine->thrower;
- f->insertMember(scope->d()->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- f->insertMember(scope->d()->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ pd->value = s.engine->thrower();
+ pd->set = s.engine->thrower();
+ f->insertMember(scope->d()->engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ f->insertMember(scope->d()->engine->id_arguments(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
}
}
-ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
+ReturnedValue SimpleScriptFunction::construct(const Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(that)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(that));
+ ExecutionContextSaver ctxSaver(scope);
+
+ Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that));
InternalClass *ic = scope.engine->emptyClass;
ScopedObject proto(scope, f->protoForConstructor());
callData->thisObject = v4->newObject(ic, proto);
- ExecutionContextSaver ctxSaver(scope, v4->currentContext());
-
CallContext::Data ctx(v4);
- ctx.vtable = CallContext::staticVTable();
+ ctx.mm_data = 0;
+ ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->strictMode();
ctx.callData = callData;
ctx.function = f->d();
@@ -524,32 +533,34 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
ctx.locals = scope.alloc(f->varCount());
for (int i = callData->argc; i < (int)f->formalParameterCount(); ++i)
callData->args[i] = Encode::undefined();
- Q_ASSERT(v4->currentContext() == &ctx);
+ v4->pushContext(&ctx);
+ Q_ASSERT(v4->current == &ctx);
ScopedObject result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
- QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
+ QQmlPropertyCapture::registerQmlDependencies(v4, f->function()->compiledFunction);
if (!result)
return callData->thisObject.asReturnedValue();
return result.asReturnedValue();
}
-ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
+ReturnedValue SimpleScriptFunction::call(const Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<SimpleScriptFunction *>(that)->internalClass()->engine;
+ ExecutionEngine *v4 = static_cast<const SimpleScriptFunction *>(that)->internalClass()->engine;
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(that));
+ ExecutionContextSaver ctxSaver(scope);
- ExecutionContextSaver ctxSaver(scope, v4->currentContext());
+ Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that));
CallContext::Data ctx(v4);
- ctx.vtable = CallContext::staticVTable();
+ ctx.mm_data = 0;
+ ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->strictMode();
ctx.callData = callData;
ctx.function = f->d();
@@ -559,12 +570,13 @@ ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
ctx.locals = scope.alloc(f->varCount());
for (int i = callData->argc; i < (int)f->formalParameterCount(); ++i)
callData->args[i] = Encode::undefined();
- Q_ASSERT(v4->currentContext() == &ctx);
+ v4->pushContext(&ctx);
+ Q_ASSERT(v4->current == &ctx);
ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
- QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
+ QQmlPropertyCapture::registerQmlDependencies(v4, f->function()->compiledFunction);
return result->asReturnedValue();
}
@@ -575,7 +587,7 @@ Heap::Object *SimpleScriptFunction::protoForConstructor()
ScopedObject p(scope, protoProperty());
if (p)
return p->d();
- return scope.engine->objectPrototype.asObject()->d();
+ return scope.engine->objectPrototype()->d();
}
@@ -588,51 +600,53 @@ Heap::BuiltinFunction::BuiltinFunction(QV4::ExecutionContext *scope, QV4::String
{
}
-ReturnedValue BuiltinFunction::construct(Managed *f, CallData *)
+ReturnedValue BuiltinFunction::construct(const Managed *f, CallData *)
{
- return static_cast<BuiltinFunction *>(f)->internalClass()->engine->throwTypeError();
+ return static_cast<const BuiltinFunction *>(f)->internalClass()->engine->throwTypeError();
}
-ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
+ReturnedValue BuiltinFunction::call(const Managed *that, CallData *callData)
{
- BuiltinFunction *f = static_cast<BuiltinFunction *>(that);
+ const BuiltinFunction *f = static_cast<const BuiltinFunction *>(that);
ExecutionEngine *v4 = f->internalClass()->engine;
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- ExecutionContextSaver ctxSaver(scope, v4->currentContext());
+ ExecutionContextSaver ctxSaver(scope);
CallContext::Data ctx(v4);
- ctx.vtable = CallContext::staticVTable();
+ ctx.mm_data = 0;
+ ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
ctx.callData = callData;
- Q_ASSERT(v4->currentContext() == &ctx);
- Scoped<CallContext> sctx(scope, &ctx);
+ v4->pushContext(&ctx);
+ Q_ASSERT(v4->current == &ctx);
- return f->d()->code(sctx);
+ return f->d()->code(static_cast<QV4::CallContext *>(v4->currentContext));
}
-ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData)
+ReturnedValue IndexedBuiltinFunction::call(const Managed *that, CallData *callData)
{
- IndexedBuiltinFunction *f = static_cast<IndexedBuiltinFunction *>(that);
+ const IndexedBuiltinFunction *f = static_cast<const IndexedBuiltinFunction *>(that);
ExecutionEngine *v4 = f->internalClass()->engine;
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- ExecutionContextSaver ctxSaver(scope, v4->currentContext());
+ ExecutionContextSaver ctxSaver(scope);
CallContext::Data ctx(v4);
- ctx.vtable = CallContext::staticVTable();
+ ctx.mm_data = 0;
+ ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
ctx.callData = callData;
- Q_ASSERT(v4->currentContext() == &ctx);
- Scoped<CallContext> sctx(scope, &ctx);
+ v4->pushContext(&ctx);
+ Q_ASSERT(v4->current == &ctx);
- return f->d()->code(sctx, f->d()->index);
+ return f->d()->code(static_cast<QV4::CallContext *>(v4->currentContext), f->d()->index);
}
DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction);
@@ -650,24 +664,24 @@ Heap::BoundFunction::BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionOb
Scope s(scope);
ScopedObject f(s, this);
- ScopedValue l(s, target->get(s.engine->id_length));
+ ScopedValue l(s, target->get(s.engine->id_length()));
int len = l->toUInt32();
if (boundArgs)
len -= boundArgs->size();
if (len < 0)
len = 0;
- f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(len));
+ f->defineReadonlyProperty(s.engine->id_length(), Primitive::fromInt32(len));
ScopedProperty pd(s);
- pd->value = s.engine->thrower;
- pd->set = s.engine->thrower;
- f->insertMember(s.engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- f->insertMember(s.engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ pd->value = s.engine->thrower();
+ pd->set = s.engine->thrower();
+ f->insertMember(s.engine->id_arguments(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ f->insertMember(s.engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
}
-ReturnedValue BoundFunction::call(Managed *that, CallData *dd)
+ReturnedValue BoundFunction::call(const Managed *that, CallData *dd)
{
- BoundFunction *f = static_cast<BoundFunction *>(that);
+ const BoundFunction *f = static_cast<const BoundFunction *>(that);
Scope scope(f->engine());
if (scope.hasException())
return Encode::undefined();
@@ -685,9 +699,9 @@ ReturnedValue BoundFunction::call(Managed *that, CallData *dd)
return t->call(callData);
}
-ReturnedValue BoundFunction::construct(Managed *that, CallData *dd)
+ReturnedValue BoundFunction::construct(const Managed *that, CallData *dd)
{
- BoundFunction *f = static_cast<BoundFunction *>(that);
+ const BoundFunction *f = static_cast<const BoundFunction *>(that);
Scope scope(f->engine());
if (scope.hasException())
return Encode::undefined();
@@ -707,7 +721,8 @@ ReturnedValue BoundFunction::construct(Managed *that, CallData *dd)
void BoundFunction::markObjects(Heap::Base *that, ExecutionEngine *e)
{
BoundFunction::Data *o = static_cast<BoundFunction::Data *>(that);
- o->target->mark(e);
+ if (o->target)
+ o->target->mark(e);
o->boundThis.mark(e);
if (o->boundArgs)
o->boundArgs->mark(e);
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 252ff40a1a..896bd2a4d2 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -33,10 +33,21 @@
#ifndef QV4FUNCTIONOBJECT_H
#define QV4FUNCTIONOBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4function_p.h"
#include "qv4context_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
QT_BEGIN_NAMESPACE
@@ -58,14 +69,14 @@ struct Q_QML_PRIVATE_EXPORT FunctionObject : Object {
FunctionObject(ExecutionContext *scope, const QString &name = QString(), bool createProto = false);
FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name);
FunctionObject(ExecutionContext *scope, const ReturnedValue name);
- FunctionObject(InternalClass *ic, QV4::Object *prototype);
+ FunctionObject();
~FunctionObject();
- unsigned int formalParameterCount() { return function ? function->compiledFunction->nFormals : 0; }
+ unsigned int formalParameterCount() { return function ? function->nFormals : 0; }
unsigned int varCount() { return function ? function->compiledFunction->nLocals : 0; }
bool needsActivation() const { return function ? function->needsActivation() : false; }
- ExecutionContext *scope;
+ Pointer<ExecutionContext> scope;
Function *function;
};
@@ -74,7 +85,7 @@ struct FunctionCtor : FunctionObject {
};
struct FunctionPrototype : FunctionObject {
- FunctionPrototype(InternalClass *ic, QV4::Object *prototype);
+ FunctionPrototype();
};
struct Q_QML_EXPORT BuiltinFunction : FunctionObject {
@@ -102,9 +113,9 @@ struct ScriptFunction : SimpleScriptFunction {
struct BoundFunction : FunctionObject {
BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs);
- FunctionObject *target;
+ Pointer<FunctionObject> target;
Value boundThis;
- MemberData *boundArgs;
+ Pointer<MemberData> boundArgs;
};
}
@@ -115,14 +126,16 @@ struct Q_QML_EXPORT FunctionObject: Object {
};
V4_OBJECT2(FunctionObject, Object)
Q_MANAGED_TYPE(FunctionObject)
+ V4_INTERNALCLASS(functionClass)
+ V4_PROTOTYPE(functionPrototype)
V4_NEEDS_DESTROY
- Heap::ExecutionContext *scope() { return d()->scope; }
- Function *function() { return d()->function; }
+ Heap::ExecutionContext *scope() const { return d()->scope; }
+ Function *function() const { return d()->function; }
- ReturnedValue name();
- unsigned int formalParameterCount() { return d()->formalParameterCount(); }
- unsigned int varCount() { return d()->varCount(); }
+ ReturnedValue name() const;
+ unsigned int formalParameterCount() const { return d()->formalParameterCount(); }
+ unsigned int varCount() const { return d()->varCount(); }
void init(String *name, bool createProto);
@@ -130,16 +143,14 @@ struct Q_QML_EXPORT FunctionObject: Object {
using Object::construct;
using Object::call;
- static ReturnedValue construct(Managed *that, CallData *);
- static ReturnedValue call(Managed *that, CallData *d);
-
- static FunctionObject *cast(const Value &v) {
- return v.asFunctionObject();
- }
+ static ReturnedValue construct(const Managed *that, CallData *);
+ static ReturnedValue call(const Managed *that, CallData *d);
static Heap::FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true);
+ static Heap::FunctionObject *createQmlFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction,
+ const QList<QByteArray> &signalParameters = QList<QByteArray>(), QString *error = 0);
- ReturnedValue protoProperty() { return memberData()->data[Heap::FunctionObject::Index_Prototype].asReturnedValue(); }
+ ReturnedValue protoProperty() { return propertyData(Heap::FunctionObject::Index_Prototype)->asReturnedValue(); }
bool needsActivation() const { return d()->needsActivation(); }
bool strictMode() const { return d()->function ? d()->function->isStrict() : false; }
@@ -152,16 +163,17 @@ struct Q_QML_EXPORT FunctionObject: Object {
};
template<>
-inline FunctionObject *value_cast(const Value &v) {
- return v.asFunctionObject();
+inline const FunctionObject *Value::as() const {
+ return isManaged() && m() && m()->vtable()->isFunctionObject ? reinterpret_cast<const FunctionObject *>(this) : 0;
}
+
struct FunctionCtor: FunctionObject
{
V4_OBJECT2(FunctionCtor, FunctionObject)
- static ReturnedValue construct(Managed *that, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct FunctionPrototype: FunctionObject
@@ -181,23 +193,23 @@ struct Q_QML_EXPORT BuiltinFunction: FunctionObject {
static Heap::BuiltinFunction *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *))
{
- return scope->engine()->memoryManager->alloc<BuiltinFunction>(scope, name, code);
+ return scope->engine()->memoryManager->allocObject<BuiltinFunction>(scope, name, code);
}
- static ReturnedValue construct(Managed *, CallData *);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct IndexedBuiltinFunction: FunctionObject
{
V4_OBJECT2(IndexedBuiltinFunction, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *)
+ static ReturnedValue construct(const Managed *m, CallData *)
{
- return static_cast<IndexedBuiltinFunction *>(m)->engine()->throwTypeError();
+ return static_cast<const IndexedBuiltinFunction *>(m)->engine()->throwTypeError();
}
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
Heap::IndexedBuiltinFunction::IndexedBuiltinFunction(QV4::ExecutionContext *scope, uint index,
@@ -211,9 +223,10 @@ Heap::IndexedBuiltinFunction::IndexedBuiltinFunction(QV4::ExecutionContext *scop
struct SimpleScriptFunction: FunctionObject {
V4_OBJECT2(SimpleScriptFunction, FunctionObject)
+ V4_INTERNALCLASS(simpleScriptFunctionClass)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
Heap::Object *protoForConstructor();
};
@@ -221,8 +234,8 @@ struct SimpleScriptFunction: FunctionObject {
struct ScriptFunction: SimpleScriptFunction {
V4_OBJECT2(ScriptFunction, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
@@ -231,15 +244,15 @@ struct BoundFunction: FunctionObject {
static Heap::BoundFunction *create(ExecutionContext *scope, FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs)
{
- return scope->engine()->memoryManager->alloc<BoundFunction>(scope, target, boundThis, boundArgs);
+ return scope->engine()->memoryManager->allocObject<BoundFunction>(scope, target, boundThis, boundArgs);
}
- Heap::FunctionObject *target() { return d()->target; }
+ Heap::FunctionObject *target() const { return d()->target; }
Value boundThis() const { return d()->boundThis; }
Heap::MemberData *boundArgs() const { return d()->boundArgs; }
- static ReturnedValue construct(Managed *, CallData *d);
- static ReturnedValue call(Managed *that, CallData *dd);
+ static ReturnedValue construct(const Managed *, CallData *d);
+ static ReturnedValue call(const Managed *that, CallData *dd);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index 4b08194b60..01a21ea06d 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -34,6 +34,17 @@
#ifndef QV4GLOBAL_H
#define QV4GLOBAL_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#if defined(QT_BUILD_QMLDEVTOOLS_LIB) || defined(QT_QMLDEVTOOLS_LIB)
#define V4_BOOTSTRAP
#endif
@@ -88,6 +99,8 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); }
#define V4_ENABLE_JIT
#endif
+#elif defined(Q_PROCESSOR_MIPS_32) && defined(Q_OS_LINUX)
+#define V4_ENABLE_JIT
#endif
// Black list some platforms
@@ -168,7 +181,7 @@ struct Property;
struct Value;
struct Lookup;
struct ArrayData;
-struct ManagedVTable;
+struct VTable;
struct BooleanObject;
struct NumberObject;
@@ -211,7 +224,6 @@ class WeakValue;
struct IdentifierTable;
class RegExpCache;
class MultiplyWrappedQObjectMap;
-struct QmlExtensions;
namespace Global {
enum {
@@ -277,8 +289,6 @@ struct PropertyAttributes
setConfigurable(!(f & Attr_NotConfigurable));
}
}
- PropertyAttributes(const PropertyAttributes &other) : m_all(other.m_all) {}
- PropertyAttributes & operator=(const PropertyAttributes &other) { m_all = other.m_all; return *this; }
void setType(Type t) { m_type = t; type_set = true; }
Type type() const { return type_set ? (Type)m_type : Generic; }
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index 8e33cec57f..110a2c9089 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -32,13 +32,15 @@
****************************************************************************/
#include "qv4globalobject_p.h"
-#include "qv4mm_p.h"
-#include "qv4value_inl_p.h"
+#include <private/qv4mm_p.h>
+#include "qv4value_p.h"
#include "qv4context_p.h"
#include "qv4function_p.h"
#include "qv4debugging_p.h"
+#include "qv4profiling_p.h"
#include "qv4script_p.h"
#include "qv4scopedvalue_p.h"
+#include "qv4string_p.h"
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
@@ -47,6 +49,7 @@
#include <qv4jsir_p.h>
#include <qv4codegen_p.h>
#include "private/qlocale_tools_p.h"
+#include "private/qtools_p.h"
#include <QtCore/QDebug>
#include <QtCore/QString>
@@ -56,25 +59,8 @@
#include <wtf/MathExtras.h>
using namespace QV4;
-
-
-static inline char toHex(char c)
-{
- static const char hexnumbers[] = "0123456789ABCDEF";
- return hexnumbers[c & 0xf];
-}
-
-static int fromHex(QChar ch)
-{
- ushort c = ch.unicode();
- if ((c >= '0') && (c <= '9'))
- return c - '0';
- if ((c >= 'A') && (c <= 'F'))
- return c - 'A' + 10;
- if ((c >= 'a') && (c <= 'f'))
- return c - 'a' + 10;
- return -1;
-}
+using QtMiscUtils::toHexUpper;
+using QtMiscUtils::fromHex;
static QString escape(const QString &input)
{
@@ -93,16 +79,16 @@ static QString escape(const QString &input)
output.append(QChar(uc));
} else {
output.append('%');
- output.append(QLatin1Char(toHex(uc >> 4)));
- output.append(QLatin1Char(toHex(uc)));
+ output.append(QLatin1Char(toHexUpper(uc >> 4)));
+ output.append(QLatin1Char(toHexUpper(uc)));
}
} else {
output.append('%');
output.append('u');
- output.append(QLatin1Char(toHex(uc >> 12)));
- output.append(QLatin1Char(toHex(uc >> 8)));
- output.append(QLatin1Char(toHex(uc >> 4)));
- output.append(QLatin1Char(toHex(uc)));
+ output.append(QLatin1Char(toHexUpper(uc >> 12)));
+ output.append(QLatin1Char(toHexUpper(uc >> 8)));
+ output.append(QLatin1Char(toHexUpper(uc >> 4)));
+ output.append(QLatin1Char(toHexUpper(uc)));
}
}
return output;
@@ -119,10 +105,10 @@ static QString unescape(const QString &input)
if ((c == '%') && (i + 1 < length)) {
QChar a = input.at(i);
if ((a == 'u') && (i + 4 < length)) {
- int d3 = fromHex(input.at(i+1));
- int d2 = fromHex(input.at(i+2));
- int d1 = fromHex(input.at(i+3));
- int d0 = fromHex(input.at(i+4));
+ int d3 = fromHex(input.at(i+1).unicode());
+ int d2 = fromHex(input.at(i+2).unicode());
+ int d1 = fromHex(input.at(i+3).unicode());
+ int d0 = fromHex(input.at(i+4).unicode());
if ((d3 != -1) && (d2 != -1) && (d1 != -1) && (d0 != -1)) {
ushort uc = ushort((d3 << 12) | (d2 << 8) | (d1 << 4) | d0);
result.append(QChar(uc));
@@ -131,8 +117,8 @@ static QString unescape(const QString &input)
result.append(c);
}
} else {
- int d1 = fromHex(a);
- int d0 = fromHex(input.at(i+1));
+ int d1 = fromHex(a.unicode());
+ int d0 = fromHex(input.at(i+1).unicode());
if ((d1 != -1) && (d0 != -1)) {
c = (d1 << 4) | d0;
i += 2;
@@ -153,8 +139,8 @@ static const char uriUnescapedReserved[] = "-_.!~*'();/?:@&=+$,#";
static void addEscapeSequence(QString &output, uchar ch)
{
output.append(QLatin1Char('%'));
- output.append(QLatin1Char(toHex(ch >> 4)));
- output.append(QLatin1Char(toHex(ch & 0xf)));
+ output.append(QLatin1Char(toHexUpper(ch >> 4)));
+ output.append(QLatin1Char(toHexUpper(ch & 0xf)));
}
static QString encode(const QString &input, const char *unescapedSet, bool *ok)
@@ -246,8 +232,8 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok)
if (i + 2 >= length)
goto error;
- int d1 = fromHex(input.at(i+1));
- int d0 = fromHex(input.at(i+2));
+ int d1 = fromHex(input.at(i+1).unicode());
+ int d0 = fromHex(input.at(i+2).unicode());
if ((d1 == -1) || (d0 == -1))
goto error;
@@ -281,8 +267,8 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok)
if (input.at(i) != percent)
goto error;
- d1 = fromHex(input.at(i+1));
- d0 = fromHex(input.at(i+2));
+ d1 = fromHex(input.at(i+1).unicode());
+ d0 = fromHex(input.at(i+2).unicode());
if ((d1 == -1) || (d0 == -1))
goto error;
@@ -339,25 +325,24 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok)
DEFINE_OBJECT_VTABLE(EvalFunction);
Heap::EvalFunction::EvalFunction(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope, scope->d()->engine->id_eval)
+ : Heap::FunctionObject(scope, scope->d()->engine->id_eval())
{
Scope s(scope);
ScopedFunctionObject f(s, this);
- f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(1));
+ f->defineReadonlyProperty(s.engine->id_length(), Primitive::fromInt32(1));
}
-ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
+ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const
{
if (callData->argc < 1)
return Encode::undefined();
ExecutionEngine *v4 = engine();
Scope scope(v4);
+ ExecutionContextSaver ctxSaver(scope);
- ScopedContext parentContext(scope, v4->currentContext());
- ExecutionContextSaver ctxSaver(scope, parentContext);
-
- ScopedContext ctx(scope, parentContext.getPointer());
+ ExecutionContext *currentContext = v4->currentContext;
+ ExecutionContext *ctx = currentContext;
if (!directCall) {
// the context for eval should be the global scope, so we fake a root
@@ -372,10 +357,10 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
bool inheritContext = !ctx->d()->strictMode;
Script script(ctx, code, QStringLiteral("eval code"));
- script.strictMode = (directCall && parentContext->d()->strictMode);
+ script.strictMode = (directCall && currentContext->d()->strictMode);
script.inheritContext = inheritContext;
script.parse();
- if (scope.engine->hasException)
+ if (v4->hasException)
return Encode::undefined();
Function *function = script.function();
@@ -395,14 +380,14 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
ctx->d()->strictMode = false;
ctx->d()->compilationUnit = function->compilationUnit;
- return function->code(ctx->engine(), function->codeData);
+ return Q_V4_PROFILE(ctx->engine(), function);
}
-ReturnedValue EvalFunction::call(Managed *that, CallData *callData)
+ReturnedValue EvalFunction::call(const Managed *that, CallData *callData)
{
// indirect call
- return static_cast<EvalFunction *>(that)->evalCall(callData, false);
+ return static_cast<const EvalFunction *>(that)->evalCall(callData, false);
}
diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h
index 74de233b47..ced85621de 100644
--- a/src/qml/jsruntime/qv4globalobject_p.h
+++ b/src/qml/jsruntime/qv4globalobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4GLOBALOBJECT_H
#define QV4GLOBALOBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4functionobject_p.h"
@@ -52,10 +63,10 @@ struct Q_QML_EXPORT EvalFunction : FunctionObject
{
V4_OBJECT2(EvalFunction, FunctionObject)
- ReturnedValue evalCall(CallData *callData, bool directCall);
+ ReturnedValue evalCall(CallData *callData, bool directCall) const;
using Object::construct;
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct GlobalFunctions
diff --git a/src/qml/jsruntime/qv4identifier_p.h b/src/qml/jsruntime/qv4identifier_p.h
index 7937391ff7..605b06c685 100644
--- a/src/qml/jsruntime/qv4identifier_p.h
+++ b/src/qml/jsruntime/qv4identifier_p.h
@@ -33,6 +33,17 @@
#ifndef QV4IDENTIFIER_H
#define QV4IDENTIFIER_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qstring.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp
index 138d76bf4a..a5336ee44f 100644
--- a/src/qml/jsruntime/qv4identifiertable.cpp
+++ b/src/qml/jsruntime/qv4identifiertable.cpp
@@ -149,6 +149,22 @@ Identifier *IdentifierTable::identifierImpl(const Heap::String *str)
return str->identifier;
}
+Heap::String *IdentifierTable::stringFromIdentifier(Identifier *i)
+{
+ if (!i)
+ return 0;
+
+ uint idx = i->hashValue % alloc;
+ while (1) {
+ Heap::String *e = entries[idx];
+ Q_ASSERT(e);
+ if (e->identifier == i)
+ return e;
+ ++idx;
+ idx %= alloc;
+ }
+}
+
Identifier *IdentifierTable::identifier(const QString &s)
{
return insertString(s)->identifier;
diff --git a/src/qml/jsruntime/qv4identifiertable_p.h b/src/qml/jsruntime/qv4identifiertable_p.h
index ff374225f4..3af9db963e 100644
--- a/src/qml/jsruntime/qv4identifiertable_p.h
+++ b/src/qml/jsruntime/qv4identifiertable_p.h
@@ -33,6 +33,17 @@
#ifndef QV4IDENTIFIERTABLE_H
#define QV4IDENTIFIERTABLE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4identifier_p.h"
#include "qv4string_p.h"
#include "qv4engine_p.h"
@@ -74,14 +85,16 @@ public:
Identifier *identifierImpl(const Heap::String *str);
+ Heap::String *stringFromIdentifier(Identifier *i);
+
void mark(ExecutionEngine *e) {
for (int i = 0; i < alloc; ++i) {
Heap::String *entry = entries[i];
if (!entry || entry->isMarked())
continue;
entry->setMarkBit();
- Q_ASSERT(entry->gcGetVtable()->markObjects);
- entry->gcGetVtable()->markObjects(entry, e);
+ Q_ASSERT(entry->vtable()->markObjects);
+ entry->vtable()->markObjects(entry, e);
}
}
};
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index e4bd460966..90c6738c46 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -49,12 +49,13 @@
QT_BEGIN_NAMESPACE
-QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QQmlContextData *context,
- const QV4::Value &qmlglobal, const QV4::Value &callback)
- : v4(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0), m_context(context)
+QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine,
+ QV4::QmlContext *qmlContext, const QV4::Value &callback)
+ : v4(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0)
{
- m_qmlglobal.set(engine, qmlglobal);
- if (callback.asFunctionObject())
+ if (qmlContext)
+ m_qmlContext.set(engine, *qmlContext);
+ if (callback.as<QV4::FunctionObject>())
m_callbackFunction.set(engine, callback);
m_resultObject.set(v4, resultValue(v4));
@@ -94,14 +95,14 @@ void QV4Include::callback(const QV4::Value &callback, const QV4::Value &status)
{
if (!callback.isObject())
return;
- QV4::ExecutionEngine *v4 = callback.asObject()->engine();
+ QV4::ExecutionEngine *v4 = callback.as<QV4::Object>()->engine();
QV4::Scope scope(v4);
QV4::ScopedFunctionObject f(scope, callback);
if (!f)
return;
QV4::ScopedCallData callData(scope, 1);
- callData->thisObject = v4->globalObject()->asReturnedValue();
+ callData->thisObject = v4->globalObject->asReturnedValue();
callData->args[0] = status;
f->call(callData);
if (scope.hasException())
@@ -142,8 +143,8 @@ void QV4Include::finished()
QString code = QString::fromUtf8(data);
QmlIR::Document::removeScriptPragmas(code);
- QV4::ScopedObject qmlglobal(scope, m_qmlglobal.value());
- QV4::Script script(v4, qmlglobal, code, m_url.toString());
+ QV4::Scoped<QV4::QmlContext> qml(scope, m_qmlContext.value());
+ QV4::Script script(v4, qml, code, m_url.toString());
script.parse();
if (!scope.engine->hasException)
@@ -176,7 +177,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
return QV4::Encode::undefined();
QV4::Scope scope(ctx->engine());
- QQmlContextData *context = QV4::QmlContextWrapper::callingContext(scope.engine);
+ QQmlContextData *context = scope.engine->callingQmlContext();
if (!context || !context->isJSContext)
V4THROW_ERROR("Qt.include(): Can only be called from JavaScript files");
@@ -184,18 +185,16 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
QUrl url(scope.engine->resolvedUrl(ctx->args()[0].toQStringNoThrow()));
QV4::ScopedValue callbackFunction(scope, QV4::Primitive::undefinedValue());
- if (ctx->argc() >= 2 && ctx->args()[1].asFunctionObject())
+ if (ctx->argc() >= 2 && ctx->args()[1].as<QV4::FunctionObject>())
callbackFunction = ctx->args()[1];
QString localFile = QQmlFile::urlToLocalFileOrQrc(url);
QV4::ScopedValue result(scope);
- QV4::ScopedObject qmlcontextobject(scope, scope.engine->qmlContextObject());
+ QV4::Scoped<QV4::QmlContext> qmlcontext(scope, scope.engine->qmlContext());
if (localFile.isEmpty()) {
- QV4Include *i = new QV4Include(url, scope.engine, context,
- qmlcontextobject,
- callbackFunction);
+ QV4Include *i = new QV4Include(url, scope.engine, qmlcontext, callbackFunction);
result = i->result();
} else {
@@ -203,7 +202,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) {
QV4::CompiledData::CompilationUnit *jsUnit = cachedUnit->createCompilationUnit();
- script.reset(new QV4::Script(scope.engine, qmlcontextobject, jsUnit));
+ script.reset(new QV4::Script(scope.engine, qmlcontext, jsUnit));
} else {
QFile f(localFile);
@@ -212,7 +211,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
QString code = QString::fromUtf8(data);
QmlIR::Document::removeScriptPragmas(code);
- script.reset(new QV4::Script(scope.engine, qmlcontextobject, code, url.toString()));
+ script.reset(new QV4::Script(scope.engine, qmlcontext, code, url.toString()));
}
}
@@ -224,7 +223,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
QV4::ScopedValue ex(scope, scope.engine->catchException());
result = resultValue(scope.engine, Exception);
QV4::ScopedString exception(scope, scope.engine->newString(QStringLiteral("exception")));
- result->asObject()->put(exception, ex);
+ result->as<QV4::Object>()->put(exception, ex);
} else {
result = resultValue(scope.engine, Ok);
}
diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h
index 5dc94e8555..3e3cf5e770 100644
--- a/src/qml/jsruntime/qv4include_p.h
+++ b/src/qml/jsruntime/qv4include_p.h
@@ -50,7 +50,7 @@
#include <private/qqmlcontext_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4context_p.h>
QT_BEGIN_NAMESPACE
@@ -76,8 +76,7 @@ private Q_SLOTS:
void finished();
private:
- QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QQmlContextData *context,
- const QV4::Value &qmlglobal, const QV4::Value &callback);
+ QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &callback);
~QV4Include();
QV4::ReturnedValue result();
@@ -95,8 +94,7 @@ private:
QV4::PersistentValue m_callbackFunction;
QV4::PersistentValue m_resultObject;
- QQmlGuardedContextData m_context;
- QV4::PersistentValue m_qmlglobal;
+ QV4::PersistentValue m_qmlContext;
};
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index a90e8e3689..8f0b1776d7 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -134,21 +134,64 @@ InternalClass::InternalClass(const QV4::InternalClass &other)
Q_ASSERT(extensible);
}
+static void insertHoleIntoPropertyData(Object *object, int idx)
+{
+ int inlineSize = object->d()->inlineMemberSize;
+ int icSize = object->internalClass()->size;
+ int from = qMax(idx, inlineSize);
+ int to = from + 1;
+ if (from < icSize)
+ memmove(object->propertyData(to), object->propertyData(from), icSize - from - 1);
+ if (from == idx)
+ return;
+ if (inlineSize < icSize)
+ *object->propertyData(inlineSize) = *object->propertyData(inlineSize - 1);
+ from = idx;
+ to = from + 1;
+ if (from < inlineSize - 1)
+ memmove(object->propertyData(to), object->propertyData(from), inlineSize - from - 1);
+}
+
+static void removeFromPropertyData(Object *object, int idx, bool accessor = false)
+{
+ int inlineSize = object->d()->inlineMemberSize;
+ int icSize = object->internalClass()->size;
+ int delta = (accessor ? 2 : 1);
+ int to = idx;
+ int from = to + delta;
+ if (from < inlineSize) {
+ memmove(object->propertyData(to), object->d()->propertyData(from), (inlineSize - from)*sizeof(Value));
+ to = inlineSize - delta;
+ from = inlineSize;
+ }
+ if (to < inlineSize && from < icSize) {
+ Q_ASSERT(from >= inlineSize);
+ memcpy(object->propertyData(to), object->d()->propertyData(from), (inlineSize - to)*sizeof(Value));
+ to = inlineSize;
+ from = inlineSize + delta;
+ }
+ if (from < icSize + delta) {
+ Q_ASSERT(to >= inlineSize && from > to);
+ memmove(object->propertyData(to), object->d()->propertyData(from), (icSize + delta - to)*sizeof(Value));
+ }
+}
+
void InternalClass::changeMember(Object *object, String *string, PropertyAttributes data, uint *index)
{
uint idx;
- InternalClass *newClass = object->internalClass()->changeMember(string->identifier(), data, &idx);
+ InternalClass *oldClass = object->internalClass();
+ InternalClass *newClass = oldClass->changeMember(string->identifier(), data, &idx);
if (index)
*index = idx;
- if (newClass->size > object->internalClass()->size) {
- Q_ASSERT(newClass->size == object->internalClass()->size + 1);
- memmove(object->memberData()->data + idx + 2, object->memberData()->data + idx + 1, (object->internalClass()->size - idx - 1)*sizeof(Value));
- } else if (newClass->size < object->internalClass()->size) {
- Q_ASSERT(newClass->size == object->internalClass()->size - 1);
- memmove(object->memberData()->data + idx + 1, object->memberData()->data + idx + 2, (object->internalClass()->size - idx - 2)*sizeof(Value));
- }
object->setInternalClass(newClass);
+ if (newClass->size > oldClass->size) {
+ Q_ASSERT(newClass->size == oldClass->size + 1);
+ insertHoleIntoPropertyData(object, idx + 1);
+ } else if (newClass->size < oldClass->size) {
+ Q_ASSERT(newClass->size == oldClass->size - 1);
+ removeFromPropertyData(object, idx + 1);
+ }
}
InternalClassTransition &InternalClass::lookupOrInsertTransition(const InternalClassTransition &t)
@@ -286,6 +329,8 @@ void InternalClass::removeMember(Object *object, Identifier *id)
Transition temp = { id, 0, -1 };
Transition &t = object->internalClass()->lookupOrInsertTransition(temp);
+ bool accessor = oldClass->propertyData.at(propIdx).isAccessor();
+
if (t.lookup) {
object->setInternalClass(t.lookup);
} else {
@@ -300,8 +345,10 @@ void InternalClass::removeMember(Object *object, Identifier *id)
object->setInternalClass(newClass);
}
- // remove the entry in memberdata
- memmove(object->memberData()->data + propIdx, object->memberData()->data + propIdx + 1, (object->internalClass()->size - propIdx)*sizeof(Value));
+ Q_ASSERT(object->internalClass()->size == oldClass->size - (accessor ? 2 : 1));
+
+ // remove the entry in the property data
+ removeFromPropertyData(object, propIdx, accessor);
t.lookup = object->internalClass();
Q_ASSERT(t.lookup);
@@ -352,20 +399,26 @@ InternalClass *InternalClass::frozen()
if (m_frozen)
return m_frozen;
- m_frozen = engine->emptyClass;
+ m_frozen = propertiesFrozen();
+ m_frozen = m_frozen->nonExtensible();
+
+ m_frozen->m_frozen = m_frozen;
+ m_frozen->m_sealed = m_frozen;
+ return m_frozen;
+}
+
+InternalClass *InternalClass::propertiesFrozen() const
+{
+ InternalClass *frozen = engine->emptyClass;
for (uint i = 0; i < size; ++i) {
PropertyAttributes attrs = propertyData.at(i);
if (attrs.isEmpty())
continue;
attrs.setWritable(false);
attrs.setConfigurable(false);
- m_frozen = m_frozen->addMember(nameMap.at(i), attrs);
+ frozen = frozen->addMember(nameMap.at(i), attrs);
}
- m_frozen = m_frozen->nonExtensible();
-
- m_frozen->m_frozen = m_frozen;
- m_frozen->m_sealed = m_frozen;
- return m_frozen;
+ return frozen;
}
void InternalClass::destroy()
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index 3289058cb7..5b91925ede 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -33,6 +33,17 @@
#ifndef QV4INTERNALCLASS_H
#define QV4INTERNALCLASS_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include <QHash>
@@ -46,7 +57,7 @@ struct String;
struct ExecutionEngine;
struct Object;
struct Identifier;
-struct ManagedVTable;
+struct VTable;
struct PropertyHashData;
struct PropertyHash
@@ -233,6 +244,7 @@ struct InternalClass : public QQmlJS::Managed {
InternalClass *sealed();
InternalClass *frozen();
+ InternalClass *propertiesFrozen() const;
void destroy();
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index e7905974df..2e5283c639 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -38,8 +38,8 @@
#include <qv4objectiterator_p.h>
#include <qv4scopedvalue_p.h>
#include <qv4runtime_p.h>
+#include "qv4string_p.h"
-#include <qjsondocument.h>
#include <qstack.h>
#include <qstringlist.h>
@@ -62,33 +62,6 @@ static int indent = 0;
DEFINE_OBJECT_VTABLE(JsonObject);
-class JsonParser
-{
-public:
- JsonParser(ExecutionEngine *engine, const QChar *json, int length);
-
- ReturnedValue parse(QJsonParseError *error);
-
-private:
- inline bool eatSpace();
- inline QChar nextToken();
-
- ReturnedValue parseObject();
- ReturnedValue parseArray();
- bool parseMember(Object *o);
- bool parseString(QString *string);
- bool parseValue(Value *val);
- bool parseNumber(Value *val);
-
- ExecutionEngine *engine;
- const QChar *head;
- const QChar *json;
- const QChar *end;
-
- int nestingLevel;
- QJsonParseError::ParseError lastError;
-};
-
static const int nestingLimit = 1024;
@@ -639,17 +612,22 @@ bool JsonParser::parseString(QString *string)
struct Stringify
{
- ExecutionContext *ctx;
+ ExecutionEngine *v4;
FunctionObject *replacerFunction;
- // ### GC
- QVector<Heap::String *> propertyList;
+ QV4::String *propertyList;
+ int propertyListSize;
QString gap;
QString indent;
+ QStack<Object *> stack;
- // ### GC
- QStack<Heap::Object *> stack;
+ bool stackContains(Object *o) {
+ for (int i = 0; i < stack.size(); ++i)
+ if (stack.at(i)->d() == o->d())
+ return true;
+ return false;
+ }
- Stringify(ExecutionContext *ctx) : ctx(ctx), replacerFunction(0) {}
+ Stringify(ExecutionEngine *e) : v4(e), replacerFunction(0), propertyList(0), propertyListSize(0) {}
QString Str(const QString &key, const Value &v);
QString JA(ArrayObject *a);
@@ -701,26 +679,26 @@ static QString quote(const QString &str)
QString Stringify::Str(const QString &key, const Value &v)
{
- Scope scope(ctx);
+ Scope scope(v4);
ScopedValue value(scope, v);
ScopedObject o(scope, value);
if (o) {
- ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toJSON")));
+ ScopedString s(scope, v4->newString(QStringLiteral("toJSON")));
ScopedFunctionObject toJSON(scope, o->get(s));
if (!!toJSON) {
ScopedCallData callData(scope, 1);
callData->thisObject = value;
- callData->args[0] = ctx->d()->engine->newString(key);
+ callData->args[0] = v4->newString(key);
value = toJSON->call(callData);
}
}
if (replacerFunction) {
- ScopedObject holder(scope, ctx->d()->engine->newObject());
+ ScopedObject holder(scope, v4->newObject());
holder->put(scope.engine, QString(), value);
ScopedCallData callData(scope, 2);
- callData->args[0] = ctx->d()->engine->newString(key);
+ callData->args[0] = v4->newString(key);
callData->args[1] = value;
callData->thisObject = holder;
value = replacerFunction->call(callData);
@@ -728,11 +706,11 @@ QString Stringify::Str(const QString &key, const Value &v)
o = value->asReturnedValue();
if (o) {
- if (NumberObject *n = o->asNumberObject())
+ if (NumberObject *n = o->as<NumberObject>())
value = Encode(n->value());
- else if (StringObject *so = o->asStringObject())
- value = so->d()->value;
- else if (BooleanObject *b =o->asBooleanObject())
+ else if (StringObject *so = o->as<StringObject>())
+ value = so->d()->string;
+ else if (BooleanObject *b = o->as<BooleanObject>())
value = Encode(b->value());
}
@@ -750,8 +728,8 @@ QString Stringify::Str(const QString &key, const Value &v)
o = value->asReturnedValue();
if (o) {
- if (!o->asFunctionObject()) {
- if (o->asArrayObject()) {
+ if (!o->as<FunctionObject>()) {
+ if (o->as<ArrayObject>()) {
return JA(static_cast<ArrayObject *>(o.getPointer()));
} else {
return JO(o);
@@ -777,20 +755,20 @@ QString Stringify::makeMember(const QString &key, const Value &v)
QString Stringify::JO(Object *o)
{
- if (stack.contains(o->d())) {
- ctx->engine()->throwTypeError();
+ if (stackContains(o)) {
+ v4->throwTypeError();
return QString();
}
- Scope scope(ctx);
+ Scope scope(v4);
QString result;
- stack.push(o->d());
+ stack.push(o);
QString stepback = indent;
indent += gap;
QStringList partial;
- if (propertyList.isEmpty()) {
+ if (!propertyListSize) {
ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
ScopedValue name(scope);
@@ -805,11 +783,13 @@ QString Stringify::JO(Object *o)
partial += member;
}
} else {
- ScopedString s(scope);
- for (int i = 0; i < propertyList.size(); ++i) {
+ ScopedValue v(scope);
+ for (int i = 0; i < propertyListSize; ++i) {
bool exists;
- s = propertyList.at(i);
- ScopedValue v(scope, o->get(s, &exists));
+ String *s = propertyList + i;
+ if (!s)
+ continue;
+ v = o->get(s, &exists);
if (!exists)
continue;
QString member = makeMember(s->toQString(), v);
@@ -821,10 +801,11 @@ QString Stringify::JO(Object *o)
if (partial.isEmpty()) {
result = QStringLiteral("{}");
} else if (gap.isEmpty()) {
- result = QStringLiteral("{") + partial.join(QLatin1Char(',')) + QStringLiteral("}");
+ result = QStringLiteral("{") + partial.join(QLatin1Char(',')) + QLatin1Char('}');
} else {
QString separator = QStringLiteral(",\n") + indent;
- result = QStringLiteral("{\n") + indent + partial.join(separator) + QStringLiteral("\n") + stepback + QStringLiteral("}");
+ result = QStringLiteral("{\n") + indent + partial.join(separator) + QLatin1Char('\n')
+ + stepback + QLatin1Char('}');
}
indent = stepback;
@@ -834,15 +815,15 @@ QString Stringify::JO(Object *o)
QString Stringify::JA(ArrayObject *a)
{
- if (stack.contains(a->d())) {
- ctx->engine()->throwTypeError();
+ if (stackContains(a)) {
+ v4->throwTypeError();
return QString();
}
Scope scope(a->engine());
QString result;
- stack.push(a->d());
+ stack.push(a);
QString stepback = indent;
indent += gap;
@@ -878,10 +859,9 @@ QString Stringify::JA(ArrayObject *a)
}
-Heap::JsonObject::JsonObject(ExecutionEngine *e)
- : Heap::Object(e->emptyClass, e->objectPrototype.asObject())
+Heap::JsonObject::JsonObject()
{
- Scope scope(e);
+ Scope scope(internalClass->engine);
ScopedObject o(scope, this);
o->defineDefaultProperty(QStringLiteral("parse"), QV4::JsonObject::method_parse, 2);
@@ -911,32 +891,38 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx)
{
Scope scope(ctx);
- Stringify stringify(ctx);
+ Stringify stringify(scope.engine);
ScopedObject o(scope, ctx->argument(1));
if (o) {
- stringify.replacerFunction = o->asFunctionObject();
+ stringify.replacerFunction = o->as<FunctionObject>();
if (o->isArrayObject()) {
uint arrayLen = o->getLength();
- ScopedValue v(scope);
+ stringify.propertyList = static_cast<QV4::String *>(scope.alloc(arrayLen));
for (uint i = 0; i < arrayLen; ++i) {
- v = o->getIndexed(i);
- if (v->asNumberObject() || v->asStringObject() || v->isNumber())
- v = RuntimeHelpers::toString(scope.engine, v);
- if (v->isString()) {
- String *s = v->stringValue();
- if (!stringify.propertyList.contains(s->d()))
- stringify.propertyList.append(s->d());
+ Value *v = stringify.propertyList + i;
+ *v = o->getIndexed(i);
+ if (v->as<NumberObject>() || v->as<StringObject>() || v->isNumber())
+ *v = RuntimeHelpers::toString(scope.engine, *v);
+ if (!v->isString()) {
+ v->setM(0);
+ } else {
+ for (uint j = 0; j <i; ++j) {
+ if (stringify.propertyList[j].m() == v->m()) {
+ v->setM(0);
+ break;
+ }
+ }
}
}
}
}
ScopedValue s(scope, ctx->argument(2));
- if (NumberObject *n = s->asNumberObject())
+ if (NumberObject *n = s->as<NumberObject>())
s = Encode(n->value());
- else if (StringObject *so = s->asStringObject())
- s = so->d()->value;
+ else if (StringObject *so = s->as<StringObject>())
+ s = so->d()->string;
if (s->isNumber()) {
stringify.gap = QString(qMin(10, (int)s->toInteger()), ' ');
@@ -957,7 +943,7 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx)
ReturnedValue JsonObject::fromJsonValue(ExecutionEngine *engine, const QJsonValue &value)
{
if (value.isString())
- return engine->currentContext()->engine->newString(value.toString())->asReturnedValue();
+ return engine->newString(value.toString())->asReturnedValue();
else if (value.isDouble())
return Encode(value.toDouble());
else if (value.isBool())
@@ -986,7 +972,7 @@ QJsonValue JsonObject::toJsonValue(const Value &value, V4ObjectSet &visitedObjec
return QJsonValue(value.toQString());
Q_ASSERT(value.isObject());
- Scope scope(value.asObject()->engine());
+ Scope scope(value.as<Object>()->engine());
ScopedArrayObject a(scope, value);
if (a)
return toJsonArray(a, visitedObjects);
@@ -1009,22 +995,22 @@ QV4::ReturnedValue JsonObject::fromJsonObject(ExecutionEngine *engine, const QJs
return o.asReturnedValue();
}
-QJsonObject JsonObject::toJsonObject(Object *o, V4ObjectSet &visitedObjects)
+QJsonObject JsonObject::toJsonObject(const Object *o, V4ObjectSet &visitedObjects)
{
QJsonObject result;
- if (!o || o->asFunctionObject())
+ if (!o || o->as<FunctionObject>())
return result;
Scope scope(o->engine());
- if (visitedObjects.contains(o->d())) {
+ if (visitedObjects.contains(ObjectItem(o))) {
// Avoid recursion.
// For compatibility with QVariant{List,Map} conversion, we return an
// empty object (and no error is thrown).
return result;
}
- visitedObjects.insert(o->d());
+ visitedObjects.insert(ObjectItem(o));
ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
ScopedValue name(scope);
@@ -1035,11 +1021,11 @@ QJsonObject JsonObject::toJsonObject(Object *o, V4ObjectSet &visitedObjects)
break;
QString key = name->toQStringNoThrow();
- if (!val->asFunctionObject())
+ if (!val->as<FunctionObject>())
result.insert(key, toJsonValue(val, visitedObjects));
}
- visitedObjects.remove(o->d());
+ visitedObjects.remove(ObjectItem(o));
return result;
}
@@ -1057,7 +1043,7 @@ QV4::ReturnedValue JsonObject::fromJsonArray(ExecutionEngine *engine, const QJso
return a.asReturnedValue();
}
-QJsonArray JsonObject::toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects)
+QJsonArray JsonObject::toJsonArray(const ArrayObject *a, V4ObjectSet &visitedObjects)
{
QJsonArray result;
if (!a)
@@ -1065,25 +1051,25 @@ QJsonArray JsonObject::toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects)
Scope scope(a->engine());
- if (visitedObjects.contains(a->d())) {
+ if (visitedObjects.contains(ObjectItem(a))) {
// Avoid recursion.
// For compatibility with QVariant{List,Map} conversion, we return an
// empty array (and no error is thrown).
return result;
}
- visitedObjects.insert(a->d());
+ visitedObjects.insert(ObjectItem(a));
ScopedValue v(scope);
quint32 length = a->getLength();
for (quint32 i = 0; i < length; ++i) {
v = a->getIndexed(i);
- if (v->asFunctionObject())
+ if (v->as<FunctionObject>())
v = Encode::null();
result.append(toJsonValue(v, visitedObjects));
}
- visitedObjects.remove(a->d());
+ visitedObjects.remove(ObjectItem(a));
return result;
}
diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h
index 81a783ee92..6a6e863bf6 100644
--- a/src/qml/jsruntime/qv4jsonobject_p.h
+++ b/src/qml/jsruntime/qv4jsonobject_p.h
@@ -33,10 +33,23 @@
#ifndef QV4JSONOBJECT_H
#define QV4JSONOBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include <qjsonarray.h>
#include <qjsonobject.h>
#include <qjsonvalue.h>
+#include <qjsondocument.h>
+#include <qhash.h>
QT_BEGIN_NAMESPACE
@@ -45,17 +58,28 @@ namespace QV4 {
namespace Heap {
struct JsonObject : Object {
- JsonObject(ExecutionEngine *e);
+ JsonObject();
};
}
+struct ObjectItem {
+ const QV4::Object *o;
+ ObjectItem(const QV4::Object *o) : o(o) {}
+};
+
+inline bool operator ==(const ObjectItem &a, const ObjectItem &b)
+{ return a.o->d() == b.o->d(); }
+
+inline int qHash(const ObjectItem &i, uint seed = 0)
+{ return ::qHash((void *)i.o->d(), seed); }
+
struct JsonObject : Object {
Q_MANAGED_TYPE(JsonObject)
V4_OBJECT2(JsonObject, Object)
private:
- // ### GC
- typedef QSet<QV4::Heap::Base *> V4ObjectSet;
+
+ typedef QSet<ObjectItem> V4ObjectSet;
public:
static ReturnedValue method_parse(CallContext *ctx);
@@ -67,18 +91,45 @@ public:
static inline QJsonValue toJsonValue(const QV4::Value &value)
{ V4ObjectSet visitedObjects; return toJsonValue(value, visitedObjects); }
- static inline QJsonObject toJsonObject(QV4::Object *o)
+ static inline QJsonObject toJsonObject(const QV4::Object *o)
{ V4ObjectSet visitedObjects; return toJsonObject(o, visitedObjects); }
- static inline QJsonArray toJsonArray(QV4::ArrayObject *a)
+ static inline QJsonArray toJsonArray(const QV4::ArrayObject *a)
{ V4ObjectSet visitedObjects; return toJsonArray(a, visitedObjects); }
private:
static QJsonValue toJsonValue(const QV4::Value &value, V4ObjectSet &visitedObjects);
- static QJsonObject toJsonObject(Object *o, V4ObjectSet &visitedObjects);
- static QJsonArray toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects);
+ static QJsonObject toJsonObject(const Object *o, V4ObjectSet &visitedObjects);
+ static QJsonArray toJsonArray(const ArrayObject *a, V4ObjectSet &visitedObjects);
};
+class JsonParser
+{
+public:
+ JsonParser(ExecutionEngine *engine, const QChar *json, int length);
+
+ ReturnedValue parse(QJsonParseError *error);
+
+private:
+ inline bool eatSpace();
+ inline QChar nextToken();
+
+ ReturnedValue parseObject();
+ ReturnedValue parseArray();
+ bool parseMember(Object *o);
+ bool parseString(QString *string);
+ bool parseValue(Value *val);
+ bool parseNumber(Value *val);
+
+ ExecutionEngine *engine;
+ const QChar *head;
+ const QChar *json;
+ const QChar *end;
+
+ int nestingLevel;
+ QJsonParseError::ParseError lastError;
+};
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index 82b20337cb..d97abdb461 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -33,6 +33,7 @@
#include "qv4lookup_p.h"
#include "qv4functionobject_p.h"
#include "qv4scopedvalue_p.h"
+#include "qv4string_p.h"
QT_BEGIN_NAMESPACE
@@ -42,7 +43,7 @@ using namespace QV4;
ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttributes *attrs)
{
ExecutionEngine *engine = o->engine();
- Identifier *name = engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]->identifier;
+ Identifier *name = engine->current->compilationUnit->runtimeStrings[nameIndex]->identifier;
int i = 0;
Heap::Object *obj = o->d();
while (i < Size && obj) {
@@ -52,7 +53,8 @@ ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttribu
if (index != UINT_MAX) {
level = i;
*attrs = obj->internalClass->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData->data[index].asReturnedValue() : Object::getValue(thisObject, obj->propertyAt(index), *attrs);
+ Value *v = obj->propertyData(index);
+ return !attrs->isAccessor() ? v->asReturnedValue() : Object::getValue(thisObject, *v, *attrs);
}
obj = obj->prototype;
@@ -64,7 +66,8 @@ ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttribu
index = obj->internalClass->find(name);
if (index != UINT_MAX) {
*attrs = obj->internalClass->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData->data[index].asReturnedValue() : Object::getValue(thisObject, obj->propertyAt(index), *attrs);
+ Value *v = obj->propertyData(index);
+ return !attrs->isAccessor() ? v->asReturnedValue() : Object::getValue(thisObject, *v, *attrs);
}
obj = obj->prototype;
@@ -72,11 +75,11 @@ ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttribu
return Primitive::emptyValue().asReturnedValue();
}
-ReturnedValue Lookup::lookup(Object *thisObject, PropertyAttributes *attrs)
+ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs)
{
Heap::Object *obj = thisObject->d();
ExecutionEngine *engine = thisObject->engine();
- Identifier *name = engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]->identifier;
+ Identifier *name = engine->current->compilationUnit->runtimeStrings[nameIndex]->identifier;
int i = 0;
while (i < Size && obj) {
classList[i] = obj->internalClass;
@@ -85,7 +88,8 @@ ReturnedValue Lookup::lookup(Object *thisObject, PropertyAttributes *attrs)
if (index != UINT_MAX) {
level = i;
*attrs = obj->internalClass->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData->data[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
+ Value *v = obj->propertyData(index);
+ return !attrs->isAccessor() ? v->asReturnedValue() : thisObject->getValue(*v, *attrs);
}
obj = obj->prototype;
@@ -97,7 +101,8 @@ ReturnedValue Lookup::lookup(Object *thisObject, PropertyAttributes *attrs)
index = obj->internalClass->find(name);
if (index != UINT_MAX) {
*attrs = obj->internalClass->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData->data[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
+ Value *v = obj->propertyData(index);
+ return !attrs->isAccessor() ? v->asReturnedValue() : thisObject->getValue(*v, *attrs);
}
obj = obj->prototype;
@@ -123,7 +128,7 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const Value &object, cons
ScopedObject o(scope, object);
if (!o) {
if (idx < UINT_MAX) {
- if (String *str = object.asString()) {
+ if (const String *str = object.as<String>()) {
if (idx >= (uint)str->toQString().length()) {
return Encode::undefined();
}
@@ -164,11 +169,11 @@ ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const Value &object, con
{
uint idx = index.asArrayIndex();
if (idx == UINT_MAX || !object.isObject())
- return indexedGetterGeneric(l, object, index);
+ return indexedGetterFallback(l, object, index);
Object *o = object.objectValue();
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
- Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (idx < s->len)
if (!s->data(idx).isEmpty())
return s->data(idx).asReturnedValue();
@@ -200,7 +205,7 @@ void Lookup::indexedSetterFallback(Lookup *l, const Value &object, const Value &
uint idx = index.asArrayIndex();
if (idx < UINT_MAX) {
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
- Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (idx < s->len) {
s->data(idx) = value;
return;
@@ -224,7 +229,7 @@ void Lookup::indexedSetterObjectInt(Lookup *l, const Value &object, const Value
Object *o = object.objectValue();
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
- Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (idx < s->len) {
s->data(idx) = v;
return;
@@ -235,7 +240,7 @@ void Lookup::indexedSetterObjectInt(Lookup *l, const Value &object, const Value
ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object)
{
- if (Object *o = object.asObject())
+ if (const Object *o = object.as<Object>())
return o->getLookup(l);
Object *proto;
@@ -244,14 +249,14 @@ ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Va
case Value::Null_Type:
return engine->throwTypeError();
case Value::Boolean_Type:
- proto = engine->booleanPrototype.asObject();
+ proto = engine->booleanPrototype();
break;
case Value::Managed_Type: {
Q_ASSERT(object.isString());
- proto = engine->stringPrototype.asObject();
+ proto = engine->stringPrototype();
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
- if (name->equals(engine->id_length)) {
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
+ if (name->equals(engine->id_length())) {
// special case, as the property is on the object itself
l->getter = stringLengthGetter;
return stringLengthGetter(l, engine, object);
@@ -260,7 +265,7 @@ ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Va
}
case Value::Integer_Type:
default: // Number
- proto = engine->numberPrototype.asObject();
+ proto = engine->numberPrototype();
}
PropertyAttributes attrs;
@@ -291,7 +296,7 @@ ReturnedValue Lookup::getterTwoClasses(Lookup *l, ExecutionEngine *engine, const
Lookup l1 = *l;
if (l1.getter == Lookup::getter0 || l1.getter == Lookup::getter1) {
- if (Object *o = object.asObject()) {
+ if (const Object *o = object.as<Object>()) {
ReturnedValue v = o->getLookup(l);
Lookup l2 = *l;
@@ -328,7 +333,7 @@ ReturnedValue Lookup::getterFallback(Lookup *l, ExecutionEngine *engine, const V
QV4::ScopedObject o(scope, object.toObject(scope.engine));
if (!o)
return Encode::undefined();
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
return o->get(name);
}
@@ -339,7 +344,7 @@ ReturnedValue Lookup::getter0(Lookup *l, ExecutionEngine *engine, const Value &o
// the internal class won't match
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass())
- return o->memberData()->data[l->index].asReturnedValue();
+ return o->propertyData(l->index)->asReturnedValue();
}
return getterTwoClasses(l, engine, object);
}
@@ -352,7 +357,7 @@ ReturnedValue Lookup::getter1(Lookup *l, ExecutionEngine *engine, const Value &o
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index].asReturnedValue();
+ return o->prototype()->propertyData(l->index)->asReturnedValue();
}
return getterTwoClasses(l, engine, object);
}
@@ -368,7 +373,7 @@ ReturnedValue Lookup::getter2(Lookup *l, ExecutionEngine *engine, const Value &o
if (l->classList[1] == p->internalClass) {
p = p->prototype;
if (l->classList[2] == p->internalClass)
- return p->memberData->data[l->index].asReturnedValue();
+ return p->propertyData(l->index)->asReturnedValue();
}
}
}
@@ -383,9 +388,9 @@ ReturnedValue Lookup::getter0getter0(Lookup *l, ExecutionEngine *engine, const V
// the internal class won't match
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass())
- return o->memberData()->data[l->index].asReturnedValue();
+ return o->propertyData(l->index)->asReturnedValue();
if (l->classList[2] == o->internalClass())
- return o->memberData()->data[l->index2].asReturnedValue();
+ return o->propertyData(l->index2)->asReturnedValue();
}
l->getter = getterFallback;
return getterFallback(l, engine, object);
@@ -398,10 +403,10 @@ ReturnedValue Lookup::getter0getter1(Lookup *l, ExecutionEngine *engine, const V
// the internal class won't match
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass())
- return o->memberData()->data[l->index].asReturnedValue();
+ return o->propertyData(l->index)->asReturnedValue();
if (l->classList[2] == o->internalClass() &&
l->classList[3] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index2].asReturnedValue();
+ return o->prototype()->propertyData(l->index2)->asReturnedValue();
}
l->getter = getterFallback;
return getterFallback(l, engine, object);
@@ -415,10 +420,10 @@ ReturnedValue Lookup::getter1getter1(Lookup *l, ExecutionEngine *engine, const V
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index].asReturnedValue();
+ return o->prototype()->propertyData(l->index)->asReturnedValue();
if (l->classList[2] == o->internalClass() &&
l->classList[3] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index2].asReturnedValue();
+ return o->prototype()->propertyData(l->index2)->asReturnedValue();
return getterFallback(l, engine, object);
}
l->getter = getterFallback;
@@ -434,7 +439,7 @@ ReturnedValue Lookup::getterAccessor0(Lookup *l, ExecutionEngine *engine, const
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass()) {
Scope scope(o->engine());
- ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -456,7 +461,7 @@ ReturnedValue Lookup::getterAccessor1(Lookup *l, ExecutionEngine *engine, const
if (l->classList[0] == o->internalClass &&
l->classList[1] == o->prototype->internalClass) {
Scope scope(o->internalClass->engine);
- ScopedFunctionObject getter(scope, o->prototype->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->prototype->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -481,7 +486,7 @@ ReturnedValue Lookup::getterAccessor2(Lookup *l, ExecutionEngine *engine, const
o = o->prototype;
if (l->classList[2] == o->internalClass) {
Scope scope(o->internalClass->engine);
- ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -501,7 +506,7 @@ ReturnedValue Lookup::primitiveGetter0(Lookup *l, ExecutionEngine *engine, const
if (object.type() == l->type) {
Object *o = l->proto;
if (l->classList[0] == o->internalClass())
- return o->memberData()->data[l->index].asReturnedValue();
+ return o->propertyData(l->index)->asReturnedValue();
}
l->getter = getterGeneric;
return getterGeneric(l, engine, object);
@@ -513,7 +518,7 @@ ReturnedValue Lookup::primitiveGetter1(Lookup *l, ExecutionEngine *engine, const
Object *o = l->proto;
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index].asReturnedValue();
+ return o->prototype()->propertyData(l->index)->asReturnedValue();
}
l->getter = getterGeneric;
return getterGeneric(l, engine, object);
@@ -525,7 +530,7 @@ ReturnedValue Lookup::primitiveGetterAccessor0(Lookup *l, ExecutionEngine *engin
Object *o = l->proto;
if (l->classList[0] == o->internalClass()) {
Scope scope(o->engine());
- ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -545,7 +550,7 @@ ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, ExecutionEngine *engin
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass) {
Scope scope(o->engine());
- ScopedFunctionObject getter(scope, o->prototype()->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->prototype()->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -560,7 +565,7 @@ ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, ExecutionEngine *engin
ReturnedValue Lookup::stringLengthGetter(Lookup *l, ExecutionEngine *engine, const Value &object)
{
- if (String *s = object.asString())
+ if (const String *s = object.as<String>())
return Encode(s->d()->length());
l->getter = getterGeneric;
@@ -569,8 +574,8 @@ ReturnedValue Lookup::stringLengthGetter(Lookup *l, ExecutionEngine *engine, con
ReturnedValue Lookup::arrayLengthGetter(Lookup *l, ExecutionEngine *engine, const Value &object)
{
- if (ArrayObject *a = object.asArrayObject())
- return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].asReturnedValue();
+ if (const ArrayObject *a = object.as<ArrayObject>())
+ return a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->asReturnedValue();
l->getter = getterGeneric;
return getterGeneric(l, engine, object);
@@ -579,7 +584,7 @@ ReturnedValue Lookup::arrayLengthGetter(Lookup *l, ExecutionEngine *engine, cons
ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ Object *o = engine->globalObject;
PropertyAttributes attrs;
ReturnedValue v = l->lookup(o, &attrs);
if (v != Primitive::emptyValue().asReturnedValue()) {
@@ -602,15 +607,15 @@ ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine)
}
}
Scope scope(engine);
- ScopedString n(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString n(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
return engine->throwReferenceError(n);
}
ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass())
- return o->memberData()->data[l->index].asReturnedValue();
+ return o->propertyData(l->index)->asReturnedValue();
l->globalGetter = globalGetterGeneric;
return globalGetterGeneric(l, engine);
@@ -618,10 +623,10 @@ ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index].asReturnedValue();
+ return o->prototype()->propertyData(l->index)->asReturnedValue();
l->globalGetter = globalGetterGeneric;
return globalGetterGeneric(l, engine);
@@ -629,13 +634,13 @@ ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionEngine *engine)
{
- Heap::Object *o = engine->globalObject()->d();
+ Heap::Object *o = engine->globalObject->d();
if (l->classList[0] == o->internalClass) {
o = o->prototype;
if (l->classList[1] == o->internalClass) {
o = o->prototype;
if (l->classList[2] == o->internalClass) {
- return o->prototype->memberData->data[l->index].asReturnedValue();
+ return o->prototype->propertyData(l->index)->asReturnedValue();
}
}
}
@@ -645,10 +650,10 @@ ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass()) {
Scope scope(o->engine());
- ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -662,11 +667,11 @@ ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass) {
Scope scope(o->engine());
- ScopedFunctionObject getter(scope, o->prototype()->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->prototype()->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -680,14 +685,14 @@ ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionEngine *engine)
{
- Heap::Object *o = engine->globalObject()->d();
+ Heap::Object *o = engine->globalObject->d();
if (l->classList[0] == o->internalClass) {
o = o->prototype;
if (l->classList[1] == o->internalClass) {
o = o->prototype;
if (l->classList[2] == o->internalClass) {
Scope scope(o->internalClass->engine);
- ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -701,7 +706,7 @@ ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionEngine *engine)
return globalGetterGeneric(l, engine);
}
-void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Scope scope(engine);
ScopedObject o(scope, object);
@@ -709,18 +714,18 @@ void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, const Value &obje
o = RuntimeHelpers::convertToObject(scope.engine, object);
if (!o) // type error
return;
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
o->put(name, value);
return;
}
o->setLookup(l, value);
}
-void Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Lookup l1 = *l;
- if (Object *o = object.asObject()) {
+ if (Object *o = object.as<Object>()) {
o->setLookup(l, value);
if (l->setter == Lookup::setter0) {
@@ -735,36 +740,34 @@ void Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &o
setterFallback(l, engine, object, value);
}
-void Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
QV4::Scope scope(engine);
QV4::ScopedObject o(scope, object.toObject(scope.engine));
if (o) {
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
o->put(name, value);
}
}
-void Lookup::setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
- o->memberData()->data[l->index] = value;
+ *o->propertyData(l->index) = value;
return;
}
setterTwoClasses(l, engine, object, value);
}
-void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
if (!o->prototype()) {
- if (!o->memberData() || l->index >= o->memberData()->size)
- o->ensureMemberIndex(l->index);
- o->memberData()->data[l->index] = value;
o->setInternalClass(l->classList[3]);
+ *o->propertyData(l->index) = value;
return;
}
}
@@ -773,16 +776,14 @@ void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, const Value &obje
setterFallback(l, engine, object, value);
}
-void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
Heap::Object *p = o->prototype();
if (p && p->internalClass == l->classList[1]) {
- if (!o->memberData() || l->index >= o->memberData()->size)
- o->ensureMemberIndex(l->index);
- o->memberData()->data[l->index] = value;
o->setInternalClass(l->classList[3]);
+ *o->propertyData(l->index) = value;
return;
}
}
@@ -791,18 +792,16 @@ void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, const Value &obje
setterFallback(l, engine, object, value);
}
-void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
Heap::Object *p = o->prototype();
if (p && p->internalClass == l->classList[1]) {
p = p->prototype;
if (p && p->internalClass == l->classList[2]) {
- if (!o->memberData() || l->index >= o->memberData()->size)
- o->ensureMemberIndex(l->index);
- o->memberData()->data[l->index] = value;
o->setInternalClass(l->classList[3]);
+ *o->propertyData(l->index) = value;
return;
}
}
@@ -812,16 +811,16 @@ void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, const Value &obje
setterFallback(l, engine, object, value);
}
-void Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
if (o) {
if (o->internalClass() == l->classList[0]) {
- o->memberData()->data[l->index] = value;
+ *o->propertyData(l->index) = value;
return;
}
if (o->internalClass() == l->classList[1]) {
- o->memberData()->data[l->index2] = value;
+ *o->propertyData(l->index2) = value;
return;
}
}
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index 88397dc36c..77ad1a7b65 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -33,6 +33,17 @@
#ifndef QV4LOOKUP_H
#define QV4LOOKUP_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4runtime_p.h"
#include "qv4engine_p.h"
@@ -51,7 +62,7 @@ struct Lookup {
void (*indexedSetter)(Lookup *l, const Value &object, const Value &index, const Value &v);
ReturnedValue (*getter)(Lookup *l, ExecutionEngine *engine, const Value &object);
ReturnedValue (*globalGetter)(Lookup *l, ExecutionEngine *engine);
- void (*setter)(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &v);
+ void (*setter)(Lookup *l, ExecutionEngine *engine, Value &object, const Value &v);
};
union {
ExecutionEngine *engine;
@@ -107,17 +118,17 @@ struct Lookup {
static ReturnedValue globalGetterAccessor1(Lookup *l, ExecutionEngine *engine);
static ReturnedValue globalGetterAccessor2(Lookup *l, ExecutionEngine *engine);
- static void setterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterFallback(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterInsert0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterInsert1(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterInsert2(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setter0setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
+ static void setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
ReturnedValue lookup(const Value &thisObject, Object *obj, PropertyAttributes *attrs);
- ReturnedValue lookup(Object *obj, PropertyAttributes *attrs);
+ ReturnedValue lookup(const Object *obj, PropertyAttributes *attrs);
};
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index c4b9fc597e..e2de36d18e 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -32,13 +32,13 @@
****************************************************************************/
#include "qv4managed_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4errorobject_p.h"
using namespace QV4;
-const ManagedVTable Managed::static_vtbl =
+const VTable Managed::static_vtbl =
{
0,
Managed::IsExecutionContext,
@@ -59,7 +59,7 @@ const ManagedVTable Managed::static_vtbl =
QString Managed::className() const
{
const char *s = 0;
- switch (Type(d()->vtable->type)) {
+ switch (Type(d()->vtable()->type)) {
case Type_Invalid:
case Type_String:
return QString();
@@ -88,29 +88,7 @@ QString Managed::className() const
s = "RegExp";
break;
case Type_ErrorObject:
- switch (static_cast<Heap::ErrorObject *>(d())->errorType) {
- case Heap::ErrorObject::Error:
- s = "Error";
- break;
- case Heap::ErrorObject::EvalError:
- s = "EvalError";
- break;
- case Heap::ErrorObject::RangeError:
- s = "RangeError";
- break;
- case Heap::ErrorObject::ReferenceError:
- s = "ReferenceError";
- break;
- case Heap::ErrorObject::SyntaxError:
- s = "SyntaxError";
- break;
- case Heap::ErrorObject::TypeError:
- s = "TypeError";
- break;
- case Heap::ErrorObject::URIError:
- s = "URIError";
- break;
- }
+ s = ErrorObject::className(static_cast<Heap::ErrorObject *>(d())->errorType);
break;
case Type_ArgumentsObject:
s = "Arguments";
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index aa3e668eef..6a1bd7a9a4 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -33,16 +33,27 @@
#ifndef QMLJS_MANAGED_H
#define QMLJS_MANAGED_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4value_p.h"
-#include "qv4internalclass_p.h"
+#include <private/qv4heap_p.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
#define Q_MANAGED_CHECK \
- template <typename _T> inline void qt_check_for_QMANAGED_macro(const _T *_q_argument) const \
+ template <typename Type> inline void qt_check_for_QMANAGED_macro(const Type *_q_argument) const \
{ int i = qYouForgotTheQ_MANAGED_Macro(this, _q_argument); i = i + 1; }
template <typename T>
@@ -65,10 +76,10 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
Q_MANAGED_CHECK \
typedef QV4::Heap::DataClass Data; \
typedef superClass SuperClass; \
- static const QV4::ManagedVTable static_vtbl; \
- static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl; } \
+ static const QV4::VTable static_vtbl; \
+ static inline const QV4::VTable *staticVTable() { return &static_vtbl; } \
V4_MANAGED_SIZE_TEST \
- QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m); }
+ QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m()); }
#define V4_MANAGED(DataClass, superClass) \
private: \
@@ -84,31 +95,6 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
(classname::func == QV4::Managed::func ? 0 : classname::func)
-struct GCDeletable
-{
- GCDeletable() : next(0), lastCall(false) {}
- virtual ~GCDeletable() {}
- GCDeletable *next;
- bool lastCall;
-};
-
-struct ManagedVTable
-{
- const ManagedVTable * const parent;
- uint isExecutionContext : 1;
- uint isString : 1;
- uint isObject : 1;
- uint isFunctionObject : 1;
- uint isErrorObject : 1;
- uint isArrayData : 1;
- uint unused : 18;
- uint type : 8;
- const char *className;
- void (*destroy)(Heap::Base *);
- void (*markObjects)(Heap::Base *, ExecutionEngine *e);
- bool (*isEqualTo)(Managed *m, Managed *other);
-};
-
#define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \
{ \
parentVTable, \
@@ -127,7 +113,7 @@ struct ManagedVTable
}
#define DEFINE_MANAGED_VTABLE(classname) \
-const QV4::ManagedVTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0)
+const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0)
struct Q_QML_PRIVATE_EXPORT Managed : Value
{
@@ -147,8 +133,6 @@ private:
public:
- inline void mark(QV4::ExecutionEngine *engine);
-
enum Type {
Type_Invalid,
Type_String,
@@ -173,55 +157,15 @@ public:
};
Q_MANAGED_TYPE(Invalid)
- template <typename T>
- T *as() {
- Q_ASSERT(d()->vtable);
-#if !defined(QT_NO_QOBJECT_CHECK)
- static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(this));
-#endif
- const ManagedVTable *vt = d()->vtable;
- while (vt) {
- if (vt == T::staticVTable())
- return static_cast<T *>(this);
- vt = vt->parent;
- }
- return 0;
- }
- template <typename T>
- const T *as() const {
- Q_ASSERT(d()->vtable);
-#if !defined(QT_NO_QOBJECT_CHECK)
- static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(const_cast<Managed *>(this)));
-#endif
- const ManagedVTable *vt = d()->vtable;
- while (vt) {
- if (vt == T::staticVTable())
- return static_cast<T *>(this);
- vt = vt->parent;
- }
- return 0;
- }
-
- String *asString() { return d()->vtable->isString ? reinterpret_cast<String *>(this) : 0; }
- Object *asObject() { return d()->vtable->isObject ? reinterpret_cast<Object *>(this) : 0; }
- ArrayObject *asArrayObject() { return d()->vtable->type == Type_ArrayObject ? reinterpret_cast<ArrayObject *>(this) : 0; }
- FunctionObject *asFunctionObject() { return d()->vtable->isFunctionObject ? reinterpret_cast<FunctionObject *>(this) : 0; }
- BooleanObject *asBooleanObject() { return d()->vtable->type == Type_BooleanObject ? reinterpret_cast<BooleanObject *>(this) : 0; }
- NumberObject *asNumberObject() { return d()->vtable->type == Type_NumberObject ? reinterpret_cast<NumberObject *>(this) : 0; }
- StringObject *asStringObject() { return d()->vtable->type == Type_StringObject ? reinterpret_cast<StringObject *>(this) : 0; }
- DateObject *asDateObject() { return d()->vtable->type == Type_DateObject ? reinterpret_cast<DateObject *>(this) : 0; }
- ErrorObject *asErrorObject() { return d()->vtable->isErrorObject ? reinterpret_cast<ErrorObject *>(this) : 0; }
- ArgumentsObject *asArgumentsObject() { return d()->vtable->type == Type_ArgumentsObject ? reinterpret_cast<ArgumentsObject *>(this) : 0; }
-
- bool isListType() const { return d()->vtable->type == Type_QmlSequence; }
-
- bool isArrayObject() const { return d()->vtable->type == Type_ArrayObject; }
- bool isStringObject() const { return d()->vtable->type == Type_StringObject; }
+ bool isListType() const { return d()->vtable()->type == Type_QmlSequence; }
+
+ bool isArrayObject() const { return d()->vtable()->type == Type_ArrayObject; }
+ bool isStringObject() const { return d()->vtable()->type == Type_StringObject; }
QString className() const;
bool isEqualTo(const Managed *other) const
- { return d()->vtable->isEqualTo(const_cast<Managed *>(this), const_cast<Managed *>(other)); }
+ { return d()->vtable()->isEqualTo(const_cast<Managed *>(this), const_cast<Managed *>(other)); }
static bool isEqualTo(Managed *m, Managed *other);
@@ -237,37 +181,15 @@ private:
template<>
-inline Managed *value_cast(const Value &v) {
- return v.asManaged();
-}
-
-template<typename T>
-inline T *managed_cast(Managed *m)
-{
- return m ? m->as<T>() : 0;
+inline const Managed *Value::as() const {
+ if (isManaged())
+ return managed();
+ return 0;
}
template<>
-inline String *managed_cast(Managed *m)
-{
- return m ? m->asString() : 0;
-}
-template<>
-inline Object *managed_cast(Managed *m)
-{
- return m ? m->asObject() : 0;
-}
-template<>
-inline FunctionObject *managed_cast(Managed *m)
-{
- return m ? m->asFunctionObject() : 0;
-}
-
-inline Value Value::fromManaged(Managed *m)
-{
- if (!m)
- return QV4::Primitive::undefinedValue();
- return *m;
+inline const Object *Value::as() const {
+ return isManaged() && m() && m()->vtable()->isObject ? objectValue() : 0;
}
}
diff --git a/src/qml/jsruntime/qv4math_p.h b/src/qml/jsruntime/qv4math_p.h
index 4f550752aa..cf627bcc5d 100644
--- a/src/qml/jsruntime/qv4math_p.h
+++ b/src/qml/jsruntime/qv4math_p.h
@@ -33,6 +33,17 @@
#ifndef QMLJS_MATH_H
#define QMLJS_MATH_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qglobal.h>
#include <QtCore/qnumeric.h>
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index 473e05bf88..3d3ac84576 100644
--- a/src/qml/jsruntime/qv4mathobject.cpp
+++ b/src/qml/jsruntime/qv4mathobject.cpp
@@ -47,10 +47,9 @@ DEFINE_OBJECT_VTABLE(MathObject);
static const double qt_PI = 2.0 * ::asin(1.0);
-Heap::MathObject::MathObject(ExecutionEngine *e)
- : Heap::Object(e->emptyClass, e->objectPrototype.asObject())
+Heap::MathObject::MathObject()
{
- Scope scope(e);
+ Scope scope(internalClass->engine);
ScopedObject m(scope, this);
m->defineReadonlyProperty(QStringLiteral("E"), Primitive::fromDouble(M_E));
@@ -278,10 +277,15 @@ Q_GLOBAL_STATIC(QThreadStorage<bool *>, seedCreatedStorage);
ReturnedValue MathObject::method_random(CallContext *context)
{
if (!seedCreatedStorage()->hasLocalData()) {
- qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()) ^ reinterpret_cast<quintptr>(context));
+ int msecs = QTime(0,0,0).msecsTo(QTime::currentTime());
+ Q_ASSERT(msecs >= 0);
+ qsrand(uint(uint(msecs) ^ reinterpret_cast<quintptr>(context)));
seedCreatedStorage()->setLocalData(new bool(true));
}
- return Encode(qrand() / (double) RAND_MAX);
+ // rand()/qrand() return a value where the upperbound is RAND_MAX inclusive. So, instead of
+ // dividing by RAND_MAX (which would return 0..RAND_MAX inclusive), we divide by RAND_MAX + 1.
+ qint64 upperLimit = qint64(RAND_MAX) + 1;
+ return Encode(qrand() / double(upperLimit));
}
ReturnedValue MathObject::method_round(CallContext *context)
diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h
index 472b2020b1..a233f74367 100644
--- a/src/qml/jsruntime/qv4mathobject_p.h
+++ b/src/qml/jsruntime/qv4mathobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4MATHOBJECT_H
#define QV4MATHOBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
QT_BEGIN_NAMESPACE
@@ -42,7 +53,7 @@ namespace QV4 {
namespace Heap {
struct MathObject : Object {
- MathObject(ExecutionEngine *e);
+ MathObject();
};
}
diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp
index 03dfee3dcf..20f8d9ec0f 100644
--- a/src/qml/jsruntime/qv4memberdata.cpp
+++ b/src/qml/jsruntime/qv4memberdata.cpp
@@ -32,7 +32,8 @@
****************************************************************************/
#include "qv4memberdata_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
+#include "qv4value_p.h"
using namespace QV4;
@@ -45,20 +46,30 @@ void MemberData::markObjects(Heap::Base *that, ExecutionEngine *e)
m->data[i].mark(e);
}
-Heap::MemberData *MemberData::reallocate(ExecutionEngine *e, Heap::MemberData *old, uint idx)
+static Heap::MemberData *reallocateHelper(ExecutionEngine *e, Heap::MemberData *old, uint n)
{
- uint s = old ? old->size : 0;
- if (idx < s)
- return old;
-
- int newAlloc = qMax((uint)4, 2*idx);
- uint alloc = sizeof(Heap::MemberData) + (newAlloc)*sizeof(Value);
+ uint alloc = sizeof(Heap::MemberData) + (n)*sizeof(Value);
Scope scope(e);
Scoped<MemberData> newMemberData(scope, e->memoryManager->allocManaged<MemberData>(alloc));
if (old)
- memcpy(newMemberData->d(), old, sizeof(Heap::MemberData) + s*sizeof(Value));
+ memcpy(newMemberData->d(), old, sizeof(Heap::MemberData) + old->size * sizeof(Value));
else
new (newMemberData->d()) Heap::MemberData;
- newMemberData->d()->size = newAlloc;
+ newMemberData->d()->size = n;
return newMemberData->d();
}
+
+Heap::MemberData *MemberData::allocate(ExecutionEngine *e, uint n)
+{
+ return reallocateHelper(e, 0, n);
+}
+
+Heap::MemberData *MemberData::reallocate(ExecutionEngine *e, Heap::MemberData *old, uint n)
+{
+ uint s = old ? old->size : 0;
+ if (n < s)
+ return old;
+
+ // n is multiplied by two to leave room for growth
+ return reallocateHelper(e, old, qMax((uint)4, 2*n));
+}
diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h
index 4c7cfa47cb..12f407e869 100644
--- a/src/qml/jsruntime/qv4memberdata_p.h
+++ b/src/qml/jsruntime/qv4memberdata_p.h
@@ -33,6 +33,17 @@
#ifndef QV4MEMBERDATA_H
#define QV4MEMBERDATA_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4managed_p.h"
@@ -61,7 +72,8 @@ struct MemberData : Managed
Value *data() { return d()->data; }
inline uint size() const { return d()->size; }
- static Heap::MemberData *reallocate(QV4::ExecutionEngine *e, Heap::MemberData *old, uint idx);
+ static Heap::MemberData *allocate(QV4::ExecutionEngine *e, uint n);
+ static Heap::MemberData *reallocate(QV4::ExecutionEngine *e, Heap::MemberData *old, uint n);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index 4a1a94e872..4ae30a7f35 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -33,6 +33,7 @@
#include "qv4numberobject_p.h"
#include "qv4runtime_p.h"
+#include "qv4string_p.h"
#include <QtCore/qnumeric.h>
#include <QtCore/qmath.h>
@@ -50,14 +51,14 @@ Heap::NumberCtor::NumberCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue NumberCtor::construct(Managed *m, CallData *callData)
+ReturnedValue NumberCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(m->cast<NumberCtor>()->engine());
double dbl = callData->argc ? callData->args[0].toNumber() : 0.;
return Encode(scope.engine->newNumberObject(dbl));
}
-ReturnedValue NumberCtor::call(Managed *, CallData *callData)
+ReturnedValue NumberCtor::call(const Managed *, CallData *callData)
{
double dbl = callData->argc ? callData->args[0].toNumber() : 0.;
return Encode(dbl);
@@ -67,8 +68,8 @@ void NumberPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(qSNaN()));
ctor->defineReadonlyProperty(QStringLiteral("NEGATIVE_INFINITY"), Primitive::fromDouble(-qInf()));
@@ -81,9 +82,9 @@ QT_WARNING_DISABLE_INTEL(239)
QT_WARNING_POP
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString);
+ defineDefaultProperty(engine->id_toString(), method_toString);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
- defineDefaultProperty(engine->id_valueOf, method_valueOf);
+ defineDefaultProperty(engine->id_valueOf(), method_valueOf);
defineDefaultProperty(QStringLiteral("toFixed"), method_toFixed, 1);
defineDefaultProperty(QStringLiteral("toExponential"), method_toExponential);
defineDefaultProperty(QStringLiteral("toPrecision"), method_toPrecision);
@@ -93,7 +94,7 @@ inline ReturnedValue thisNumberValue(ExecutionContext *ctx)
{
if (ctx->thisObject().isNumber())
return ctx->thisObject().asReturnedValue();
- NumberObject *n = ctx->thisObject().asNumberObject();
+ NumberObject *n = ctx->thisObject().as<NumberObject>();
if (!n)
return ctx->engine()->throwTypeError();
return Encode(n->value());
@@ -103,7 +104,7 @@ inline double thisNumber(ExecutionContext *ctx)
{
if (ctx->thisObject().isNumber())
return ctx->thisObject().asDouble();
- NumberObject *n = ctx->thisObject().asNumberObject();
+ NumberObject *n = ctx->thisObject().as<NumberObject>();
if (!n)
return ctx->engine()->throwTypeError();
return n->value();
@@ -119,7 +120,7 @@ ReturnedValue NumberPrototype::method_toString(CallContext *ctx)
if (ctx->argc() && !ctx->args()[0].isUndefined()) {
int radix = ctx->args()[0].toInt32();
if (radix < 2 || radix > 36)
- return ctx->engine()->throwError(QString::fromLatin1("Number.prototype.toString: %0 is not a valid radix")
+ return ctx->engine()->throwError(QStringLiteral("Number.prototype.toString: %0 is not a valid radix")
.arg(radix));
if (std::isnan(num)) {
@@ -197,7 +198,7 @@ ReturnedValue NumberPrototype::method_toFixed(CallContext *ctx)
QString str;
if (std::isnan(v))
- str = QString::fromLatin1("NaN");
+ str = QStringLiteral("NaN");
else if (qIsInf(v))
str = QString::fromLatin1(v < 0 ? "-Infinity" : "Infinity");
else if (v < 1.e21) {
diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h
index 205995701b..cc5033531e 100644
--- a/src/qml/jsruntime/qv4numberobject_p.h
+++ b/src/qml/jsruntime/qv4numberobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4NUMBEROBJECT_H
#define QV4NUMBEROBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include <QtCore/qnumeric.h>
@@ -53,8 +64,8 @@ struct NumberCtor: FunctionObject
{
V4_OBJECT2(NumberCtor, FunctionObject)
- static ReturnedValue construct(Managed *that, CallData *callData);
- static ReturnedValue call(Managed *, CallData *callData);
+ static ReturnedValue construct(const Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *, CallData *callData);
};
struct NumberPrototype: NumberObject
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 211fd1812e..ba29d52bc6 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -37,12 +37,14 @@
#include "qv4objectproto_p.h"
#include "qv4stringobject_p.h"
#include "qv4argumentsobject_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4lookup_p.h"
#include "qv4scopedvalue_p.h"
#include "qv4memberdata_p.h"
#include "qv4objectiterator_p.h"
#include "qv4identifier_p.h"
+#include "qv4string_p.h"
+#include "qv4identifiertable_p.h"
#include <stdint.h>
@@ -50,15 +52,25 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(Object);
-Heap::Object::Object(InternalClass *internalClass, QV4::Object *prototype)
- : internalClass(internalClass),
- prototype(prototype ? prototype->d() : 0)
+void Object::setInternalClass(InternalClass *ic)
{
- if (internalClass->size) {
- Scope scope(internalClass->engine);
- ScopedObject o(scope, this);
- o->ensureMemberIndex(internalClass->engine, internalClass->size);
- }
+ d()->internalClass = ic;
+ ensureMemberData();
+}
+
+void Object::getProperty(uint index, Property *p, PropertyAttributes *attrs) const
+{
+ p->value = *propertyData(index);
+ *attrs = internalClass()->propertyData.at(index);
+ if (attrs->isAccessor())
+ p->set = *propertyData(index + SetterOffset);
+}
+
+void Object::setProperty(uint index, const Property *p)
+{
+ *propertyData(index) = p->value;
+ if (internalClass()->propertyData.at(index).isAccessor())
+ *propertyData(index + SetterOffset) = p->set;
}
bool Object::setPrototype(Object *proto)
@@ -80,28 +92,32 @@ void Object::put(ExecutionEngine *engine, const QString &name, const Value &valu
put(n, value);
}
-ReturnedValue Object::getValue(const Value &thisObject, const Property *p, PropertyAttributes attrs)
+ReturnedValue Object::getValue(const Value &thisObject, const Value &v, PropertyAttributes attrs)
{
if (!attrs.isAccessor())
- return p->value.asReturnedValue();
- if (!p->getter())
+ return v.asReturnedValue();
+ const QV4::FunctionObject *f = v.as<FunctionObject>();
+ if (!f)
return Encode::undefined();
- Scope scope(p->getter()->internalClass->engine);
- ScopedFunctionObject getter(scope, p->getter());
+ Scope scope(f->engine());
ScopedCallData callData(scope);
callData->thisObject = thisObject;
- return getter->call(callData);
+ return f->call(callData);
}
-void Object::putValue(Property *pd, PropertyAttributes attrs, const Value &value)
+void Object::putValue(uint memberIndex, const Value &value)
{
- if (internalClass()->engine->hasException)
+ QV4::InternalClass *ic = internalClass();
+ if (ic->engine->hasException)
return;
+ PropertyAttributes attrs = ic->propertyData[memberIndex];
+
if (attrs.isAccessor()) {
- if (Heap::FunctionObject *set = pd->setter()) {
- Scope scope(set->internalClass->engine);
+ FunctionObject *set = propertyData(memberIndex + SetterOffset)->as<FunctionObject>();
+ if (set) {
+ Scope scope(ic->engine);
ScopedFunctionObject setter(scope, set);
ScopedCallData callData(scope, 1);
callData->args[0] = value;
@@ -115,11 +131,11 @@ void Object::putValue(Property *pd, PropertyAttributes attrs, const Value &value
if (!attrs.isWritable())
goto reject;
- pd->value = value;
+ *propertyData(memberIndex) = value;
return;
reject:
- if (engine()->currentContext()->strictMode)
+ if (engine()->current->strictMode)
engine()->throwTypeError();
}
@@ -136,9 +152,9 @@ void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(Ca
ExecutionEngine *e = engine();
Scope scope(e);
ScopedString s(scope, e->newIdentifier(name));
- ScopedContext global(scope, e->rootContext());
+ ExecutionContext *global = e->rootContext();
ScopedFunctionObject function(scope, BuiltinFunction::create(global, s, code));
- function->defineReadonlyProperty(e->id_length, Primitive::fromInt32(argumentCount));
+ function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(s, function);
}
@@ -146,9 +162,9 @@ void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(CallConte
{
ExecutionEngine *e = engine();
Scope scope(e);
- ScopedContext global(scope, e->rootContext());
+ ExecutionContext *global = e->rootContext();
ScopedFunctionObject function(scope, BuiltinFunction::create(global, name, code));
- function->defineReadonlyProperty(e->id_length, Primitive::fromInt32(argumentCount));
+ function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(name, function);
}
@@ -165,7 +181,7 @@ void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(CallCo
ExecutionEngine *v4 = engine();
QV4::Scope scope(v4);
ScopedProperty p(scope);
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = v4->rootContext();
p->setGetter(ScopedFunctionObject(scope, (getter ? BuiltinFunction::create(global, name, getter) : 0)));
p->setSetter(ScopedFunctionObject(scope, (setter ? BuiltinFunction::create(global, name, setter) : 0)));
insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
@@ -188,6 +204,12 @@ void Object::markObjects(Heap::Base *that, ExecutionEngine *e)
{
Heap::Object *o = static_cast<Heap::Object *>(that);
+ if (o->inlineMemberSize) {
+ Value *v = o->propertyData(0);
+ for (uint i = 0; i < o->inlineMemberSize; ++i)
+ v[i].mark(e);
+ }
+
if (o->memberData)
o->memberData->mark(e);
if (o->arrayData)
@@ -196,9 +218,11 @@ void Object::markObjects(Heap::Base *that, ExecutionEngine *e)
o->prototype->mark(e);
}
-void Object::ensureMemberIndex(uint idx)
+void Object::ensureMemberData()
{
- d()->memberData = MemberData::reallocate(engine(), d()->memberData, idx);
+ QV4::InternalClass *ic = internalClass();
+ if (ic->size > d()->inlineMemberSize)
+ d()->memberData = MemberData::reallocate(ic->engine, d()->memberData, ic->size - d()->inlineMemberSize);
}
void Object::insertMember(String *s, const Property *p, PropertyAttributes attributes)
@@ -206,102 +230,97 @@ void Object::insertMember(String *s, const Property *p, PropertyAttributes attri
uint idx;
InternalClass::addMember(this, s, attributes, &idx);
-
- ensureMemberIndex(internalClass()->size);
-
if (attributes.isAccessor()) {
- Property *pp = propertyAt(idx);
- pp->value = p->value;
- pp->set = p->set;
+ *propertyData(idx + GetterOffset) = p->value;
+ *propertyData(idx + SetterOffset) = p->set;
} else {
- d()->memberData->data[idx] = p->value;
+ *propertyData(idx) = p->value;
}
}
// Section 8.12.1
-Property *Object::__getOwnProperty__(String *name, PropertyAttributes *attrs)
+void Object::getOwnProperty(String *name, PropertyAttributes *attrs, Property *p)
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
- return __getOwnProperty__(idx, attrs);
+ return getOwnProperty(idx, attrs, p);
uint member = internalClass()->find(name);
if (member < UINT_MAX) {
- if (attrs)
- *attrs = internalClass()->propertyData[member];
- return propertyAt(member);
+ *attrs = internalClass()->propertyData[member];
+ if (p) {
+ p->value = *propertyData(member);
+ if (attrs->isAccessor())
+ p->set = *propertyData(member + SetterOffset);
+ }
+ return;
}
if (attrs)
*attrs = Attr_Invalid;
- return 0;
+ return;
}
-Property *Object::__getOwnProperty__(uint index, PropertyAttributes *attrs)
+void Object::getOwnProperty(uint index, PropertyAttributes *attrs, Property *p)
{
- Property *p = arrayData() ? arrayData()->getProperty(index) : 0;
- if (p) {
- if (attrs)
- *attrs = arrayData()->attributes(index);
- return p;
+ Property *pd = arrayData() ? arrayData()->getProperty(index) : 0;
+ if (pd) {
+ *attrs = arrayData()->attributes(index);
+ if (p)
+ p->copy(pd, *attrs);
+ return;
}
if (isStringObject()) {
- if (attrs)
- *attrs = Attr_NotConfigurable|Attr_NotWritable;
- return static_cast<StringObject *>(this)->getIndex(index);
+ *attrs = Attr_NotConfigurable|Attr_NotWritable;
+ if (p)
+ p->value = static_cast<StringObject *>(this)->getIndex(index);
+ return;
}
if (attrs)
*attrs = Attr_Invalid;
- return 0;
+ return;
}
// Section 8.12.2
-Property *Object::__getPropertyDescriptor__(String *name, PropertyAttributes *attrs) const
+Value *Object::getValueOrSetter(String *name, PropertyAttributes *attrs)
{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return __getPropertyDescriptor__(idx, attrs);
-
+ Q_ASSERT(name->asArrayIndex() == UINT_MAX);
- const Heap::Object *o = d();
+ Heap::Object *o = d();
while (o) {
uint idx = o->internalClass->find(name);
if (idx < UINT_MAX) {
- if (attrs)
- *attrs = o->internalClass->propertyData[idx];
- return const_cast<Property *>(o->propertyAt(idx));
+ *attrs = o->internalClass->propertyData[idx];
+ return o->propertyData(attrs->isAccessor() ? idx + SetterOffset : idx);
}
o = o->prototype;
}
- if (attrs)
- *attrs = Attr_Invalid;
+ *attrs = Attr_Invalid;
return 0;
}
-Property *Object::__getPropertyDescriptor__(uint index, PropertyAttributes *attrs) const
+Value *Object::getValueOrSetter(uint index, PropertyAttributes *attrs)
{
- const Heap::Object *o = d();
+ Heap::Object *o = d();
while (o) {
Property *p = o->arrayData ? o->arrayData->getProperty(index) : 0;
if (p) {
- if (attrs)
- *attrs = o->arrayData->attributes(index);
- return p;
+ *attrs = o->arrayData->attributes(index);
+ return attrs->isAccessor() ? &p->set : &p->value;
}
- if (o->vtable->type == Type_StringObject) {
- Property *p = static_cast<const Heap::StringObject *>(o)->getIndex(index);
- if (p) {
- if (attrs)
- *attrs = (Attr_NotWritable|Attr_NotConfigurable);
- return p;
+ if (o->vtable()->type == Type_StringObject) {
+ if (index < static_cast<const Heap::StringObject *>(o)->length()) {
+ // this is an evil hack, but it works, as the method is only ever called from putIndexed,
+ // where we don't use the returned pointer there for non writable attributes
+ *attrs = (Attr_NotWritable|Attr_NotConfigurable);
+ return reinterpret_cast<Value *>(0x1);
}
}
o = o->prototype;
}
- if (attrs)
- *attrs = Attr_Invalid;
+ *attrs = Attr_Invalid;
return 0;
}
@@ -356,8 +375,7 @@ bool Object::hasOwnProperty(uint index) const
return true;
if (isStringObject()) {
- String *s = static_cast<const StringObject *>(this)->d()->value.asString();
- if (index < (uint)s->d()->length())
+ if (index < static_cast<const StringObject *>(this)->length())
return true;
}
if (!queryIndexed(index).isEmpty())
@@ -365,24 +383,24 @@ bool Object::hasOwnProperty(uint index) const
return false;
}
-ReturnedValue Object::construct(Managed *m, CallData *)
+ReturnedValue Object::construct(const Managed *m, CallData *)
{
- return static_cast<Object *>(m)->engine()->throwTypeError();
+ return static_cast<const Object *>(m)->engine()->throwTypeError();
}
-ReturnedValue Object::call(Managed *m, CallData *)
+ReturnedValue Object::call(const Managed *m, CallData *)
{
- return static_cast<Object *>(m)->engine()->throwTypeError();
+ return static_cast<const Object *>(m)->engine()->throwTypeError();
}
-ReturnedValue Object::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue Object::get(const Managed *m, String *name, bool *hasProperty)
{
- return static_cast<Object *>(m)->internalGet(name, hasProperty);
+ return static_cast<const Object *>(m)->internalGet(name, hasProperty);
}
-ReturnedValue Object::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue Object::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
- return static_cast<Object *>(m)->internalGetIndexed(index, hasProperty);
+ return static_cast<const Object *>(m)->internalGetIndexed(index, hasProperty);
}
void Object::put(Managed *m, String *name, const Value &value)
@@ -416,8 +434,7 @@ PropertyAttributes Object::queryIndexed(const Managed *m, uint index)
return o->arrayData()->attributes(index);
if (o->isStringObject()) {
- String *s = static_cast<const StringObject *>(o)->d()->value.asString();
- if (index < (uint)s->d()->length())
+ if (index < static_cast<const StringObject *>(o)->length())
return (Attr_NotWritable|Attr_NotConfigurable);
}
return Attr_Invalid;
@@ -433,9 +450,9 @@ bool Object::deleteIndexedProperty(Managed *m, uint index)
return static_cast<Object *>(m)->internalDeleteIndexedProperty(index);
}
-ReturnedValue Object::getLookup(Managed *m, Lookup *l)
+ReturnedValue Object::getLookup(const Managed *m, Lookup *l)
{
- Object *o = static_cast<Object *>(m);
+ const Object *o = static_cast<const Object *>(m);
PropertyAttributes attrs;
ReturnedValue v = l->lookup(o, &attrs);
if (v != Primitive::emptyValue().asReturnedValue()) {
@@ -468,7 +485,7 @@ void Object::setLookup(Managed *m, Lookup *l, const Value &value)
{
Scope scope(static_cast<Object *>(m)->engine());
ScopedObject o(scope, static_cast<Object *>(m));
- ScopedString name(scope, scope.engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, scope.engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
InternalClass *c = o->internalClass();
uint idx = c->find(name);
@@ -477,12 +494,12 @@ void Object::setLookup(Managed *m, Lookup *l, const Value &value)
l->classList[0] = o->internalClass();
l->index = idx;
l->setter = Lookup::setter0;
- o->memberData()->data[idx] = value;
+ *o->propertyData(idx) = value;
return;
}
if (idx != UINT_MAX) {
- o->putValue(o->propertyAt(idx), o->internalClass()->propertyData[idx], value);
+ o->putValue(idx, value);
return;
}
}
@@ -516,10 +533,10 @@ void Object::setLookup(Managed *m, Lookup *l, const Value &value)
l->setter = Lookup::setterGeneric;
}
-void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *pd, PropertyAttributes *attrs)
+void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *pd, PropertyAttributes *attrs)
{
Object *o = static_cast<Object *>(m);
- *name = 0;
+ name->setM(0);
*index = UINT_MAX;
if (o->arrayData()) {
@@ -531,7 +548,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
while (it->arrayNode != o->sparseEnd()) {
int k = it->arrayNode->key();
uint pidx = it->arrayNode->value;
- Heap::SparseArrayData *sa = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *sa = o->d()->arrayData.cast<Heap::SparseArrayData>();
Property *p = reinterpret_cast<Property *>(sa->arrayData + pidx);
it->arrayNode = it->arrayNode->nextNode();
PropertyAttributes a = sa->attrs ? sa->attrs[pidx] : Attr_Data;
@@ -548,7 +565,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
}
// dense arrays
while (it->arrayIndex < o->d()->arrayData->len) {
- Heap::SimpleArrayData *sa = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *sa = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Value &val = sa->data(it->arrayIndex);
PropertyAttributes a = o->arrayData()->attributes(it->arrayIndex);
++it->arrayIndex;
@@ -570,13 +587,15 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
continue;
}
- Property *p = o->propertyAt(it->memberIndex);
+ int idx = it->memberIndex;
PropertyAttributes a = o->internalClass()->propertyData[it->memberIndex];
++it->memberIndex;
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
- *name = o->engine()->newString(n->string);
+ name->setM(o->engine()->identifierTable->stringFromIdentifier(n));
*attrs = a;
- pd->copy(p, a);
+ pd->value = *o->propertyData(idx);
+ if (a.isAccessor())
+ pd->set = *o->propertyData(idx + SetterOffset);
return;
}
}
@@ -585,7 +604,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
}
// Section 8.12.3
-ReturnedValue Object::internalGet(String *name, bool *hasProperty)
+ReturnedValue Object::internalGet(String *name, bool *hasProperty) const
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
@@ -600,7 +619,7 @@ ReturnedValue Object::internalGet(String *name, bool *hasProperty)
if (idx < UINT_MAX) {
if (hasProperty)
*hasProperty = true;
- return getValue(o->propertyAt(idx), o->internalClass()->propertyData.at(idx));
+ return getValue(*o->propertyData(idx), o->internalClass()->propertyData.at(idx));
}
o = o->prototype();
@@ -611,7 +630,7 @@ ReturnedValue Object::internalGet(String *name, bool *hasProperty)
return Encode::undefined();
}
-ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
+ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) const
{
Property *pd = 0;
PropertyAttributes attrs;
@@ -625,10 +644,12 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
break;
}
if (o->isStringObject()) {
- pd = static_cast<StringObject *>(o.getPointer())->getIndex(index);
- if (pd) {
+ ScopedString str(scope, static_cast<StringObject *>(o.getPointer())->getIndex(index));
+ if (str) {
attrs = (Attr_NotWritable|Attr_NotConfigurable);
- break;
+ if (hasProperty)
+ *hasProperty = true;
+ return str.asReturnedValue();
}
}
o = o->prototype();
@@ -637,7 +658,7 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
if (pd) {
if (hasProperty)
*hasProperty = true;
- return getValue(pd, attrs);
+ return getValue(pd->value, attrs);
}
if (hasProperty)
@@ -659,22 +680,22 @@ void Object::internalPut(String *name, const Value &value)
name->makeIdentifier(engine());
uint member = internalClass()->find(name);
- Property *pd = 0;
+ Value *v = 0;
PropertyAttributes attrs;
if (member < UINT_MAX) {
- pd = propertyAt(member);
attrs = internalClass()->propertyData[member];
+ v = propertyData(attrs.isAccessor() ? member + SetterOffset : member);
}
// clause 1
- if (pd) {
+ if (v) {
if (attrs.isAccessor()) {
- if (pd->setter())
+ if (v->as<FunctionObject>())
goto cont;
goto reject;
} else if (!attrs.isWritable())
goto reject;
- else if (isArrayObject() && name->equals(engine()->id_length)) {
+ else if (isArrayObject() && name->equals(engine()->id_length())) {
bool ok;
uint l = value.asArrayLength(&ok);
if (!ok) {
@@ -685,7 +706,7 @@ void Object::internalPut(String *name, const Value &value)
if (!ok)
goto reject;
} else {
- pd->value = value;
+ *v = value;
}
return;
} else if (!prototype()) {
@@ -694,9 +715,9 @@ void Object::internalPut(String *name, const Value &value)
} else {
// clause 4
Scope scope(engine());
- if ((pd = ScopedObject(scope, prototype())->__getPropertyDescriptor__(name, &attrs))) {
+ if ((v = ScopedObject(scope, prototype())->getValueOrSetter(name, &attrs))) {
if (attrs.isAccessor()) {
- if (!pd->setter())
+ if (!v->as<FunctionObject>())
goto reject;
} else if (!isExtensible() || !attrs.isWritable()) {
goto reject;
@@ -709,11 +730,11 @@ void Object::internalPut(String *name, const Value &value)
cont:
// Clause 5
- if (pd && attrs.isAccessor()) {
- assert(pd->setter() != 0);
+ if (v && attrs.isAccessor()) {
+ Q_ASSERT(v->as<FunctionObject>());
Scope scope(engine());
- ScopedFunctionObject setter(scope, pd->setter());
+ ScopedFunctionObject setter(scope, *v);
ScopedCallData callData(scope, 1);
callData->args[0] = value;
callData->thisObject = this;
@@ -725,7 +746,7 @@ void Object::internalPut(String *name, const Value &value)
return;
reject:
- if (engine()->currentContext()->strictMode) {
+ if (engine()->current->strictMode) {
QString message = QStringLiteral("Cannot assign to read-only property \"");
message += name->toQString();
message += QLatin1Char('\"');
@@ -740,27 +761,24 @@ void Object::internalPutIndexed(uint index, const Value &value)
PropertyAttributes attrs;
- Property *pd = arrayData() ? arrayData()->getProperty(index) : 0;
- if (pd)
- attrs = arrayData()->attributes(index);
+ Value *v = arrayData() ? arrayData()->getValueOrSetter(index, &attrs) : 0;
- if (!pd && isStringObject()) {
- pd = static_cast<StringObject *>(this)->getIndex(index);
- if (pd)
+ if (!v && isStringObject()) {
+ if (index < static_cast<StringObject *>(this)->length())
// not writable
goto reject;
}
// clause 1
- if (pd) {
+ if (v) {
if (attrs.isAccessor()) {
- if (pd->setter())
+ if (v->as<FunctionObject>())
goto cont;
goto reject;
} else if (!attrs.isWritable())
goto reject;
else
- pd->value = value;
+ *v = value;
return;
} else if (!prototype()) {
if (!isExtensible())
@@ -768,9 +786,9 @@ void Object::internalPutIndexed(uint index, const Value &value)
} else {
// clause 4
Scope scope(engine());
- if ((pd = ScopedObject(scope, prototype())->__getPropertyDescriptor__(index, &attrs))) {
+ if ((v = ScopedObject(scope, prototype())->getValueOrSetter(index, &attrs))) {
if (attrs.isAccessor()) {
- if (!pd->setter())
+ if (!v->as<FunctionObject>())
goto reject;
} else if (!isExtensible() || !attrs.isWritable()) {
goto reject;
@@ -783,11 +801,11 @@ void Object::internalPutIndexed(uint index, const Value &value)
cont:
// Clause 5
- if (pd && attrs.isAccessor()) {
- assert(pd->setter() != 0);
+ if (v && attrs.isAccessor()) {
+ Q_ASSERT(v->as<FunctionObject>());
Scope scope(engine());
- ScopedFunctionObject setter(scope, pd->setter());
+ ScopedFunctionObject setter(scope, *v);
ScopedCallData callData(scope, 1);
callData->args[0] = value;
callData->thisObject = this;
@@ -799,7 +817,7 @@ void Object::internalPutIndexed(uint index, const Value &value)
return;
reject:
- if (engine()->currentContext()->strictMode)
+ if (engine()->current->strictMode)
engine()->throwTypeError();
}
@@ -821,7 +839,7 @@ bool Object::internalDeleteProperty(String *name)
InternalClass::removeMember(this, name->identifier());
return true;
}
- if (engine()->currentContext()->strictMode)
+ if (engine()->current->strictMode)
engine()->throwTypeError();
return false;
}
@@ -839,7 +857,7 @@ bool Object::internalDeleteIndexedProperty(uint index)
if (!ad || ad->vtable()->del(this, index))
return true;
- if (engine()->currentContext()->strictMode)
+ if (engine()->current->strictMode)
engine()->throwTypeError();
return false;
}
@@ -854,17 +872,16 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
Scope scope(engine);
name->makeIdentifier(scope.engine);
- Property *current;
- PropertyAttributes *cattrs;
uint memberIndex;
- if (isArrayObject() && name->equals(engine->id_length)) {
- Q_ASSERT(Heap::ArrayObject::LengthPropertyIndex == internalClass()->find(engine->id_length));
- Property *lp = propertyAt(Heap::ArrayObject::LengthPropertyIndex);
- cattrs = internalClass()->propertyData.constData() + Heap::ArrayObject::LengthPropertyIndex;
- if (attrs.isEmpty() || p->isSubset(attrs, lp, *cattrs))
+ if (isArrayObject() && name->equals(engine->id_length())) {
+ Q_ASSERT(Heap::ArrayObject::LengthPropertyIndex == internalClass()->find(engine->id_length()));
+ ScopedProperty lp(scope);
+ PropertyAttributes cattrs;
+ getProperty(Heap::ArrayObject::LengthPropertyIndex, lp, &cattrs);
+ if (attrs.isEmpty() || p->isSubset(attrs, lp, cattrs))
return true;
- if (!cattrs->isWritable() || attrs.type() == PropertyAttributes::Accessor || attrs.isConfigurable() || attrs.isEnumerable())
+ if (!cattrs.isWritable() || attrs.type() == PropertyAttributes::Accessor || attrs.isConfigurable() || attrs.isEnumerable())
goto reject;
bool succeeded = true;
if (attrs.type() == PropertyAttributes::Data) {
@@ -877,8 +894,10 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
}
succeeded = setArrayLength(l);
}
- if (attrs.hasWritable() && !attrs.isWritable())
- cattrs->setWritable(false);
+ if (attrs.hasWritable() && !attrs.isWritable()) {
+ cattrs.setWritable(false);
+ InternalClass::changeMember(this, engine->id_length(), cattrs);
+ }
if (!succeeded)
goto reject;
return true;
@@ -886,10 +905,8 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
// Clause 1
memberIndex = internalClass()->find(name);
- current = (memberIndex < UINT_MAX) ? propertyAt(memberIndex) : 0;
- cattrs = internalClass()->propertyData.constData() + memberIndex;
- if (!current) {
+ if (memberIndex == UINT_MAX) {
// clause 3
if (!isExtensible())
goto reject;
@@ -903,7 +920,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
return __defineOwnProperty__(engine, memberIndex, name, p, attrs);
reject:
- if (engine->currentContext()->strictMode)
+ if (engine->current->strictMode)
engine->throwTypeError();
return false;
}
@@ -919,23 +936,23 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, const Pr
return defineOwnProperty2(engine, index, p, attrs);
reject:
- if (engine->currentContext()->strictMode)
+ if (engine->current->strictMode)
engine->throwTypeError();
return false;
}
bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs)
{
- Property *current = 0;
+ bool hasProperty = 0;
// Clause 1
if (arrayData()) {
- current = arrayData()->getProperty(index);
- if (!current && isStringObject())
- current = static_cast<StringObject *>(this)->getIndex(index);
+ hasProperty = arrayData()->getProperty(index);
+ if (!hasProperty && isStringObject())
+ hasProperty = (index < static_cast<StringObject *>(this)->length());
}
- if (!current) {
+ if (!hasProperty) {
// clause 3
if (!isExtensible())
goto reject;
@@ -955,7 +972,7 @@ bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Prope
return __defineOwnProperty__(engine, index, 0, p, attrs);
reject:
- if (engine->currentContext()->strictMode)
+ if (engine->current->strictMode)
engine->throwTypeError();
return false;
}
@@ -966,13 +983,14 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
if (attrs.isEmpty())
return true;
- Property *current = 0;
+ Scope scope(engine);
+ ScopedProperty current(scope);
PropertyAttributes cattrs;
if (member) {
- current = propertyAt(index);
+ getProperty(index, current, &cattrs);
cattrs = internalClass()->propertyData[index];
} else if (arrayData()) {
- current = arrayData()->getProperty(index);
+ arrayData()->getProperty(index, current, &cattrs);
cattrs = arrayData()->attributes(index);
}
@@ -1006,7 +1024,6 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
initSparseArray();
Q_ASSERT(arrayData());
setArrayAttributes(index, cattrs);
- current = arrayData()->getProperty(index);
}
current->setGetter(0);
current->setSetter(0);
@@ -1017,7 +1034,6 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
if (!member) {
// need to convert the array and the slot
setArrayAttributes(index, cattrs);
- current = arrayData()->getProperty(index);
}
current->value = Primitive::undefinedValue();
}
@@ -1029,9 +1045,9 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
} else { // clause 10
Q_ASSERT(cattrs.isAccessor() && attrs.isAccessor());
if (!cattrs.isConfigurable()) {
- if (!p->value.isEmpty() && current->value.val != p->value.val)
+ if (!p->value.isEmpty() && current->value.rawValue() != p->value.rawValue())
goto reject;
- if (!p->set.isEmpty() && current->set.val != p->set.val)
+ if (!p->set.isEmpty() && current->set.rawValue() != p->set.rawValue())
goto reject;
}
}
@@ -1041,12 +1057,14 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
current->merge(cattrs, p, attrs);
if (member) {
InternalClass::changeMember(this, member, cattrs);
+ setProperty(index, current);
} else {
setArrayAttributes(index, cattrs);
+ arrayData()->setProperty(index, current);
}
return true;
reject:
- if (engine->currentContext()->strictMode)
+ if (engine->current->strictMode)
engine->throwTypeError();
return false;
}
@@ -1089,7 +1107,7 @@ void Object::copyArrayData(Object *other)
dd->len = other->d()->arrayData->len;
dd->offset = other->d()->arrayData->offset;
}
- memcpy(d()->arrayData->arrayData, other->d()->arrayData->arrayData, d()->arrayData->alloc*sizeof(Value));
+ memcpy(d()->arrayData->arrayData, other->d()->arrayData->arrayData, other->d()->arrayData->alloc*sizeof(Value));
}
setArrayLengthUnchecked(other->getLength());
}
@@ -1097,7 +1115,7 @@ void Object::copyArrayData(Object *other)
uint Object::getLength(const Managed *m)
{
Scope scope(static_cast<const Object *>(m)->engine());
- ScopedValue v(scope, static_cast<Object *>(const_cast<Managed *>(m))->get(scope.engine->id_length));
+ ScopedValue v(scope, static_cast<Object *>(const_cast<Managed *>(m))->get(scope.engine->id_length()));
return v->toUInt32();
}
@@ -1136,11 +1154,11 @@ void Object::initSparseArray()
DEFINE_OBJECT_VTABLE(ArrayObject);
-Heap::ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list)
- : Heap::Object(engine->arrayClass, engine->arrayPrototype.asObject())
+Heap::ArrayObject::ArrayObject(const QStringList &list)
+ : Heap::Object()
{
init();
- Scope scope(engine);
+ Scope scope(internalClass->engine);
ScopedObject a(scope, this);
// Converts a QStringList to JS.
@@ -1151,19 +1169,19 @@ Heap::ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list)
a->arrayReserve(len);
ScopedValue v(scope);
for (int ii = 0; ii < len; ++ii)
- a->arrayPut(ii, (v = engine->newString(list.at(ii))));
+ a->arrayPut(ii, (v = scope.engine->newString(list.at(ii))));
a->setArrayLengthUnchecked(len);
}
-ReturnedValue ArrayObject::getLookup(Managed *m, Lookup *l)
+ReturnedValue ArrayObject::getLookup(const Managed *m, Lookup *l)
{
- Scope scope(static_cast<Object *>(m)->engine());
- ScopedString name(scope, scope.engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
- if (name->equals(scope.engine->id_length)) {
+ Scope scope(static_cast<const Object *>(m)->engine());
+ ScopedString name(scope, scope.engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
+ if (name->equals(scope.engine->id_length())) {
// special case, as the property is on the object itself
l->getter = Lookup::arrayLengthGetter;
- ArrayObject *a = static_cast<ArrayObject *>(m);
- return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].asReturnedValue();
+ const ArrayObject *a = static_cast<const ArrayObject *>(m);
+ return a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->asReturnedValue();
}
return Object::getLookup(m, l);
}
@@ -1171,9 +1189,9 @@ ReturnedValue ArrayObject::getLookup(Managed *m, Lookup *l)
uint ArrayObject::getLength(const Managed *m)
{
const ArrayObject *a = static_cast<const ArrayObject *>(m);
- if (a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].isInteger())
- return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].integerValue();
- return Primitive::toUInt32(a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].doubleValue());
+ if (a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->isInteger())
+ return a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->integerValue();
+ return Primitive::toUInt32(a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->doubleValue());
}
QStringList ArrayObject::toQStringList() const
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index e2250b9f18..5c660f7e3f 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -33,31 +33,43 @@
#ifndef QV4_OBJECT_H
#define QV4_OBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4managed_p.h"
#include "qv4memberdata_p.h"
#include "qv4arraydata_p.h"
+#include "qv4engine_p.h"
+#include "qv4scopedvalue_p.h"
+#include "qv4value_p.h"
QT_BEGIN_NAMESPACE
+
namespace QV4 {
namespace Heap {
struct Object : Base {
- Object(ExecutionEngine *engine)
- : internalClass(engine->emptyClass),
- prototype(static_cast<Object *>(engine->objectPrototype.m))
- {
- }
- Object(InternalClass *internal, QV4::Object *prototype);
+ inline Object() {}
- const Property *propertyAt(uint index) const { return reinterpret_cast<const Property *>(memberData->data + index); }
- Property *propertyAt(uint index) { return reinterpret_cast<Property *>(memberData->data + index); }
+ const Value *propertyData(uint index) const { if (index < inlineMemberSize) return reinterpret_cast<const Value *>(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; }
+ Value *propertyData(uint index) { if (index < inlineMemberSize) return reinterpret_cast<Value *>(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; }
+ uint inlineMemberOffset;
+ uint inlineMemberSize;
InternalClass *internalClass;
- Heap::Object *prototype;
- MemberData *memberData;
- ArrayData *arrayData;
+ Pointer<Object> prototype;
+ Pointer<MemberData> memberData;
+ Pointer<ArrayData> arrayData;
};
}
@@ -67,9 +79,9 @@ struct Object : Base {
Q_MANAGED_CHECK \
typedef superClass SuperClass; \
static const QV4::ObjectVTable static_vtbl; \
- static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+ static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \
V4_MANAGED_SIZE_TEST \
- Data *d() const { return static_cast<Data *>(m); }
+ Data *d() const { return static_cast<Data *>(m()); }
#define V4_OBJECT2(DataClass, superClass) \
private: \
@@ -80,33 +92,40 @@ struct Object : Base {
typedef QV4::Heap::DataClass Data; \
typedef superClass SuperClass; \
static const QV4::ObjectVTable static_vtbl; \
- static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+ static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \
V4_MANAGED_SIZE_TEST \
- QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m); }
+ QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m()); }
+
+#define V4_INTERNALCLASS(c) \
+ static QV4::InternalClass *defaultInternalClass(QV4::ExecutionEngine *e) \
+ { return e->c; }
+#define V4_PROTOTYPE(p) \
+ static QV4::Object *defaultPrototype(QV4::ExecutionEngine *e) \
+ { return e->p(); }
struct ObjectVTable
{
- ManagedVTable managedVTable;
- ReturnedValue (*call)(Managed *, CallData *data);
- ReturnedValue (*construct)(Managed *, CallData *data);
- ReturnedValue (*get)(Managed *, String *name, bool *hasProperty);
- ReturnedValue (*getIndexed)(Managed *, uint index, bool *hasProperty);
+ VTable vTable;
+ ReturnedValue (*call)(const Managed *, CallData *data);
+ ReturnedValue (*construct)(const Managed *, CallData *data);
+ ReturnedValue (*get)(const Managed *, String *name, bool *hasProperty);
+ ReturnedValue (*getIndexed)(const Managed *, uint index, bool *hasProperty);
void (*put)(Managed *, String *name, const Value &value);
void (*putIndexed)(Managed *, uint index, const Value &value);
PropertyAttributes (*query)(const Managed *, String *name);
PropertyAttributes (*queryIndexed)(const Managed *, uint index);
bool (*deleteProperty)(Managed *m, String *name);
bool (*deleteIndexedProperty)(Managed *m, uint index);
- ReturnedValue (*getLookup)(Managed *m, Lookup *l);
+ ReturnedValue (*getLookup)(const Managed *m, Lookup *l);
void (*setLookup)(Managed *m, Lookup *l, const Value &v);
uint (*getLength)(const Managed *m);
- void (*advanceIterator)(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
+ void (*advanceIterator)(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
};
#define DEFINE_OBJECT_VTABLE(classname) \
const QV4::ObjectVTable classname::static_vtbl = \
{ \
- DEFINE_MANAGED_VTABLE_INT(classname, &classname::SuperClass::static_vtbl == &Object::static_vtbl ? 0 : &classname::SuperClass::static_vtbl.managedVTable), \
+ DEFINE_MANAGED_VTABLE_INT(classname, &classname::SuperClass::static_vtbl == &Object::static_vtbl ? 0 : &classname::SuperClass::static_vtbl.vTable), \
call, \
construct, \
get, \
@@ -128,31 +147,36 @@ const QV4::ObjectVTable classname::static_vtbl = \
struct Q_QML_EXPORT Object: Managed {
V4_OBJECT2(Object, Object)
Q_MANAGED_TYPE(Object)
+ V4_INTERNALCLASS(emptyClass)
+ V4_PROTOTYPE(objectPrototype)
enum {
- IsObject = true
+ IsObject = true,
+ GetterOffset = 0,
+ SetterOffset = 1
};
InternalClass *internalClass() const { return d()->internalClass; }
- void setInternalClass(InternalClass *ic) { d()->internalClass = ic; }
+ void setInternalClass(InternalClass *ic);
+
+ const Value *propertyData(uint index) const { return d()->propertyData(index); }
+ Value *propertyData(uint index) { return d()->propertyData(index); }
- Heap::MemberData *memberData() { return d()->memberData; }
- const Heap::MemberData *memberData() const { return d()->memberData; }
Heap::ArrayData *arrayData() const { return d()->arrayData; }
void setArrayData(ArrayData *a) { d()->arrayData = a->d(); }
- const Property *propertyAt(uint index) const { return d()->propertyAt(index); }
- Property *propertyAt(uint index) { return d()->propertyAt(index); }
+ void getProperty(uint index, Property *p, PropertyAttributes *attrs) const;
+ void setProperty(uint index, const Property *p);
- const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(d()->vtable); }
+ const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(d()->vtable()); }
Heap::Object *prototype() const { return d()->prototype; }
bool setPrototype(Object *proto);
- Property *__getOwnProperty__(String *name, PropertyAttributes *attrs = 0);
- Property *__getOwnProperty__(uint index, PropertyAttributes *attrs = 0);
+ void getOwnProperty(String *name, PropertyAttributes *attrs, Property *p = 0);
+ void getOwnProperty(uint index, PropertyAttributes *attrs, Property *p = 0);
- Property *__getPropertyDescriptor__(String *name, PropertyAttributes *attrs = 0) const;
- Property *__getPropertyDescriptor__(uint index, PropertyAttributes *attrs = 0) const;
+ Value *getValueOrSetter(String *name, PropertyAttributes *attrs);
+ Value *getValueOrSetter(uint index, PropertyAttributes *attrs);
bool hasProperty(String *name) const;
bool hasProperty(uint index) const;
@@ -171,14 +195,14 @@ struct Q_QML_EXPORT Object: Managed {
//
void put(ExecutionEngine *engine, const QString &name, const Value &value);
- static ReturnedValue getValue(const Value &thisObject, const Property *p, PropertyAttributes attrs);
- ReturnedValue getValue(const Property *p, PropertyAttributes attrs) const {
+ static ReturnedValue getValue(const Value &thisObject, const Value &v, PropertyAttributes attrs);
+ ReturnedValue getValue(const Value &v, PropertyAttributes attrs) const {
Scope scope(this->engine());
ScopedValue t(scope, const_cast<Object *>(this));
- return getValue(t, p, attrs);
+ return getValue(t, v, attrs);
}
- void putValue(Property *pd, PropertyAttributes attrs, const Value &value);
+ void putValue(uint memberIndex, const Value &value);
/* The spec default: Writable: true, Enumerable: false, Configurable: true */
void defineDefaultProperty(String *name, const Value &value) {
@@ -193,10 +217,6 @@ struct Q_QML_EXPORT Object: Managed {
void defineReadonlyProperty(const QString &name, const Value &value);
void defineReadonlyProperty(String *name, const Value &value);
- void ensureMemberIndex(QV4::ExecutionEngine *e, uint idx) {
- d()->memberData = MemberData::reallocate(e, d()->memberData, idx);
- }
-
void insertMember(String *s, const Value &v, PropertyAttributes attributes = Attr_Data) {
Scope scope(engine());
ScopedProperty p(scope);
@@ -273,11 +293,10 @@ public:
return false;
}
- void ensureMemberIndex(uint idx);
- inline ReturnedValue get(String *name, bool *hasProperty = 0)
+ inline ReturnedValue get(String *name, bool *hasProperty = 0) const
{ return vtable()->get(this, name, hasProperty); }
- inline ReturnedValue getIndexed(uint idx, bool *hasProperty = 0)
+ inline ReturnedValue getIndexed(uint idx, bool *hasProperty = 0) const
{ return vtable()->getIndexed(this, idx, hasProperty); }
inline void put(String *name, const Value &v)
{ vtable()->put(this, name, v); }
@@ -291,38 +310,40 @@ public:
{ return vtable()->deleteProperty(this, name); }
bool deleteIndexedProperty(uint index)
{ return vtable()->deleteIndexedProperty(this, index); }
- ReturnedValue getLookup(Lookup *l)
+ ReturnedValue getLookup(Lookup *l) const
{ return vtable()->getLookup(this, l); }
void setLookup(Lookup *l, const Value &v)
{ vtable()->setLookup(this, l, v); }
- void advanceIterator(ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes)
+ void advanceIterator(ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
{ vtable()->advanceIterator(this, it, name, index, p, attributes); }
uint getLength() const { return vtable()->getLength(this); }
- inline ReturnedValue construct(CallData *d)
+ inline ReturnedValue construct(CallData *d) const
{ return vtable()->construct(this, d); }
- inline ReturnedValue call(CallData *d)
+ inline ReturnedValue call(CallData *d) const
{ return vtable()->call(this, d); }
protected:
static void markObjects(Heap::Base *that, ExecutionEngine *e);
- static ReturnedValue construct(Managed *m, CallData *);
- static ReturnedValue call(Managed *m, CallData *);
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue construct(const Managed *m, CallData *);
+ static ReturnedValue call(const Managed *m, CallData *);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static void putIndexed(Managed *m, uint index, const Value &value);
static PropertyAttributes query(const Managed *m, String *name);
static PropertyAttributes queryIndexed(const Managed *m, uint index);
static bool deleteProperty(Managed *m, String *name);
static bool deleteIndexedProperty(Managed *m, uint index);
- static ReturnedValue getLookup(Managed *m, Lookup *l);
+ static ReturnedValue getLookup(const Managed *m, Lookup *l);
static void setLookup(Managed *m, Lookup *l, const Value &v);
- static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static uint getLength(const Managed *m);
+ void ensureMemberData();
+
private:
- ReturnedValue internalGet(String *name, bool *hasProperty);
- ReturnedValue internalGetIndexed(uint index, bool *hasProperty);
+ ReturnedValue internalGet(String *name, bool *hasProperty) const;
+ ReturnedValue internalGetIndexed(uint index, bool *hasProperty) const;
void internalPut(String *name, const Value &value);
void internalPutIndexed(uint index, const Value &value);
bool internalDeleteProperty(String *name);
@@ -335,32 +356,18 @@ private:
namespace Heap {
struct BooleanObject : Object {
- BooleanObject(InternalClass *ic, QV4::Object *prototype)
- : Object(ic, prototype),
- b(false)
- {
- }
-
- BooleanObject(ExecutionEngine *engine, bool b)
- : Object(engine->emptyClass, engine->booleanPrototype.asObject()),
- b(b)
- {
- }
+ BooleanObject() {}
+ BooleanObject(bool b)
+ : b(b)
+ {}
bool b;
};
struct NumberObject : Object {
- NumberObject(InternalClass *ic, QV4::Object *prototype)
- : Object(ic, prototype),
- value(0)
- {
- }
-
- NumberObject(ExecutionEngine *engine, double val)
- : Object(engine->emptyClass, engine->numberPrototype.asObject()),
- value(val)
- {
- }
+ NumberObject() {}
+ NumberObject(double val)
+ : value(val)
+ {}
double value;
};
@@ -369,15 +376,11 @@ struct ArrayObject : Object {
LengthPropertyIndex = 0
};
- ArrayObject(ExecutionEngine *engine)
- : Heap::Object(engine->arrayClass, engine->arrayPrototype.asObject())
- { init(); }
- ArrayObject(ExecutionEngine *engine, const QStringList &list);
- ArrayObject(InternalClass *ic, QV4::Object *prototype)
- : Heap::Object(ic, prototype)
+ ArrayObject()
{ init(); }
+ ArrayObject(const QStringList &list);
void init()
- { memberData->data[LengthPropertyIndex] = Primitive::fromInt32(0); }
+ { *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0); }
};
}
@@ -385,6 +388,7 @@ struct ArrayObject : Object {
struct BooleanObject: Object {
V4_OBJECT2(BooleanObject, Object)
Q_MANAGED_TYPE(BooleanObject)
+ V4_PROTOTYPE(booleanPrototype)
bool value() const { return d()->b; }
@@ -393,6 +397,7 @@ struct BooleanObject: Object {
struct NumberObject: Object {
V4_OBJECT2(NumberObject, Object)
Q_MANAGED_TYPE(NumberObject)
+ V4_PROTOTYPE(numberPrototype)
double value() const { return d()->value; }
};
@@ -400,10 +405,12 @@ struct NumberObject: Object {
struct ArrayObject: Object {
V4_OBJECT2(ArrayObject, Object)
Q_MANAGED_TYPE(ArrayObject)
+ V4_INTERNALCLASS(arrayClass)
+ V4_PROTOTYPE(arrayPrototype)
void init(ExecutionEngine *engine);
- static ReturnedValue getLookup(Managed *m, Lookup *l);
+ static ReturnedValue getLookup(const Managed *m, Lookup *l);
using Object::getLength;
static uint getLength(const Managed *m);
@@ -413,7 +420,7 @@ struct ArrayObject: Object {
inline void Object::setArrayLengthUnchecked(uint l)
{
if (isArrayObject())
- memberData()->data[Heap::ArrayObject::LengthPropertyIndex] = Primitive::fromUInt32(l);
+ *propertyData(Heap::ArrayObject::LengthPropertyIndex) = Primitive::fromUInt32(l);
}
inline void Object::push_back(const Value &v)
@@ -436,10 +443,7 @@ inline void Object::arraySet(uint index, const Property *p, PropertyAttributes a
arrayData()->vtable()->reallocate(this, index + 1, false);
}
setArrayAttributes(index, attributes);
- Property *pd = ArrayData::insert(this, index, attributes.isAccessor());
- pd->value = p->value;
- if (attributes.isAccessor())
- pd->set = p->set;
+ ArrayData::insert(this, index, &p->value, attributes.isAccessor());
if (isArrayObject() && index >= getLength())
setArrayLengthUnchecked(index + 1);
}
@@ -451,20 +455,15 @@ inline void Object::arraySet(uint index, const Value &value)
if (index > 0x1000 && index > 2*d()->arrayData->alloc) {
initSparseArray();
}
- Property *pd = ArrayData::insert(this, index);
- pd->value = value;
+ ArrayData::insert(this, index, &value);
if (isArrayObject() && index >= getLength())
setArrayLengthUnchecked(index + 1);
}
-template<>
-inline Object *value_cast(const Value &v) {
- return v.asObject();
-}
template<>
-inline ArrayObject *value_cast(const Value &v) {
- return v.asArrayObject();
+inline const ArrayObject *Value::as() const {
+ return isManaged() && m() && m()->vtable()->type == Managed::Type_ArrayObject ? static_cast<const ArrayObject *>(this) : 0;
}
#ifndef V4_BOOTSTRAP
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index f36ee554a7..1413f439b1 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -35,6 +35,7 @@
#include "qv4stringobject_p.h"
#include "qv4identifier_p.h"
#include "qv4argumentsobject_p.h"
+#include "qv4string_p.h"
using namespace QV4;
@@ -50,7 +51,7 @@ ObjectIterator::ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scrat
init(o);
}
-ObjectIterator::ObjectIterator(Scope &scope, Object *o, uint flags)
+ObjectIterator::ObjectIterator(Scope &scope, const Object *o, uint flags)
: engine(scope.engine)
, object(scope.alloc(1))
, current(scope.alloc(1))
@@ -62,14 +63,14 @@ ObjectIterator::ObjectIterator(Scope &scope, Object *o, uint flags)
init(o);
}
-void ObjectIterator::init(Object *o)
+void ObjectIterator::init(const Object *o)
{
- object->m = o ? o->m : 0;
- current->m = o ? o->m : 0;
+ object->setM(o ? o->m() : 0);
+ current->setM(o ? o->m() : 0);
-#if QT_POINTER_SIZE == 4
- object->tag = QV4::Value::Managed_Type;
- current->tag = QV4::Value::Managed_Type;
+#ifndef QV4_USE_64_BIT_VALUE_ENCODING
+ object->setTag(QV4::Value::Managed_Type);
+ current->setTag(QV4::Value::Managed_Type);
#endif
if (object->as<ArgumentsObject>()) {
@@ -78,12 +79,12 @@ void ObjectIterator::init(Object *o)
}
}
-void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, PropertyAttributes *attrs)
+void ObjectIterator::next(Value *name, uint *index, Property *pd, PropertyAttributes *attrs)
{
- *name = 0;
+ name->setM(0);
*index = UINT_MAX;
- if (!object->asObject()) {
+ if (!object->as<Object>()) {
*attrs = PropertyAttributes();
return;
}
@@ -92,19 +93,19 @@ void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, Proper
ScopedString n(scope);
while (1) {
- if (!current->asObject())
+ if (!current->as<Object>())
break;
while (1) {
- current->asObject()->advanceIterator(this, name, index, pd, attrs);
+ current->as<Object>()->advanceIterator(this, name, index, pd, attrs);
if (attrs->isEmpty())
break;
// check the property is not already defined earlier in the proto chain
if (current->heapObject() != object->heapObject()) {
- o = object->asObject();
+ o = object->as<Object>();
n = *name;
bool shadowed = false;
- while (o->asObject()->d() != current->heapObject()) {
+ while (o->d() != current->heapObject()) {
if ((!!n && o->hasOwnProperty(n)) ||
(*index != UINT_MAX && o->hasOwnProperty(*index))) {
shadowed = true;
@@ -119,9 +120,9 @@ void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, Proper
}
if (flags & WithProtoChain)
- current->m = current->objectValue()->prototype();
+ current->setM(current->objectValue()->prototype());
else
- current->m = (Heap::Base *)0;
+ current->setM(0);
arrayIndex = 0;
memberIndex = 0;
@@ -131,7 +132,7 @@ void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, Proper
ReturnedValue ObjectIterator::nextPropertyName(Value *value)
{
- if (!object->asObject())
+ if (!object->as<Object>())
return Encode::null();
PropertyAttributes attrs;
@@ -143,17 +144,17 @@ ReturnedValue ObjectIterator::nextPropertyName(Value *value)
if (attrs.isEmpty())
return Encode::null();
- *value = object->objectValue()->getValue(p, attrs);
+ *value = object->objectValue()->getValue(p->value, attrs);
if (!!name)
return name->asReturnedValue();
- assert(index < UINT_MAX);
+ Q_ASSERT(index < UINT_MAX);
return Encode(index);
}
ReturnedValue ObjectIterator::nextPropertyNameAsString(Value *value)
{
- if (!object->asObject())
+ if (!object->as<Object>())
return Encode::null();
PropertyAttributes attrs;
@@ -165,17 +166,17 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString(Value *value)
if (attrs.isEmpty())
return Encode::null();
- *value = object->objectValue()->getValue(p, attrs);
+ *value = object->objectValue()->getValue(p->value, attrs);
if (!!name)
return name->asReturnedValue();
- assert(index < UINT_MAX);
+ Q_ASSERT(index < UINT_MAX);
return Encode(engine->newString(QString::number(index)));
}
ReturnedValue ObjectIterator::nextPropertyNameAsString()
{
- if (!object->asObject())
+ if (!object->as<Object>())
return Encode::null();
PropertyAttributes attrs;
diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h
index a7abd2ca10..877b34c22d 100644
--- a/src/qml/jsruntime/qv4objectiterator_p.h
+++ b/src/qml/jsruntime/qv4objectiterator_p.h
@@ -33,6 +33,17 @@
#ifndef QV4OBJECTITERATOR_H
#define QV4OBJECTITERATOR_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4object_p.h"
@@ -57,9 +68,9 @@ struct Q_QML_EXPORT ObjectIterator
uint flags;
ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scratch2, Object *o, uint flags);
- ObjectIterator(Scope &scope, Object *o, uint flags);
- void init(Object *o);
- void next(Heap::String **name, uint *index, Property *pd, PropertyAttributes *attributes = 0);
+ ObjectIterator(Scope &scope, const Object *o, uint flags);
+ void init(const Object *o);
+ void next(Value *name, uint *index, Property *pd, PropertyAttributes *attributes = 0);
ReturnedValue nextPropertyName(Value *value);
ReturnedValue nextPropertyNameAsString(Value *value);
ReturnedValue nextPropertyNameAsString();
@@ -67,7 +78,7 @@ struct Q_QML_EXPORT ObjectIterator
namespace Heap {
struct ForEachIteratorObject : Object {
- ForEachIteratorObject(QV4::ExecutionEngine *engine, QV4::Object *o);
+ ForEachIteratorObject(QV4::Object *o);
ObjectIterator it;
Value workArea[2];
};
@@ -85,9 +96,8 @@ protected:
};
inline
-Heap::ForEachIteratorObject::ForEachIteratorObject(QV4::ExecutionEngine *engine, QV4::Object *o)
- : Heap::Object(engine)
- , it(engine, workArea, workArea + 1, o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain)
+Heap::ForEachIteratorObject::ForEachIteratorObject(QV4::Object *o)
+ : it(internalClass->engine, workArea, workArea + 1, o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain)
{
}
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 9356ea434e..df7441ef5d 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -34,10 +34,11 @@
#include "qv4objectproto_p.h"
#include "qv4argumentsobject_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4scopedvalue_p.h"
#include "qv4runtime_p.h"
#include "qv4objectiterator_p.h"
+#include "qv4string_p.h"
#include <QtCore/QDateTime>
#include <QtCore/QStringList>
@@ -52,14 +53,14 @@ Heap::ObjectCtor::ObjectCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData)
+ReturnedValue ObjectCtor::construct(const Managed *that, CallData *callData)
{
- ObjectCtor *ctor = static_cast<ObjectCtor *>(that);
+ const ObjectCtor *ctor = static_cast<const ObjectCtor *>(that);
ExecutionEngine *v4 = ctor->engine();
Scope scope(v4);
if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull()) {
ScopedObject obj(scope, v4->newObject());
- ScopedObject proto(scope, ctor->get(v4->id_prototype));
+ ScopedObject proto(scope, ctor->get(v4->id_prototype()));
if (!!proto)
obj->setPrototype(proto);
return obj.asReturnedValue();
@@ -67,9 +68,9 @@ ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData)
return RuntimeHelpers::toObject(scope.engine, callData->args[0]);
}
-ReturnedValue ObjectCtor::call(Managed *m, CallData *callData)
+ReturnedValue ObjectCtor::call(const Managed *m, CallData *callData)
{
- ObjectCtor *ctor = static_cast<ObjectCtor *>(m);
+ const ObjectCtor *ctor = static_cast<const ObjectCtor *>(m);
ExecutionEngine *v4 = ctor->engine();
if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull())
return v4->newObject()->asReturnedValue();
@@ -81,8 +82,8 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
Scope scope(v4);
ScopedObject o(scope, this);
- ctor->defineReadonlyProperty(v4->id_prototype, o);
- ctor->defineReadonlyProperty(v4->id_length, Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(v4->id_prototype(), o);
+ ctor->defineReadonlyProperty(v4->id_length(), Primitive::fromInt32(1));
ctor->defineDefaultProperty(QStringLiteral("getPrototypeOf"), method_getPrototypeOf, 1);
ctor->defineDefaultProperty(QStringLiteral("getOwnPropertyDescriptor"), method_getOwnPropertyDescriptor, 2);
ctor->defineDefaultProperty(QStringLiteral("getOwnPropertyNames"), method_getOwnPropertyNames, 1);
@@ -98,20 +99,20 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
ctor->defineDefaultProperty(QStringLiteral("keys"), method_keys, 1);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(v4->id_toString, method_toString, 0);
+ defineDefaultProperty(v4->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString, 0);
- defineDefaultProperty(v4->id_valueOf, method_valueOf, 0);
+ defineDefaultProperty(v4->id_valueOf(), method_valueOf, 0);
defineDefaultProperty(QStringLiteral("hasOwnProperty"), method_hasOwnProperty, 1);
defineDefaultProperty(QStringLiteral("isPrototypeOf"), method_isPrototypeOf, 1);
defineDefaultProperty(QStringLiteral("propertyIsEnumerable"), method_propertyIsEnumerable, 1);
defineDefaultProperty(QStringLiteral("__defineGetter__"), method_defineGetter, 2);
defineDefaultProperty(QStringLiteral("__defineSetter__"), method_defineSetter, 2);
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = v4->rootContext();
ScopedProperty p(scope);
- p->value = BuiltinFunction::create(global, v4->id___proto__, method_get_proto);
- p->set = BuiltinFunction::create(global, v4->id___proto__, method_set_proto);
- insertMember(v4->id___proto__, p, Attr_Accessor|Attr_NotEnumerable);
+ p->value = BuiltinFunction::create(global, v4->id___proto__(), method_get_proto);
+ p->set = BuiltinFunction::create(global, v4->id___proto__(), method_set_proto);
+ insertMember(v4->id___proto__(), p, Attr_Accessor|Attr_NotEnumerable);
}
ReturnedValue ObjectPrototype::method_getPrototypeOf(CallContext *ctx)
@@ -140,7 +141,8 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(CallContext *ctx)
if (scope.hasException())
return Encode::undefined();
PropertyAttributes attrs;
- Property *desc = O->__getOwnProperty__(name, &attrs);
+ ScopedProperty desc(scope);
+ O->getOwnProperty(name, &attrs, desc);
return fromPropertyDescriptor(scope.engine, desc, attrs);
}
@@ -163,7 +165,7 @@ ReturnedValue ObjectPrototype::method_create(CallContext *ctx)
return ctx->engine()->throwTypeError();
ScopedObject newObject(scope, ctx->d()->engine->newObject());
- newObject->setPrototype(O->asObject());
+ newObject->setPrototype(O->as<Object>());
if (ctx->argc() > 1 && !ctx->args()[1].isUndefined()) {
ctx->d()->callData->args[0] = newObject.asReturnedValue();
@@ -220,7 +222,7 @@ ReturnedValue ObjectPrototype::method_defineProperties(CallContext *ctx)
if (attrs.isEmpty())
break;
PropertyAttributes nattrs;
- val = o->getValue(pd, attrs);
+ val = o->getValue(pd->value, attrs);
toPropertyDescriptor(scope.engine, val, n, &nattrs);
if (scope.engine->hasException)
return Encode::undefined();
@@ -390,7 +392,7 @@ ReturnedValue ObjectPrototype::method_toString(CallContext *ctx)
} else {
ScopedObject obj(scope, RuntimeHelpers::toObject(scope.engine, ctx->thisObject()));
QString className = obj->className();
- return ctx->d()->engine->newString(QString::fromLatin1("[object %1]").arg(className))->asReturnedValue();
+ return ctx->d()->engine->newString(QStringLiteral("[object %1]").arg(className))->asReturnedValue();
}
}
@@ -400,7 +402,7 @@ ReturnedValue ObjectPrototype::method_toLocaleString(CallContext *ctx)
ScopedObject o(scope, ctx->thisObject().toObject(scope.engine));
if (!o)
return Encode::undefined();
- ScopedFunctionObject f(scope, o->get(ctx->d()->engine->id_toString));
+ ScopedFunctionObject f(scope, o->get(ctx->d()->engine->id_toString()));
if (!f)
return ctx->engine()->throwTypeError();
ScopedCallData callData(scope);
@@ -462,7 +464,7 @@ ReturnedValue ObjectPrototype::method_propertyIsEnumerable(CallContext *ctx)
if (scope.engine->hasException)
return Encode::undefined();
PropertyAttributes attrs;
- o->__getOwnProperty__(p, &attrs);
+ o->getOwnProperty(p, &attrs);
return Encode(attrs.isEnumerable());
}
@@ -484,7 +486,7 @@ ReturnedValue ObjectPrototype::method_defineGetter(CallContext *ctx)
if (!o) {
if (!ctx->thisObject().isUndefined())
return Encode::undefined();
- o = ctx->d()->engine->globalObject();
+ o = ctx->d()->engine->globalObject;
}
ScopedProperty pd(scope);
@@ -512,7 +514,7 @@ ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx)
if (!o) {
if (!ctx->thisObject().isUndefined())
return Encode::undefined();
- o = ctx->d()->engine->globalObject();
+ o = ctx->d()->engine->globalObject;
}
ScopedProperty pd(scope);
@@ -525,7 +527,7 @@ ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx)
ReturnedValue ObjectPrototype::method_get_proto(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject o(scope, ctx->thisObject().asObject());
+ ScopedObject o(scope, ctx->thisObject().as<Object>());
if (!o)
return ctx->engine()->throwTypeError();
@@ -572,15 +574,15 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
desc->set = Primitive::emptyValue();
ScopedValue tmp(scope);
- if (o->hasProperty(engine->id_enumerable))
- attrs->setEnumerable((tmp = o->get(engine->id_enumerable))->toBoolean());
+ if (o->hasProperty(engine->id_enumerable()))
+ attrs->setEnumerable((tmp = o->get(engine->id_enumerable()))->toBoolean());
- if (o->hasProperty(engine->id_configurable))
- attrs->setConfigurable((tmp = o->get(engine->id_configurable))->toBoolean());
+ if (o->hasProperty(engine->id_configurable()))
+ attrs->setConfigurable((tmp = o->get(engine->id_configurable()))->toBoolean());
- if (o->hasProperty(engine->id_get)) {
- ScopedValue get(scope, o->get(engine->id_get));
- FunctionObject *f = get->asFunctionObject();
+ if (o->hasProperty(engine->id_get())) {
+ ScopedValue get(scope, o->get(engine->id_get()));
+ FunctionObject *f = get->as<FunctionObject>();
if (f || get->isUndefined()) {
desc->value = get;
} else {
@@ -590,9 +592,9 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->hasProperty(engine->id_set)) {
- ScopedValue set(scope, o->get(engine->id_set));
- FunctionObject *f = set->asFunctionObject();
+ if (o->hasProperty(engine->id_set())) {
+ ScopedValue set(scope, o->get(engine->id_set()));
+ FunctionObject *f = set->as<FunctionObject>();
if (f || set->isUndefined()) {
desc->set = set;
} else {
@@ -602,22 +604,22 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->hasProperty(engine->id_writable)) {
+ if (o->hasProperty(engine->id_writable())) {
if (attrs->isAccessor()) {
engine->throwTypeError();
return;
}
- attrs->setWritable((tmp = o->get(engine->id_writable))->toBoolean());
+ attrs->setWritable((tmp = o->get(engine->id_writable()))->toBoolean());
// writable forces it to be a data descriptor
desc->value = Primitive::undefinedValue();
}
- if (o->hasProperty(engine->id_value)) {
+ if (o->hasProperty(engine->id_value())) {
if (attrs->isAccessor()) {
engine->throwTypeError();
return;
}
- desc->value = o->get(engine->id_value);
+ desc->value = o->get(engine->id_value());
attrs->setType(PropertyAttributes::Data);
}
@@ -628,7 +630,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
ReturnedValue ObjectPrototype::fromPropertyDescriptor(ExecutionEngine *engine, const Property *desc, PropertyAttributes attrs)
{
- if (!desc)
+ if (attrs.isEmpty())
return Encode::undefined();
Scope scope(engine);
diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h
index 4e96681017..ec829e4bd2 100644
--- a/src/qml/jsruntime/qv4objectproto_p.h
+++ b/src/qml/jsruntime/qv4objectproto_p.h
@@ -33,6 +33,17 @@
#ifndef QV4ECMAOBJECTS_P_H
#define QV4ECMAOBJECTS_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include <QtCore/qnumeric.h>
@@ -53,8 +64,8 @@ struct ObjectCtor: FunctionObject
{
V4_OBJECT2(ObjectCtor, FunctionObject)
- static ReturnedValue construct(Managed *that, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct ObjectPrototype: Object
diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp
index 88dc1946b8..4a0f84b685 100644
--- a/src/qml/jsruntime/qv4persistent.cpp
+++ b/src/qml/jsruntime/qv4persistent.cpp
@@ -32,7 +32,7 @@
****************************************************************************/
#include "qv4persistent_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4object_p.h"
#include "PageAllocation.h"
@@ -78,11 +78,11 @@ Page *allocatePage(PersistentValueStorage *storage)
if (p->header.next)
p->header.next->header.prev = &p->header.next;
for (int i = 0; i < kEntriesPerPage - 1; ++i) {
- p->values[i].tag = QV4::Value::Empty_Type;
- p->values[i].int_32 = i + 1;
+ p->values[i].setTag(QV4::Value::Empty_Type);
+ p->values[i].setInt_32(i + 1);
}
- p->values[kEntriesPerPage - 1].tag = QV4::Value::Empty_Type;
- p->values[kEntriesPerPage - 1].int_32 = -1;
+ p->values[kEntriesPerPage - 1].setTag(QV4::Value::Empty_Type);
+ p->values[kEntriesPerPage - 1].setInt_32(-1);
storage->firstPage = p;
@@ -93,15 +93,57 @@ Page *allocatePage(PersistentValueStorage *storage)
}
+PersistentValueStorage::Iterator::Iterator(void *p, int idx)
+ : p(p), index(idx)
+{
+ Page *page = static_cast<Page *>(p);
+ if (page)
+ ++page->header.refCount;
+}
+
+PersistentValueStorage::Iterator::Iterator(const PersistentValueStorage::Iterator &o)
+ : p(o.p), index(o.index)
+{
+ Page *page = static_cast<Page *>(p);
+ if (page)
+ ++page->header.refCount;
+}
+
+PersistentValueStorage::Iterator &PersistentValueStorage::Iterator::operator=(const PersistentValueStorage::Iterator &o)
+{
+ Page *page = static_cast<Page *>(p);
+ if (page && !--page->header.refCount)
+ freePage(p);
+ p = o.p;
+ index = o.index;
+ page = static_cast<Page *>(p);
+ if (page)
+ ++page->header.refCount;
+
+ return *this;
+}
+
+PersistentValueStorage::Iterator::~Iterator()
+{
+ Page *page = static_cast<Page *>(p);
+ if (page && !--page->header.refCount)
+ freePage(page);
+}
+
PersistentValueStorage::Iterator &PersistentValueStorage::Iterator::operator++() {
while (p) {
while (index < kEntriesPerPage - 1) {
++index;
- if (static_cast<Page *>(p)->values[index].tag != QV4::Value::Empty_Type)
+ if (static_cast<Page *>(p)->values[index].tag() != QV4::Value::Empty_Type)
return *this;
}
index = -1;
- p = static_cast<Page *>(p)->header.next;
+ Page *next = static_cast<Page *>(p)->header.next;
+ if (!--static_cast<Page *>(p)->header.refCount)
+ freePage(p);
+ p = next;
+ if (next)
+ ++next->header.refCount;
}
index = 0;
return *this;
@@ -147,10 +189,10 @@ Value *PersistentValueStorage::allocate()
p = allocatePage(this);
Value *v = p->values + p->header.freeList;
- p->header.freeList = v->int_32;
+ p->header.freeList = v->int_32();
++p->header.refCount;
- v->val = Encode::undefined();
+ v->setRawValue(Encode::undefined());
return v;
}
@@ -162,24 +204,19 @@ void PersistentValueStorage::free(Value *v)
Page *p = getPage(v);
- v->tag = QV4::Value::Empty_Type;
- v->int_32 = p->header.freeList;
+ v->setTag(QV4::Value::Empty_Type);
+ v->setInt_32(p->header.freeList);
p->header.freeList = v - p->values;
- if (!--p->header.refCount) {
- if (p->header.prev)
- *p->header.prev = p->header.next;
- if (p->header.next)
- p->header.next->header.prev = p->header.prev;
- p->header.alloc.deallocate();
- }
+ if (!--p->header.refCount)
+ freePage(p);
}
static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase)
{
while (engine->jsStackTop > markBase) {
Heap::Base *h = engine->popForGC();
- Q_ASSERT (h->gcGetVtable()->markObjects);
- h->gcGetVtable()->markObjects(h, engine);
+ Q_ASSERT (h->vtable()->markObjects);
+ h->vtable()->markObjects(h, engine);
}
}
@@ -190,7 +227,7 @@ void PersistentValueStorage::mark(ExecutionEngine *e)
Page *p = static_cast<Page *>(firstPage);
while (p) {
for (int i = 0; i < kEntriesPerPage; ++i) {
- if (Managed *m = p->values[i].asManaged())
+ if (Managed *m = p->values[i].as<Managed>())
m->mark(e);
}
drainMarkStack(e, markBase);
@@ -204,6 +241,16 @@ ExecutionEngine *PersistentValueStorage::getEngine(Value *v)
return getPage(v)->header.engine;
}
+void PersistentValueStorage::freePage(void *page)
+{
+ Page *p = static_cast<Page *>(page);
+ if (p->header.prev)
+ *p->header.prev = p->header.next;
+ if (p->header.next)
+ p->header.next->header.prev = p->header.prev;
+ p->header.alloc.deallocate();
+}
+
PersistentValue::PersistentValue(const PersistentValue &other)
: val(0)
@@ -312,6 +359,12 @@ WeakValue::WeakValue(const WeakValue &other)
}
}
+WeakValue::WeakValue(ExecutionEngine *engine, const Value &value)
+{
+ val = engine->memoryManager->m_weakValues->allocate();
+ *val = value;
+}
+
WeakValue &WeakValue::operator=(const WeakValue &other)
{
if (!val) {
diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h
index 7cac2ed95f..80b4ecdea8 100644
--- a/src/qml/jsruntime/qv4persistent_p.h
+++ b/src/qml/jsruntime/qv4persistent_p.h
@@ -33,7 +33,19 @@
#ifndef QV4PERSISTENT_H
#define QV4PERSISTENT_H
-#include "qv4value_inl_p.h"
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qv4value_p.h"
+#include "qv4managed_p.h"
QT_BEGIN_NAMESPACE
@@ -50,8 +62,10 @@ struct Q_QML_EXPORT PersistentValueStorage
void mark(ExecutionEngine *e);
struct Iterator {
- Q_DECL_CONSTEXPR Iterator(void *p, int idx)
- : p(p), index(idx) {}
+ Iterator(void *p, int idx);
+ Iterator(const Iterator &o);
+ Iterator & operator=(const Iterator &o);
+ ~Iterator();
void *p;
int index;
Iterator &operator++();
@@ -67,6 +81,8 @@ struct Q_QML_EXPORT PersistentValueStorage
ExecutionEngine *engine;
void *firstPage;
+private:
+ static void freePage(void *page);
};
class Q_QML_EXPORT PersistentValue
@@ -96,7 +112,13 @@ public:
Managed *asManaged() const {
if (!val)
return 0;
- return val->asManaged();
+ return val->as<Managed>();
+ }
+ template<typename T>
+ T *as() const {
+ if (!val)
+ return 0;
+ return val->as<T>();
}
ExecutionEngine *engine() const {
@@ -122,6 +144,7 @@ class Q_QML_EXPORT WeakValue
public:
WeakValue() : val(0) {}
WeakValue(const WeakValue &other);
+ WeakValue(ExecutionEngine *engine, const Value &value);
WeakValue &operator=(const WeakValue &other);
~WeakValue();
@@ -138,7 +161,13 @@ public:
Managed *asManaged() const {
if (!val)
return 0;
- return val->asManaged();
+ return val->as<Managed>();
+ }
+ template <typename T>
+ T *as() const {
+ if (!val)
+ return 0;
+ return val->as<T>();
}
ExecutionEngine *engine() const {
diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp
index a7019d0558..b62f367601 100644
--- a/src/qml/jsruntime/qv4profiling.cpp
+++ b/src/qml/jsruntime/qv4profiling.cpp
@@ -32,12 +32,13 @@
****************************************************************************/
#include "qv4profiling_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
+#include <private/qv4string_p.h>
QT_BEGIN_NAMESPACE
-using namespace QV4;
-using namespace QV4::Profiling;
+namespace QV4 {
+namespace Profiling {
FunctionCallProperties FunctionCall::resolve() const
{
@@ -55,42 +56,43 @@ FunctionCallProperties FunctionCall::resolve() const
Profiler::Profiler(QV4::ExecutionEngine *engine) : featuresEnabled(0), m_engine(engine)
{
- static int metatype = qRegisterMetaType<QList<QV4::Profiling::FunctionCallProperties> >();
- static int metatype2 = qRegisterMetaType<QList<QV4::Profiling::MemoryAllocationProperties> >();
- Q_UNUSED(metatype);
- Q_UNUSED(metatype2);
+ static int meta = qRegisterMetaType<QVector<QV4::Profiling::FunctionCallProperties> >();
+ static int meta2 = qRegisterMetaType<QVector<QV4::Profiling::MemoryAllocationProperties> >();
+ Q_UNUSED(meta);
+ Q_UNUSED(meta2);
m_timer.start();
}
-struct FunctionCallComparator {
- bool operator()(const FunctionCallProperties &p1, const FunctionCallProperties &p2)
- { return p1.start < p2.start; }
-};
-
void Profiler::stopProfiling()
{
featuresEnabled = 0;
reportData();
}
+bool operator<(const FunctionCall &call1, const FunctionCall &call2)
+{
+ return call1.m_start < call2.m_start ||
+ (call1.m_start == call2.m_start && (call1.m_end < call2.m_end ||
+ (call1.m_end == call2.m_end && call1.m_function < call2.m_function)));
+}
+
void Profiler::reportData()
{
- QList<FunctionCallProperties> resolved;
+ std::sort(m_data.begin(), m_data.end());
+ QVector<FunctionCallProperties> resolved;
resolved.reserve(m_data.size());
- FunctionCallComparator comp;
- foreach (const FunctionCall &call, m_data) {
- FunctionCallProperties props = call.resolve();
- resolved.insert(std::upper_bound(resolved.begin(), resolved.end(), props, comp), props);
- }
+
+ foreach (const FunctionCall &call, m_data)
+ resolved.append(call.resolve());
+
emit dataReady(resolved, m_memory_data);
+ m_data.clear();
+ m_memory_data.clear();
}
void Profiler::startProfiling(quint64 features)
{
if (featuresEnabled == 0) {
- m_data.clear();
- m_memory_data.clear();
-
if (features & (1 << FeatureMemoryAllocation)) {
qint64 timestamp = m_timer.nsecsElapsed();
MemoryAllocationProperties heap = {timestamp,
@@ -111,4 +113,7 @@ void Profiler::startProfiling(quint64 features)
}
}
+} // namespace Profiling
+} // namespace QV4
+
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h
index c3441eaacd..6c54fc9bbd 100644
--- a/src/qml/jsruntime/qv4profiling_p.h
+++ b/src/qml/jsruntime/qv4profiling_p.h
@@ -34,6 +34,17 @@
#ifndef QV4PROFILING_H
#define QV4PROFILING_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4engine_p.h"
#include "qv4function_p.h"
@@ -104,6 +115,7 @@ public:
FunctionCallProperties resolve() const;
private:
+ friend bool operator<(const FunctionCall &call1, const FunctionCall &call2);
Function *m_function;
qint64 m_start;
@@ -155,14 +167,14 @@ public slots:
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
signals:
- void dataReady(const QList<QV4::Profiling::FunctionCallProperties> &,
- const QList<QV4::Profiling::MemoryAllocationProperties> &);
+ void dataReady(const QVector<QV4::Profiling::FunctionCallProperties> &,
+ const QVector<QV4::Profiling::MemoryAllocationProperties> &);
private:
QV4::ExecutionEngine *m_engine;
QElapsedTimer m_timer;
QVector<FunctionCall> m_data;
- QList<MemoryAllocationProperties> m_memory_data;
+ QVector<MemoryAllocationProperties> m_memory_data;
friend class FunctionCallProfiler;
};
@@ -202,7 +214,7 @@ Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCallProperties, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCall, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QList<QV4::Profiling::FunctionCallProperties>)
-Q_DECLARE_METATYPE(QList<QV4::Profiling::MemoryAllocationProperties>)
+Q_DECLARE_METATYPE(QVector<QV4::Profiling::FunctionCallProperties>)
+Q_DECLARE_METATYPE(QVector<QV4::Profiling::MemoryAllocationProperties>)
#endif // QV4PROFILING_H
diff --git a/src/qml/jsruntime/qv4property_p.h b/src/qml/jsruntime/qv4property_p.h
index 1b55abd1f7..8ddb4cf6f7 100644
--- a/src/qml/jsruntime/qv4property_p.h
+++ b/src/qml/jsruntime/qv4property_p.h
@@ -33,9 +33,19 @@
#ifndef QV4PROPERTYDESCRIPTOR_H
#define QV4PROPERTYDESCRIPTOR_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4value_p.h"
-#include "qv4internalclass_p.h"
QT_BEGIN_NAMESPACE
@@ -73,8 +83,8 @@ struct Property {
inline Heap::FunctionObject *getter() const { return value.isManaged() ? reinterpret_cast<Heap::FunctionObject *>(value.heapObject()) : 0; }
inline Heap::FunctionObject *setter() const { return set.isManaged() ? reinterpret_cast<Heap::FunctionObject *>(set.heapObject()) : 0; }
- inline void setGetter(FunctionObject *g) { value = Primitive::fromManaged(reinterpret_cast<Managed *>(g)); }
- inline void setSetter(FunctionObject *s) { set = s ? Primitive::fromManaged(reinterpret_cast<Managed *>(s)) : Value::fromHeapObject(0); }
+ inline void setGetter(FunctionObject *g) { value = reinterpret_cast<Managed *>(g); }
+ inline void setSetter(FunctionObject *s) { set = (s ? reinterpret_cast<Managed *>(s) : 0); }
void copy(const Property *other, PropertyAttributes attrs) {
value = other->value;
@@ -85,12 +95,12 @@ struct Property {
explicit Property() { value = Encode::undefined(); set = Value::fromHeapObject(0); }
explicit Property(Value v) : value(v) { set = Value::fromHeapObject(0); }
Property(FunctionObject *getter, FunctionObject *setter) {
- value = Primitive::fromManaged(reinterpret_cast<Managed *>(getter));
- set = Primitive::fromManaged(reinterpret_cast<Managed *>(setter));
+ value = reinterpret_cast<Managed *>(getter);
+ set = reinterpret_cast<Managed *>(setter);
}
Property(Heap::FunctionObject *getter, Heap::FunctionObject *setter) {
- value.m = reinterpret_cast<Heap::Base *>(getter);
- set.m = reinterpret_cast<Heap::Base *>(setter);
+ value.setM(reinterpret_cast<Heap::Base *>(getter));
+ set.setM(reinterpret_cast<Heap::Base *>(setter));
}
Property &operator=(Value v) { value = v; return *this; }
private:
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 0a1aa56aab..8f471132b7 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -55,6 +55,7 @@
#include <private/qv4objectproto_p.h>
#include <private/qv4jsonobject_p.h>
#include <private/qv4regexpobject_p.h>
+#include <private/qv4dateobject_p.h>
#include <private/qv4scopedvalue_p.h>
#include <private/qv4mm_p.h>
#include <private/qqmlscriptstring_p.h>
@@ -92,7 +93,7 @@ static QPair<QObject *, int> extractQtMethod(QV4::FunctionObject *function)
static QPair<QObject *, int> extractQtSignal(const Value &value)
{
if (value.isObject()) {
- QV4::ExecutionEngine *v4 = value.asObject()->engine();
+ QV4::ExecutionEngine *v4 = value.as<Object>()->engine();
QV4::Scope scope(v4);
QV4::ScopedFunctionObject function(scope, value);
if (function)
@@ -227,16 +228,15 @@ static QV4::ReturnedValue LoadProperty(QV4::ExecutionEngine *v4, QObject *object
}
}
-Heap::QObjectWrapper::QObjectWrapper(ExecutionEngine *engine, QObject *object)
- : Heap::Object(engine)
- , object(object)
+Heap::QObjectWrapper::QObjectWrapper(QObject *object)
+ : object(object)
{
}
void QObjectWrapper::initializeBindings(ExecutionEngine *engine)
{
- engine->functionPrototype.asObject()->defineDefaultProperty(QStringLiteral("connect"), method_connect);
- engine->functionPrototype.asObject()->defineDefaultProperty(QStringLiteral("disconnect"), method_disconnect);
+ engine->functionPrototype()->defineDefaultProperty(QStringLiteral("connect"), method_connect);
+ engine->functionPrototype()->defineDefaultProperty(QStringLiteral("disconnect"), method_disconnect);
}
QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const
@@ -254,8 +254,8 @@ QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlCont
return result;
}
-ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String *n, QObjectWrapper::RevisionMode revisionMode,
- bool *hasProperty, bool includeImports)
+ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String *name, QObjectWrapper::RevisionMode revisionMode,
+ bool *hasProperty, bool includeImports) const
{
if (QQmlData::wasDeleted(d()->object)) {
if (hasProperty)
@@ -263,20 +263,18 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
return QV4::Encode::undefined();
}
- QV4::Scope scope(engine());
- QV4::ScopedString name(scope, n);
+ ExecutionEngine *v4 = engine();
- if (name->equals(scope.engine->id_destroy) || name->equals(scope.engine->id_toString)) {
- int index = name->equals(scope.engine->id_destroy) ? QV4::QObjectMethod::DestroyMethod : QV4::QObjectMethod::ToStringMethod;
- ScopedContext global(scope, scope.engine->rootContext());
- QV4::ScopedValue method(scope, QV4::QObjectMethod::create(global, d()->object, index));
+ if (name->equals(v4->id_destroy()) || name->equals(v4->id_toString())) {
+ int index = name->equals(v4->id_destroy()) ? QV4::QObjectMethod::DestroyMethod : QV4::QObjectMethod::ToStringMethod;
if (hasProperty)
*hasProperty = true;
- return method->asReturnedValue();
+ ExecutionContext *global = v4->rootContext();
+ return QV4::QObjectMethod::create(global, d()->object, index);
}
QQmlPropertyData local;
- QQmlPropertyData *result = findProperty(scope.engine, qmlContext, name, revisionMode, &local);
+ QQmlPropertyData *result = findProperty(v4, qmlContext, name, revisionMode, &local);
if (!result) {
if (includeImports && name->startsWithUpper()) {
@@ -291,10 +289,10 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
if (r.scriptIndex != -1) {
return QV4::Encode::undefined();
} else if (r.type) {
- return QmlTypeWrapper::create(scope.engine, d()->object,
+ return QmlTypeWrapper::create(v4, d()->object,
r.type, Heap::QmlTypeWrapper::ExcludeEnums);
} else if (r.importNamespace) {
- return QmlTypeWrapper::create(scope.engine, d()->object,
+ return QmlTypeWrapper::create(v4, d()->object,
qmlContext->imports, r.importNamespace, Heap::QmlTypeWrapper::ExcludeEnums);
}
Q_ASSERT(!"Unreachable");
@@ -317,14 +315,11 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
if (hasProperty)
*hasProperty = true;
- ScopedContext ctx(scope, scope.engine->currentContext());
- return getProperty(d()->object, ctx, result);
+ return getProperty(v4, d()->object, result);
}
-ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, bool captureRequired)
+ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, bool captureRequired)
{
- QV4::Scope scope(ctx);
-
QQmlData::flushPendingBinding(object, property->coreIndex);
if (property->isFunction() && !property->isVarProperty()) {
@@ -333,25 +328,19 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
Q_ASSERT(vmemo);
return vmemo->vmeMethod(property->coreIndex);
} else if (property->isV4Function()) {
- QV4::ScopedObject qmlcontextobject(scope, ctx->d()->engine->qmlContextObject());
- ScopedContext global(scope, scope.engine->rootContext());
- return QV4::QObjectMethod::create(global, object, property->coreIndex, qmlcontextobject);
+ Scope scope(engine);
+ ScopedContext global(scope, engine->qmlContext());
+ return QV4::QObjectMethod::create(global, object, property->coreIndex);
} else if (property->isSignalHandler()) {
- QV4::Scoped<QV4::QmlSignalHandler> handler(scope, scope.engine->memoryManager->alloc<QV4::QmlSignalHandler>(ctx->d()->engine, object, property->coreIndex));
-
- QV4::ScopedString connect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("connect")));
- QV4::ScopedString disconnect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("disconnect")));
- handler->put(connect, QV4::ScopedValue(scope, ctx->d()->engine->functionPrototype.asObject()->get(connect)));
- handler->put(disconnect, QV4::ScopedValue(scope, ctx->d()->engine->functionPrototype.asObject()->get(disconnect)));
-
- return handler.asReturnedValue();
+ QmlSignalHandler::initProto(engine);
+ return engine->memoryManager->allocObject<QV4::QmlSignalHandler>(object, property->coreIndex)->asReturnedValue();
} else {
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = engine->rootContext();
return QV4::QObjectMethod::create(global, object, property->coreIndex);
}
}
- QQmlEnginePrivate *ep = scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : 0;
+ QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
if (property->hasAccessors()) {
QQmlNotifier *n = 0;
@@ -360,37 +349,38 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
if (ep && ep->propertyCapture && property->accessors->notifier)
nptr = &n;
- QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(ctx->d()->engine, object, *property, nptr));
+ Scope scope(engine);
+ QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(engine, object, *property, nptr));
if (captureRequired) {
if (property->accessors->notifier) {
- if (n)
- ep->captureProperty(n);
+ if (n && ep->propertyCapture)
+ ep->propertyCapture->captureProperty(n);
} else {
- ep->captureProperty(object, property->coreIndex, property->notifyIndex);
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureProperty(object, property->coreIndex, property->notifyIndex);
}
}
return rv->asReturnedValue();
}
- if (captureRequired && ep && !property->isConstant())
- ep->captureProperty(object, property->coreIndex, property->notifyIndex);
+ if (captureRequired && ep && ep->propertyCapture && !property->isConstant())
+ ep->propertyCapture->captureProperty(object, property->coreIndex, property->notifyIndex);
if (property->isVarProperty()) {
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
return vmemo->vmeProperty(property->coreIndex);
} else if (property->isDirect()) {
- return LoadProperty<ReadAccessor::Direct>(ctx->d()->engine, object, *property, 0);
+ return LoadProperty<ReadAccessor::Direct>(engine, object, *property, 0);
} else {
- return LoadProperty<ReadAccessor::Indirect>(ctx->d()->engine, object, *property, 0);
+ return LoadProperty<ReadAccessor::Indirect>(engine, object, *property, 0);
}
}
ReturnedValue QObjectWrapper::getQmlProperty(QV4::ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, QObjectWrapper::RevisionMode revisionMode, bool *hasProperty)
{
- QV4::Scope scope(engine);
if (QQmlData::wasDeleted(object)) {
if (hasProperty)
*hasProperty = false;
@@ -403,6 +393,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(QV4::ExecutionEngine *engine, QQmlC
return QV4::Encode::null();
}
+ QV4::Scope scope(engine);
QV4::Scoped<QObjectWrapper> wrapper(scope, wrap(engine, object));
if (!wrapper) {
if (hasProperty)
@@ -419,11 +410,7 @@ bool QObjectWrapper::setQmlProperty(ExecutionEngine *engine, QQmlContextData *qm
return false;
QQmlPropertyData local;
- QQmlPropertyData *result = 0;
- {
- result = QQmlPropertyCache::property(engine->jsEngine(), object, name, qmlContext, local);
- }
-
+ QQmlPropertyData *result = QQmlPropertyCache::property(engine->jsEngine(), object, name, qmlContext, local);
if (!result)
return false;
@@ -433,23 +420,21 @@ bool QObjectWrapper::setQmlProperty(ExecutionEngine *engine, QQmlContextData *qm
return false;
}
- Scope scope(engine);
- ScopedContext ctx(scope, engine->currentContext());
- setProperty(object, ctx, result, value);
+ setProperty(engine, object, result, value);
return true;
}
-void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, const Value &value)
+void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, const Value &value)
{
if (!property->isWritable() && !property->isQList()) {
QString error = QLatin1String("Cannot assign to read-only property \"") +
property->name(object) + QLatin1Char('\"');
- ctx->engine()->throwTypeError(error);
+ engine->throwTypeError(error);
return;
}
QQmlBinding *newBinding = 0;
- QV4::Scope scope(ctx);
+ QV4::Scope scope(engine);
QV4::ScopedFunctionObject f(scope, value);
if (f) {
if (!f->isBinding()) {
@@ -460,25 +445,25 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
error += QLatin1String("[unknown property type]");
else
error += QLatin1String(QMetaType::typeName(property->propType));
- ctx->engine()->throwError(error);
+ scope.engine->throwError(error);
return;
}
} else {
// binding assignment.
- QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->d()->engine);
+ QQmlContextData *callingQmlContext = scope.engine->callingQmlContext();
QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
bindingFunction->initBindingLocation();
newBinding = new QQmlBinding(value, object, callingQmlContext);
- newBinding->setTarget(object, *property, callingQmlContext);
+ newBinding->setTarget(object, *property);
}
}
- QQmlAbstractBinding *oldBinding =
- QQmlPropertyPrivate::setBinding(object, property->coreIndex, -1, newBinding);
- if (oldBinding)
- oldBinding->destroy();
+ if (newBinding)
+ QQmlPropertyPrivate::setBinding(newBinding);
+ else
+ QQmlPropertyPrivate::removeBinding(object, property->encodedIndex());
if (!newBinding && property->isVarProperty()) {
// allow assignment of "special" values (null, undefined, function) to var properties
@@ -505,16 +490,16 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
} else if (value.isUndefined() && property->propType == QMetaType::QJsonValue) {
PROPERTY_STORE(QJsonValue, QJsonValue(QJsonValue::Undefined));
} else if (!newBinding && property->propType == qMetaTypeId<QJSValue>()) {
- PROPERTY_STORE(QJSValue, QJSValue(ctx->d()->engine, value.asReturnedValue()));
+ PROPERTY_STORE(QJSValue, QJSValue(scope.engine, value.asReturnedValue()));
} else if (value.isUndefined() && property->propType != qMetaTypeId<QQmlScriptString>()) {
QString error = QLatin1String("Cannot assign [undefined] to ");
if (!QMetaType::typeName(property->propType))
error += QLatin1String("[unknown property type]");
else
error += QLatin1String(QMetaType::typeName(property->propType));
- ctx->engine()->throwError(error);
+ scope.engine->throwError(error);
return;
- } else if (value.asFunctionObject()) {
+ } else if (value.as<FunctionObject>()) {
// this is handled by the binding creation above
} else if (property->propType == QMetaType::Int && value.isNumber()) {
PROPERTY_STORE(int, value.asDouble());
@@ -543,11 +528,11 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
} else {
QVariant v;
if (property->isQList())
- v = ctx->d()->engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
+ v = scope.engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
else
- v = ctx->d()->engine->toVariant(value, property->propType);
+ v = scope.engine->toVariant(value, property->propType);
- QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->d()->engine);
+ QQmlContextData *callingQmlContext = scope.engine->callingQmlContext();
if (!QQmlPropertyPrivate::write(object, *property, v, callingQmlContext)) {
const char *valueType = 0;
if (v.userType() == QVariant::Invalid) valueType = "null";
@@ -561,7 +546,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
QLatin1String(valueType) +
QLatin1String(" to ") +
QLatin1String(targetTypeName);
- ctx->engine()->throwError(error);
+ scope.engine->throwError(error);
return;
}
}
@@ -634,7 +619,7 @@ void QObjectWrapper::markWrapper(QObject *object, ExecutionEngine *engine)
engine->m_multiplyWrappedQObjects->mark(object, engine);
}
-ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx, int propertyIndex, bool captureRequired)
+ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, bool captureRequired)
{
if (QQmlData::wasDeleted(object))
return QV4::Encode::null();
@@ -646,14 +631,19 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
Q_ASSERT(cache);
QQmlPropertyData *property = cache->property(propertyIndex);
Q_ASSERT(property); // We resolved this property earlier, so it better exist!
- return getProperty(object, ctx, property, captureRequired);
+ return getProperty(engine, object, property, captureRequired);
+}
+
+void QObjectWrapper::setProperty(ExecutionEngine *engine, int propertyIndex, const Value &value)
+{
+ setProperty(engine, d()->object, propertyIndex, value);
}
-void QObjectWrapper::setProperty(ExecutionContext *ctx, int propertyIndex, const Value &value)
+void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, const Value &value)
{
- if (QQmlData::wasDeleted(d()->object))
+ if (QQmlData::wasDeleted(object))
return;
- QQmlData *ddata = QQmlData::get(d()->object, /*create*/false);
+ QQmlData *ddata = QQmlData::get(object, /*create*/false);
if (!ddata)
return;
@@ -661,14 +651,14 @@ void QObjectWrapper::setProperty(ExecutionContext *ctx, int propertyIndex, const
Q_ASSERT(cache);
QQmlPropertyData *property = cache->property(propertyIndex);
Q_ASSERT(property); // We resolved this property earlier, so it better exist!
- return setProperty(d()->object, ctx, property, value);
+ return setProperty(engine, object, property, value);
}
bool QObjectWrapper::isEqualTo(Managed *a, Managed *b)
{
Q_ASSERT(a->as<QV4::QObjectWrapper>());
QV4::QObjectWrapper *qobjectWrapper = static_cast<QV4::QObjectWrapper *>(a);
- QV4::Object *o = b->asObject();
+ QV4::Object *o = b->as<Object>();
if (o) {
if (QV4::QmlTypeWrapper *qmlTypeWrapper = o->as<QV4::QmlTypeWrapper>())
return qmlTypeWrapper->toVariant().value<QObject*>() == qobjectWrapper->object();
@@ -681,13 +671,13 @@ ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QObject *object)
{
if (engine->jsEngine())
QQmlData::ensurePropertyCache(engine->jsEngine(), object);
- return (engine->memoryManager->alloc<QV4::QObjectWrapper>(engine, object))->asReturnedValue();
+ return (engine->memoryManager->allocObject<QV4::QObjectWrapper>(object))->asReturnedValue();
}
-QV4::ReturnedValue QObjectWrapper::get(Managed *m, String *name, bool *hasProperty)
+QV4::ReturnedValue QObjectWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
- QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
- QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(that->engine());
+ const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m);
+ QQmlContextData *qmlContext = that->engine()->callingQmlContext();
return that->getQmlProperty(qmlContext, name, IgnoreRevision, hasProperty, /*includeImports*/ true);
}
@@ -699,7 +689,7 @@ void QObjectWrapper::put(Managed *m, String *name, const Value &value)
if (v4->hasException || QQmlData::wasDeleted(that->d()->object))
return;
- QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(v4);
+ QQmlContextData *qmlContext = v4->callingQmlContext();
if (!setQmlProperty(v4, qmlContext, that->d()->object, name, QV4::QObjectWrapper::IgnoreRevision, value)) {
QQmlData *ddata = QQmlData::get(that->d()->object);
// Types created by QML are not extensible at run-time, but for other QObjects we can store them
@@ -718,23 +708,23 @@ PropertyAttributes QObjectWrapper::query(const Managed *m, String *name)
{
const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m);
ExecutionEngine *engine = that->engine();
- QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(engine);
+ QQmlContextData *qmlContext = engine->callingQmlContext();
QQmlPropertyData local;
if (that->findProperty(engine, qmlContext, name, IgnoreRevision, &local)
- || name->equals(engine->id_destroy) || name->equals(engine->id_toString))
+ || name->equals(engine->id_destroy()) || name->equals(engine->id_toString()))
return QV4::Attr_Data;
else
return QV4::Object::query(m, name);
}
-void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes)
+void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
{
// Used to block access to QObject::destroyed() and QObject::deleteLater() from QML
static const int destroyedIdx1 = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)");
static const int destroyedIdx2 = QObject::staticMetaObject.indexOfSignal("destroyed()");
static const int deleteLaterIdx = QObject::staticMetaObject.indexOfSlot("deleteLater()");
- *name = (Heap::String *)0;
+ name->setM(0);
*index = UINT_MAX;
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
@@ -745,10 +735,9 @@ void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Heap::Strin
const bool preventDestruction = mo->superClass() || mo == &QObject::staticMetaObject;
const int propertyCount = mo->propertyCount();
if (it->arrayIndex < static_cast<uint>(propertyCount)) {
- // #### GC
Scope scope(that->engine());
ScopedString propName(scope, that->engine()->newString(QString::fromUtf8(mo->property(it->arrayIndex).name())));
- *name = propName->d();
+ name->setM(propName->d());
++it->arrayIndex;
*attributes = QV4::Attr_Data;
p->value = that->get(propName);
@@ -761,10 +750,9 @@ void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Heap::Strin
++it->arrayIndex;
if (method.access() == QMetaMethod::Private || (preventDestruction && (index == deleteLaterIdx || index == destroyedIdx1 || index == destroyedIdx2)))
continue;
- // #### GC
Scope scope(that->engine());
ScopedString methodName(scope, that->engine()->newString(QString::fromUtf8(method.name())));
- *name = methodName->d();
+ name->setM(methodName->d());
*attributes = QV4::Attr_Data;
p->value = that->get(methodName);
return;
@@ -811,7 +799,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
QV4::ScopedFunctionObject f(scope, This->function.value());
QV4::ScopedCallData callData(scope, argCount);
- callData->thisObject = This->thisObject.isUndefined() ? v4->globalObject()->asReturnedValue() : This->thisObject.value();
+ callData->thisObject = This->thisObject.isUndefined() ? v4->globalObject->asReturnedValue() : This->thisObject.value();
for (int ii = 0; ii < argCount; ++ii) {
int type = argsTypes[ii + 1];
if (type == qMetaTypeId<QVariant>()) {
@@ -826,7 +814,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
QQmlError error = v4->catchExceptionAsQmlError();
if (error.description().isEmpty()) {
QV4::ScopedString name(scope, f->name());
- error.setDescription(QString::fromLatin1("Unknown exception occurred during evaluation of connected function: %1").arg(name->toQString()));
+ error.setDescription(QStringLiteral("Unknown exception occurred during evaluation of connected function: %1").arg(name->toQString()));
}
if (QQmlEngine *qmlEngine = v4->qmlEngine()) {
QQmlEnginePrivate::get(qmlEngine)->warning(error);
@@ -1028,56 +1016,35 @@ void QObjectWrapper::markObjects(Heap::Base *that, QV4::ExecutionEngine *e)
QV4::Object::markObjects(that, e);
}
-namespace {
- struct QObjectDeleter : public QV4::GCDeletable
- {
- QObjectDeleter(QObject *o)
- : m_objectToDelete(o)
- {}
- ~QObjectDeleter()
- {
- QQmlData *ddata = QQmlData::get(m_objectToDelete, false);
- if (ddata && ddata->ownContext && ddata->context)
- ddata->context->emitDestruction();
- // This object is notionally destroyed now
- ddata->isQueuedForDeletion = true;
- if (lastCall)
- delete m_objectToDelete;
- else
- m_objectToDelete->deleteLater();
- }
-
- QObject *m_objectToDelete;
- };
-}
-
-void QObjectWrapper::destroy(Heap::Base *that)
+void QObjectWrapper::destroyObject(bool lastCall)
{
- Heap::QObjectWrapper *This = static_cast<Heap::QObjectWrapper*>(that);
- QPointer<QObject> object = This->object;
- ExecutionEngine *engine = This->internalClass->engine;
- This->~Data();
- This = 0;
- if (!object)
- return;
-
- QQmlData *ddata = QQmlData::get(object, false);
- if (!ddata)
- return;
-
- if (object->parent() || ddata->indestructible)
- return;
+ Heap::QObjectWrapper *h = d();
+ if (!h->internalClass)
+ return; // destroyObject already got called
+
+ if (h->object) {
+ QQmlData *ddata = QQmlData::get(h->object, false);
+ if (ddata) {
+ if (!h->object->parent() && !ddata->indestructible) {
+ if (ddata && ddata->ownContext && ddata->context)
+ ddata->context->emitDestruction();
+ // This object is notionally destroyed now
+ ddata->isQueuedForDeletion = true;
+ if (lastCall)
+ delete h->object;
+ else
+ h->object->deleteLater();
+ }
+ }
+ }
- QObjectDeleter *deleter = new QObjectDeleter(object);
- engine->memoryManager->registerDeletable(deleter);
+ h->internalClass = 0;
+ h->~Data();
}
DEFINE_OBJECT_VTABLE(QObjectWrapper);
-// XXX TODO: Need to review all calls to QQmlEngine *engine() to confirm QObjects work
-// correctly in a worker thread
-
namespace {
template<typename A, typename B, typename C, typename D, typename E,
@@ -1229,7 +1196,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
default:
return 10;
}
- } else if (actual.asDateObject()) {
+ } else if (actual.as<DateObject>()) {
switch (conversionType) {
case QMetaType::QDateTime:
return 0;
@@ -1247,7 +1214,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
default:
return 10;
}
- } else if (actual.asArrayObject()) {
+ } else if (actual.as<ArrayObject>()) {
switch (conversionType) {
case QMetaType::QJsonArray:
return 3;
@@ -1276,7 +1243,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
return 10;
}
}
- } else if (QV4::Object *obj = actual.asObject()) {
+ } else if (const Object *obj = actual.as<Object>()) {
if (obj->as<QV4::VariantObject>()) {
if (conversionType == qMetaTypeId<QVariant>())
return 0;
@@ -1379,7 +1346,7 @@ static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQ
if (returnType == QMetaType::UnknownType) {
QString typeName = QString::fromLatin1(unknownTypeError);
- QString error = QString::fromLatin1("Unknown method return type: %1").arg(typeName);
+ QString error = QStringLiteral("Unknown method return type: %1").arg(typeName);
return engine->throwError(error);
}
@@ -1392,7 +1359,7 @@ static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQ
if (!args) {
QString typeName = QString::fromLatin1(unknownTypeError);
- QString error = QString::fromLatin1("Unknown method parameter type: %1").arg(typeName);
+ QString error = QStringLiteral("Unknown method parameter type: %1").arg(typeName);
return engine->throwError(error);
}
@@ -1606,9 +1573,9 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
type = callType;
} else if (callType == QMetaType::QObjectStar) {
qobjectPtr = 0;
- if (QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
+ if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
qobjectPtr = qobjectWrapper->object();
- else if (QV4::QmlTypeWrapper *qmlTypeWrapper = value.as<QV4::QmlTypeWrapper>())
+ else if (const QV4::QmlTypeWrapper *qmlTypeWrapper = value.as<QV4::QmlTypeWrapper>())
queryEngine = qmlTypeWrapper->isSingleton();
type = callType;
} else if (callType == qMetaTypeId<QVariant>()) {
@@ -1630,7 +1597,7 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
}
} else {
QObject *o = 0;
- if (QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
+ if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
o = qobjectWrapper->object();
qlistPtr->append(o);
}
@@ -1739,29 +1706,26 @@ QV4::ReturnedValue CallArgument::toValue(QV4::ExecutionEngine *engine)
}
}
-ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, int index, const Value &qmlGlobal)
+ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, int index)
{
Scope valueScope(scope);
- Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->alloc<QObjectMethod>(scope));
+ Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->allocObject<QObjectMethod>(scope));
method->d()->object = object;
if (QQmlData *ddata = QQmlData::get(object))
method->d()->propertyCache = ddata->propertyCache;
method->d()->index = index;
- method->d()->qmlGlobal = qmlGlobal;
- method->d()->valueTypeWrapper = Primitive::undefinedValue();
return method.asReturnedValue();
}
-ReturnedValue QObjectMethod::create(ExecutionContext *scope, QQmlValueTypeWrapper *valueType, int index, const Value &qmlGlobal)
+ReturnedValue QObjectMethod::create(ExecutionContext *scope, const QQmlValueTypeWrapper *valueType, int index)
{
Scope valueScope(scope);
- Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->alloc<QObjectMethod>(scope));
+ Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->allocObject<QObjectMethod>(scope));
method->d()->propertyCache = valueType->d()->propertyCache;
method->d()->index = index;
- method->d()->qmlGlobal = qmlGlobal;
- method->d()->valueTypeWrapper = valueType;
+ method->d()->valueTypeWrapper = valueType->d();
return method.asReturnedValue();
}
@@ -1777,7 +1741,7 @@ const QMetaObject *Heap::QObjectMethod::metaObject()
return object->metaObject();
}
-QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx)
+QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) const
{
QString result;
if (const QMetaObject *metaObject = d()->metaObject()) {
@@ -1803,7 +1767,7 @@ QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx)
return ctx->d()->engine->newString(result)->asReturnedValue();
}
-QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc)
+QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc) const
{
if (!d()->object)
return Encode::undefined();
@@ -1822,16 +1786,16 @@ QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, con
return Encode::undefined();
}
-ReturnedValue QObjectMethod::call(Managed *m, CallData *callData)
+ReturnedValue QObjectMethod::call(const Managed *m, CallData *callData)
{
- QObjectMethod *This = static_cast<QObjectMethod*>(m);
+ const QObjectMethod *This = static_cast<const QObjectMethod*>(m);
return This->callInternal(callData);
}
-ReturnedValue QObjectMethod::callInternal(CallData *callData)
+ReturnedValue QObjectMethod::callInternal(CallData *callData) const
{
- Scope scope(engine());
- ScopedContext context(scope, scope.engine->currentContext());
+ ExecutionEngine *v4 = engine();
+ ExecutionContext *context = v4->currentContext;
if (d()->index == DestroyMethod)
return method_destroy(context, callData->args, callData->argc);
else if (d()->index == ToStringMethod)
@@ -1839,11 +1803,10 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
QQmlObjectOrGadget object(d()->object.data());
if (!d()->object) {
- Scoped<QQmlValueTypeWrapper> wrapper(scope, d()->valueTypeWrapper);
- if (!wrapper)
+ if (!d()->valueTypeWrapper)
return Encode::undefined();
- object = QQmlObjectOrGadget(d()->propertyCache.data(), wrapper->d()->gadgetPtr);
+ object = QQmlObjectOrGadget(d()->propertyCache.data(), d()->valueTypeWrapper->gadgetPtr);
}
QQmlPropertyData method;
@@ -1875,12 +1838,9 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
}
if (method.isV4Function()) {
+ Scope scope(v4);
QV4::ScopedValue rv(scope, QV4::Primitive::undefinedValue());
-
- QV4::ScopedValue qmlGlobal(scope, d()->qmlGlobal);
- QQmlV4Function func(callData, rv, qmlGlobal,
- QmlContextWrapper::getContext(qmlGlobal),
- scope.engine);
+ QQmlV4Function func(callData, rv, v4);
QQmlV4Function *funcptr = &func;
void *args[] = { 0, &funcptr };
@@ -1890,32 +1850,46 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
}
if (!method.isOverload()) {
- return CallPrecise(object, method, scope.engine, callData);
+ return CallPrecise(object, method, v4, callData);
} else {
- return CallOverloaded(object, method, scope.engine, callData, d()->propertyCache);
+ return CallOverloaded(object, method, v4, callData, d()->propertyCache);
}
}
void QObjectMethod::markObjects(Heap::Base *that, ExecutionEngine *e)
{
QObjectMethod::Data *This = static_cast<QObjectMethod::Data*>(that);
- This->qmlGlobal.mark(e);
- This->valueTypeWrapper.mark(e);
+ if (This->valueTypeWrapper)
+ This->valueTypeWrapper->mark(e);
FunctionObject::markObjects(that, e);
}
DEFINE_OBJECT_VTABLE(QObjectMethod);
-Heap::QmlSignalHandler::QmlSignalHandler(QV4::ExecutionEngine *engine, QObject *object, int signalIndex)
- : Heap::Object(engine)
- , object(object)
+Heap::QmlSignalHandler::QmlSignalHandler(QObject *object, int signalIndex)
+ : object(object)
, signalIndex(signalIndex)
{
}
DEFINE_OBJECT_VTABLE(QmlSignalHandler);
+void QmlSignalHandler::initProto(ExecutionEngine *engine)
+{
+ if (engine->signalHandlerPrototype()->d())
+ return;
+
+ Scope scope(engine);
+ ScopedObject o(scope, engine->newObject());
+ QV4::ScopedString connect(scope, engine->newIdentifier(QStringLiteral("connect")));
+ QV4::ScopedString disconnect(scope, engine->newIdentifier(QStringLiteral("disconnect")));
+ o->put(connect, QV4::ScopedValue(scope, engine->functionPrototype()->get(connect)));
+ o->put(disconnect, QV4::ScopedValue(scope, engine->functionPrototype()->get(disconnect)));
+
+ engine->jsObjects[QV4::ExecutionEngine::SignalHandlerProto] = o->d();
+}
+
void MultiplyWrappedQObjectMap::insert(QObject *key, Heap::Object *value)
{
QV4::WeakValue v;
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 24e8b29e08..1126013806 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -54,7 +54,7 @@
#include <private/qqmlpropertycache_p.h>
#include <private/qintrusivelist_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
QT_BEGIN_NAMESPACE
@@ -69,8 +69,10 @@ struct QObjectSlotDispatcher;
namespace Heap {
+struct QQmlValueTypeWrapper;
+
struct QObjectWrapper : Object {
- QObjectWrapper(QV4::ExecutionEngine *engine, QObject *object);
+ QObjectWrapper(QObject *object);
QPointer<QObject> object;
};
@@ -79,15 +81,14 @@ struct QObjectMethod : FunctionObject {
QPointer<QObject> object;
QQmlRefPointer<QQmlPropertyCache> propertyCache;
int index;
- Value qmlGlobal;
- Value valueTypeWrapper;
+ Pointer<QQmlValueTypeWrapper> valueTypeWrapper;
const QMetaObject *metaObject();
};
struct QmlSignalHandler : Object {
- QmlSignalHandler(QV4::ExecutionEngine *engine, QObject *object, int signalIndex);
+ QmlSignalHandler(QObject *object, int signalIndex);
QPointer<QObject> object;
int signalIndex;
};
@@ -104,7 +105,7 @@ struct Q_QML_EXPORT QObjectWrapper : public Object
QObject *object() const { return d()->object.data(); }
- ReturnedValue getQmlProperty(QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false);
+ ReturnedValue getQmlProperty(QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false) const;
static ReturnedValue getQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = 0);
static bool setQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, const Value &value);
@@ -114,26 +115,27 @@ struct Q_QML_EXPORT QObjectWrapper : public Object
using Object::get;
- static ReturnedValue getProperty(QObject *object, ExecutionContext *ctx, int propertyIndex, bool captureRequired);
- void setProperty(ExecutionContext *ctx, int propertyIndex, const Value &value);
+ static ReturnedValue getProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, bool captureRequired);
+ static void setProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, const Value &value);
+ void setProperty(ExecutionEngine *engine, int propertyIndex, const Value &value);
+
+ void destroyObject(bool lastCall);
protected:
static bool isEqualTo(Managed *that, Managed *o);
-private:
- static ReturnedValue getProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, bool captureRequired = true);
- static void setProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, const Value &value);
+ static ReturnedValue getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, bool captureRequired = true);
+ static void setProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, const Value &value);
static ReturnedValue create(ExecutionEngine *engine, QObject *object);
QQmlPropertyData *findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const;
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static PropertyAttributes query(const Managed *, String *name);
- static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e);
- static void destroy(Heap::Base *that);
static ReturnedValue method_connect(CallContext *ctx);
static ReturnedValue method_disconnect(CallContext *ctx);
@@ -148,18 +150,18 @@ struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject
enum { DestroyMethod = -1, ToStringMethod = -2 };
- static ReturnedValue create(QV4::ExecutionContext *scope, QObject *object, int index, const Value &qmlGlobal = Primitive::undefinedValue());
- static ReturnedValue create(QV4::ExecutionContext *scope, QQmlValueTypeWrapper *valueType, int index, const Value &qmlGlobal = Primitive::undefinedValue());
+ static ReturnedValue create(QV4::ExecutionContext *scope, QObject *object, int index);
+ static ReturnedValue create(QV4::ExecutionContext *scope, const QQmlValueTypeWrapper *valueType, int index);
int methodIndex() const { return d()->index; }
QObject *object() const { return d()->object.data(); }
- QV4::ReturnedValue method_toString(QV4::ExecutionContext *ctx);
- QV4::ReturnedValue method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc);
+ QV4::ReturnedValue method_toString(QV4::ExecutionContext *ctx) const;
+ QV4::ReturnedValue method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc) const;
- static ReturnedValue call(Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *, CallData *callData);
- ReturnedValue callInternal(CallData *callData);
+ ReturnedValue callInternal(CallData *callData) const;
static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e);
};
@@ -167,10 +169,13 @@ struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject
struct QmlSignalHandler : public QV4::Object
{
V4_OBJECT2(QmlSignalHandler, QV4::Object)
+ V4_PROTOTYPE(signalHandlerPrototype)
V4_NEEDS_DESTROY
int signalIndex() const { return d()->signalIndex; }
QObject *object() const { return d()->object.data(); }
+
+ static void initProto(ExecutionEngine *v4);
};
class MultiplyWrappedQObjectMap : public QObject,
diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp
index 8e18a5fbdd..31fee534ad 100644
--- a/src/qml/jsruntime/qv4regexp.cpp
+++ b/src/qml/jsruntime/qv4regexp.cpp
@@ -34,16 +34,16 @@
#include "qv4regexp_p.h"
#include "qv4engine_p.h"
#include "qv4scopedvalue_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
using namespace QV4;
RegExpCache::~RegExpCache()
{
- for (RegExpCache::Iterator it = begin(), e = end();
- it != e; ++it)
- it.value()->cache = 0;
- clear();
+ for (RegExpCache::Iterator it = begin(), e = end(); it != e; ++it) {
+ if (RegExp *re = it.value().as<RegExp>())
+ re->d()->cache = 0;
+ }
}
DEFINE_MANAGED_VTABLE(RegExp);
@@ -68,19 +68,18 @@ Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bo
RegExpCacheKey key(pattern, ignoreCase, multiline);
RegExpCache *cache = engine->regExpCache;
- if (cache) {
- if (Heap::RegExp *result = cache->value(key))
- return result;
- }
+ if (!cache)
+ cache = engine->regExpCache = new RegExpCache;
+
+ QV4::WeakValue &cachedValue = (*cache)[key];
+ if (QV4::RegExp *result = cachedValue.as<RegExp>())
+ return result->d();
Scope scope(engine);
Scoped<RegExp> result(scope, engine->memoryManager->alloc<RegExp>(engine, pattern, ignoreCase, multiline));
- if (!cache)
- cache = engine->regExpCache = new RegExpCache;
-
result->d()->cache = cache;
- cache->insert(key, result->d());
+ cachedValue.set(engine, result);
return result->d();
}
diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h
index 819e31e5f1..928362a995 100644
--- a/src/qml/jsruntime/qv4regexp_p.h
+++ b/src/qml/jsruntime/qv4regexp_p.h
@@ -33,6 +33,17 @@
#ifndef QV4REGEXP_H
#define QV4REGEXP_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QString>
#include <QVector>
@@ -133,8 +144,7 @@ inline RegExpCacheKey::RegExpCacheKey(const RegExp::Data *re)
inline uint qHash(const RegExpCacheKey& key, uint seed = 0) Q_DECL_NOTHROW
{ return qHash(key.pattern, seed); }
-// ### GC
-class RegExpCache : public QHash<RegExpCacheKey, Heap::RegExp*>
+class RegExpCache : public QHash<RegExpCacheKey, WeakValue>
{
public:
~RegExpCache();
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index f6e88e62b7..1839ff17ab 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -37,7 +37,7 @@
#include "qv4objectproto_p.h"
#include "qv4regexp_p.h"
#include "qv4stringobject_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
@@ -62,35 +62,30 @@ Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyn
using namespace QV4;
DEFINE_OBJECT_VTABLE(RegExpObject);
-DEFINE_OBJECT_VTABLE(RegExpPrototype);
-Heap::RegExpObject::RegExpObject(InternalClass *ic, QV4::Object *prototype)
- : Heap::Object(ic, prototype)
+Heap::RegExpObject::RegExpObject()
{
- Scope scope(ic->engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::RegExpObject> o(scope, this);
- o->d()->value = QV4::RegExp::create(ic->engine, QString(), false, false);
+ o->d()->value = QV4::RegExp::create(scope.engine, QString(), false, false);
o->d()->global = false;
- o->init(ic->engine);
+ o->initProperties();
}
-Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *value, bool global)
- : Heap::Object(engine->emptyClass, engine->regExpPrototype.asObject())
- , value(value->d())
+Heap::RegExpObject::RegExpObject(QV4::RegExp *value, bool global)
+ : value(value->d())
, global(global)
{
- Scope scope(engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::RegExpObject> o(scope, this);
- o->init(engine);
+ o->initProperties();
}
// Converts a QRegExp to a JS RegExp.
// The conversion is not 100% exact since ECMA regexp and QRegExp
// have different semantics/flags, but we try to do our best.
-Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re)
- : Heap::Object(engine->emptyClass, engine->regExpPrototype.asObject())
+Heap::RegExpObject::RegExpObject(const QRegExp &re)
{
- value = 0;
global = false;
// Convert the pattern to a ECMAScript pattern.
@@ -130,26 +125,21 @@ Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re
pattern = ecmaPattern;
}
- Scope scope(engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::RegExpObject> o(scope, this);
- o->d()->value = QV4::RegExp::create(engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false);
+ o->d()->value = QV4::RegExp::create(scope.engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false);
- o->init(engine);
+ o->initProperties();
}
-void RegExpObject::init(ExecutionEngine *engine)
+void RegExpObject::initProperties()
{
- Scope scope(engine);
- ScopedObject protectThis(scope, this);
+ *propertyData(Index_LastIndex) = Primitive::fromInt32(0);
- ScopedString lastIndex(scope, engine->newIdentifier(QStringLiteral("lastIndex")));
- ScopedValue v(scope, Primitive::fromInt32(0));
- insertMember(lastIndex, v, Attr_NotEnumerable|Attr_NotConfigurable);
- if (!this->value())
- return;
+ Q_ASSERT(value());
- QString p = this->value()->pattern;
+ QString p = value()->pattern;
if (p.isEmpty()) {
p = QStringLiteral("(?:)");
} else {
@@ -157,10 +147,10 @@ void RegExpObject::init(ExecutionEngine *engine)
p.replace('/', QLatin1String("\\/"));
}
- defineReadonlyProperty(QStringLiteral("source"), (v = engine->newString(p)));
- defineReadonlyProperty(QStringLiteral("global"), Primitive::fromBoolean(global()));
- defineReadonlyProperty(QStringLiteral("ignoreCase"), Primitive::fromBoolean(this->value()->ignoreCase));
- defineReadonlyProperty(QStringLiteral("multiline"), Primitive::fromBoolean(this->value()->multiLine));
+ *propertyData(Index_Source) = engine()->newString(p);
+ *propertyData(Index_Global) = Primitive::fromBoolean(global());
+ *propertyData(Index_IgnoreCase) = Primitive::fromBoolean(value()->ignoreCase);
+ *propertyData(Index_Multiline) = Primitive::fromBoolean(value()->multiLine);
}
@@ -172,10 +162,10 @@ void RegExpObject::markObjects(Heap::Base *that, ExecutionEngine *e)
Object::markObjects(that, e);
}
-Property *RegExpObject::lastIndexProperty()
+Value *RegExpObject::lastIndexProperty()
{
- Q_ASSERT(0 == internalClass()->find(engine()->id_lastIndex));
- return propertyAt(0);
+ Q_ASSERT(0 == internalClass()->find(engine()->id_lastIndex()));
+ return propertyData(0);
}
// Converts a JS RegExp to a QRegExp.
@@ -231,25 +221,24 @@ Heap::RegExpCtor::RegExpCtor(QV4::ExecutionContext *scope)
void Heap::RegExpCtor::clearLastMatch()
{
lastMatch = Primitive::nullValue();
- lastInput = internalClass->engine->id_empty;
+ lastInput = internalClass->engine->id_empty()->d();
lastMatchStart = 0;
lastMatchEnd = 0;
}
-ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
+ReturnedValue RegExpCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<Object *>(m)->engine());
- ScopedContext ctx(scope, scope.engine->currentContext());
+ Scope scope(static_cast<const Object *>(m)->engine());
ScopedValue r(scope, callData->argument(0));
ScopedValue f(scope, callData->argument(1));
Scoped<RegExpObject> re(scope, r);
if (re) {
if (!f->isUndefined())
- return ctx->engine()->throwTypeError();
+ return scope.engine->throwTypeError();
Scoped<RegExp> regexp(scope, re->value());
- return Encode(ctx->d()->engine->newRegExpObject(regexp, re->global()));
+ return Encode(scope.engine->newRegExpObject(regexp, re->global()));
}
QString pattern;
@@ -274,19 +263,19 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
} else if (str.at(i) == QLatin1Char('m') && !multiLine) {
multiLine = true;
} else {
- return ctx->engine()->throwSyntaxError(QStringLiteral("Invalid flags supplied to RegExp constructor"));
+ return scope.engine->throwSyntaxError(QStringLiteral("Invalid flags supplied to RegExp constructor"));
}
}
}
- Scoped<RegExp> regexp(scope, RegExp::create(ctx->d()->engine, pattern, ignoreCase, multiLine));
+ Scoped<RegExp> regexp(scope, RegExp::create(scope.engine, pattern, ignoreCase, multiLine));
if (!regexp->isValid())
- return ctx->engine()->throwSyntaxError(QStringLiteral("Invalid regular expression"));
+ return scope.engine->throwSyntaxError(QStringLiteral("Invalid regular expression"));
- return Encode(ctx->d()->engine->newRegExpObject(regexp, global));
+ return Encode(scope.engine->newRegExpObject(regexp, global));
}
-ReturnedValue RegExpCtor::call(Managed *that, CallData *callData)
+ReturnedValue RegExpCtor::call(const Managed *that, CallData *callData)
{
if (callData->argc > 0 && callData->args[0].as<RegExpObject>()) {
if (callData->argc == 1 || callData->args[1].isUndefined())
@@ -300,7 +289,7 @@ void RegExpCtor::markObjects(Heap::Base *that, ExecutionEngine *e)
{
RegExpCtor::Data *This = static_cast<RegExpCtor::Data *>(that);
This->lastMatch.mark(e);
- This->lastInput.mark(e);
+ This->lastInput->mark(e);
FunctionObject::markObjects(that, e);
}
@@ -310,8 +299,8 @@ void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor)
ScopedObject o(scope);
ScopedObject ctor(scope, constructor);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(2));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(2));
// Properties deprecated in the spec but required by "the web" :(
ctor->defineAccessorProperty(QStringLiteral("lastMatch"), method_get_lastMatch_n<0>, 0);
@@ -337,7 +326,7 @@ void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor)
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
defineDefaultProperty(QStringLiteral("exec"), method_exec, 1);
defineDefaultProperty(QStringLiteral("test"), method_test, 1);
- defineDefaultProperty(engine->id_toString, method_toString, 0);
+ defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("compile"), method_compile, 2);
}
@@ -354,25 +343,25 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
return Encode::undefined();
QString s = arg->stringValue()->toQString();
- int offset = r->global() ? r->lastIndexProperty()->value.toInt32() : 0;
+ int offset = r->global() ? r->lastIndexProperty()->toInt32() : 0;
if (offset < 0 || offset > s.length()) {
- r->lastIndexProperty()->value = Primitive::fromInt32(0);
+ *r->lastIndexProperty() = Primitive::fromInt32(0);
return Encode::null();
}
uint* matchOffsets = (uint*)alloca(r->value()->captureCount() * 2 * sizeof(uint));
const int result = Scoped<RegExp>(scope, r->value())->match(s, offset, matchOffsets);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor);
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor());
regExpCtor->d()->clearLastMatch();
if (result == -1) {
- r->lastIndexProperty()->value = Primitive::fromInt32(0);
+ *r->lastIndexProperty() = Primitive::fromInt32(0);
return Encode::null();
}
// fill in result data
- ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->regExpExecArrayClass, scope.engine->arrayPrototype.asObject()));
+ ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->regExpExecArrayClass, scope.engine->arrayPrototype()));
int len = r->value()->captureCount();
array->arrayReserve(len);
ScopedValue v(scope);
@@ -383,17 +372,17 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
array->arrayPut(i, v);
}
array->setArrayLengthUnchecked(len);
- array->memberData()->data[Index_ArrayIndex] = Primitive::fromInt32(result);
- array->memberData()->data[Index_ArrayInput] = arg;
+ *array->propertyData(Index_ArrayIndex) = Primitive::fromInt32(result);
+ *array->propertyData(Index_ArrayInput) = arg;
RegExpCtor::Data *dd = regExpCtor->d();
dd->lastMatch = array;
- dd->lastInput = arg->stringValue();
+ dd->lastInput = arg->stringValue()->d();
dd->lastMatchStart = matchOffsets[0];
dd->lastMatchEnd = matchOffsets[1];
if (r->global())
- r->lastIndexProperty()->value = Primitive::fromInt32(matchOffsets[1]);
+ *r->lastIndexProperty() = Primitive::fromInt32(matchOffsets[1]);
return array.asReturnedValue();
}
@@ -425,7 +414,7 @@ ReturnedValue RegExpPrototype::method_compile(CallContext *ctx)
ScopedCallData callData(scope, ctx->argc());
memcpy(callData->args, ctx->args(), ctx->argc()*sizeof(Value));
- Scoped<RegExpObject> re(scope, ctx->d()->engine->regExpCtor.asFunctionObject()->construct(callData));
+ Scoped<RegExpObject> re(scope, ctx->d()->engine->regExpCtor()->as<FunctionObject>()->construct(callData));
r->d()->value = re->value();
r->d()->global = re->global();
@@ -436,7 +425,7 @@ template <int index>
ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx)
{
Scope scope(ctx);
- ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastMatch());
+ ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastMatch());
ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined());
if (result->isUndefined())
return ctx->d()->engine->newString()->asReturnedValue();
@@ -446,7 +435,7 @@ ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx)
ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx)
{
Scope scope(ctx);
- ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastMatch());
+ ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastMatch());
ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined());
if (result->isUndefined())
return ctx->d()->engine->newString()->asReturnedValue();
@@ -455,13 +444,13 @@ ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx)
ReturnedValue RegExpPrototype::method_get_input(CallContext *ctx)
{
- return static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastInput().asReturnedValue();
+ return static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastInput()->asReturnedValue();
}
ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor);
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor());
QString lastInput = regExpCtor->lastInput()->toQString();
return ctx->d()->engine->newString(lastInput.left(regExpCtor->lastMatchStart()))->asReturnedValue();
}
@@ -469,7 +458,7 @@ ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx)
ReturnedValue RegExpPrototype::method_get_rightContext(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor);
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor());
QString lastInput = regExpCtor->lastInput()->toQString();
return ctx->d()->engine->newString(lastInput.mid(regExpCtor->lastMatchEnd()))->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index f5f255faf5..81ea9cf14b 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4REGEXPOBJECT_H
#define QV4REGEXPOBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4runtime_p.h"
#include "qv4engine_p.h"
#include "qv4context_p.h"
@@ -57,33 +68,30 @@ namespace QV4 {
namespace Heap {
struct RegExpObject : Object {
- RegExpObject(InternalClass *ic, QV4::Object *prototype);
- RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *value, bool global);
- RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re);
+ RegExpObject();
+ RegExpObject(QV4::RegExp *value, bool global);
+ RegExpObject(const QRegExp &re);
- RegExp *value;
+ Pointer<RegExp> value;
bool global;
};
struct RegExpCtor : FunctionObject {
RegExpCtor(QV4::ExecutionContext *scope);
Value lastMatch;
- StringValue lastInput;
+ Pointer<String> lastInput;
int lastMatchStart;
int lastMatchEnd;
void clearLastMatch();
};
-struct RegExpPrototype : RegExpObject
-{
- inline RegExpPrototype(ExecutionEngine *e);
-};
-
}
struct RegExpObject: Object {
V4_OBJECT2(RegExpObject, Object)
Q_MANAGED_TYPE(RegExpObject)
+ V4_INTERNALCLASS(regExpObjectClass)
+ V4_PROTOTYPE(regExpPrototype)
// needs to be compatible with the flags in qv4jsir_p.h
enum Flags {
@@ -93,6 +101,11 @@ struct RegExpObject: Object {
};
enum {
+ Index_LastIndex = 0,
+ Index_Source = 1,
+ Index_Global = 2,
+ Index_IgnoreCase = 3,
+ Index_Multiline = 4,
Index_ArrayIndex = Heap::ArrayObject::LengthPropertyIndex + 1,
Index_ArrayInput = Index_ArrayIndex + 1
};
@@ -100,9 +113,9 @@ struct RegExpObject: Object {
Heap::RegExp *value() const { return d()->value; }
bool global() const { return d()->global; }
- void init(ExecutionEngine *engine);
+ void initProperties();
- Property *lastIndexProperty();
+ Value *lastIndexProperty();
QRegExp toQRegExp() const;
QString toString() const;
QString source() const;
@@ -117,19 +130,17 @@ struct RegExpCtor: FunctionObject
V4_OBJECT2(RegExpCtor, FunctionObject)
Value lastMatch() { return d()->lastMatch; }
- StringValue lastInput() { return d()->lastInput; }
+ Heap::String *lastInput() { return d()->lastInput; }
int lastMatchStart() { return d()->lastMatchStart; }
int lastMatchEnd() { return d()->lastMatchEnd; }
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
struct RegExpPrototype: RegExpObject
{
- V4_OBJECT2(RegExpPrototype, RegExpObject)
-
void init(ExecutionEngine *engine, Object *ctor);
static ReturnedValue method_exec(CallContext *ctx);
@@ -145,11 +156,6 @@ struct RegExpPrototype: RegExpObject
static ReturnedValue method_get_rightContext(CallContext *ctx);
};
-inline Heap::RegExpPrototype::RegExpPrototype(ExecutionEngine *e)
- : RegExpObject(e->emptyClass, e->objectPrototype.asObject())
-{
-}
-
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index b66e917b87..a988313f5f 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -40,12 +40,15 @@
#include "qv4stringobject_p.h"
#include "qv4argumentsobject_p.h"
#include "qv4objectiterator_p.h"
+#include "qv4dateobject_p.h"
#include "qv4lookup_p.h"
#include "qv4function_p.h"
#include "private/qlocale_tools_p.h"
#include "qv4scopedvalue_p.h"
#include <private/qqmlcontextwrapper_p.h>
#include <private/qqmltypewrapper_p.h>
+#include <private/qqmlengine_p.h>
+#include <private/qqmljavascriptexpression_p.h>
#include "qv4qobjectwrapper_p.h"
#include <private/qv8engine_p.h>
#endif
@@ -265,10 +268,9 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix)
ReturnedValue Runtime::closure(ExecutionEngine *engine, int functionId)
{
- QV4::Function *clos = engine->currentContext()->compilationUnit->runtimeFunctions[functionId];
+ QV4::Function *clos = engine->current->compilationUnit->runtimeFunctions[functionId];
Q_ASSERT(clos);
- Scope scope(engine);
- return FunctionObject::createScriptFunction(ScopedContext(scope, engine->currentContext()), clos)->asReturnedValue();
+ return FunctionObject::createScriptFunction(engine->currentContext, clos)->asReturnedValue();
}
ReturnedValue Runtime::deleteElement(ExecutionEngine *engine, const Value &base, const Value &index)
@@ -289,7 +291,7 @@ ReturnedValue Runtime::deleteElement(ExecutionEngine *engine, const Value &base,
ReturnedValue Runtime::deleteMember(ExecutionEngine *engine, const Value &base, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
return deleteMemberString(engine, base, name);
}
@@ -305,22 +307,21 @@ ReturnedValue Runtime::deleteMemberString(ExecutionEngine *engine, const Value &
ReturnedValue Runtime::deleteName(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- return Encode(ctx->deleteProperty(name));
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ return Encode(engine->currentContext->deleteProperty(name));
}
QV4::ReturnedValue Runtime::instanceof(ExecutionEngine *engine, const Value &left, const Value &right)
{
Scope scope(engine);
- ScopedFunctionObject f(scope, right.asFunctionObject());
+ ScopedFunctionObject f(scope, right.as<FunctionObject>());
if (!f)
return engine->throwTypeError();
if (f->isBoundFunction())
f = static_cast<BoundFunction *>(f.getPointer())->target();
- ScopedObject v(scope, left.asObject());
+ ScopedObject v(scope, left.as<Object>());
if (!v)
return Encode(false);
@@ -380,10 +381,10 @@ Heap::String *RuntimeHelpers::stringFromNumber(ExecutionEngine *engine, double n
return engine->newString(qstr);
}
-ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint)
+ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeHint)
{
if (typeHint == PREFERREDTYPE_HINT) {
- if (object->asDateObject())
+ if (object->as<DateObject>())
typeHint = STRING_HINT;
else
typeHint = NUMBER_HINT;
@@ -393,18 +394,18 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint)
if (engine->hasException)
return Encode::undefined();
- StringValue *meth1 = &engine->id_toString;
- StringValue *meth2 = &engine->id_valueOf;
+ String *meth1 = engine->id_toString();
+ String *meth2 = engine->id_valueOf();
if (typeHint == NUMBER_HINT)
qSwap(meth1, meth2);
Scope scope(engine);
ScopedCallData callData(scope, 0);
- callData->thisObject = object;
+ callData->thisObject = *object;
- ScopedValue conv(scope, object->get(*meth1));
- if (FunctionObject *o = conv->asFunctionObject()) {
+ ScopedValue conv(scope, object->get(meth1));
+ if (FunctionObject *o = conv->as<FunctionObject>()) {
ScopedValue r(scope, o->call(callData));
if (r->isPrimitive())
return r->asReturnedValue();
@@ -413,8 +414,8 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint)
if (engine->hasException)
return Encode::undefined();
- conv = object->get(*meth2);
- if (FunctionObject *o = conv->asFunctionObject()) {
+ conv = object->get(meth2);
+ if (FunctionObject *o = conv->as<FunctionObject>()) {
ScopedValue r(scope, o->call(callData));
if (r->isPrimitive())
return r->asReturnedValue();
@@ -437,7 +438,7 @@ Heap::Object *RuntimeHelpers::convertToObject(ExecutionEngine *engine, const Val
return engine->newBooleanObject(value.booleanValue());
case Value::Managed_Type:
Q_ASSERT(value.isString());
- return engine->newStringObject(value);
+ return engine->newStringObject(value.stringValue());
case Value::Integer_Type:
default: // double
return engine->newNumberObject(value.asDouble());
@@ -450,14 +451,14 @@ Heap::String *RuntimeHelpers::convertToString(ExecutionEngine *engine, const Val
case Value::Empty_Type:
Q_ASSERT(!"empty Value encountered");
case Value::Undefined_Type:
- return engine->id_undefined->d();
+ return engine->id_undefined()->d();
case Value::Null_Type:
- return engine->id_null->d();
+ return engine->id_null()->d();
case Value::Boolean_Type:
if (value.booleanValue())
- return engine->id_true->d();
+ return engine->id_true()->d();
else
- return engine->id_false->d();
+ return engine->id_false()->d();
case Value::Managed_Type:
if (value.isString())
return value.stringValue()->d();
@@ -467,7 +468,7 @@ Heap::String *RuntimeHelpers::convertToString(ExecutionEngine *engine, const Val
return RuntimeHelpers::convertToString(engine, prim);
}
case Value::Integer_Type:
- return RuntimeHelpers::stringFromNumber(engine, value.int_32);
+ return RuntimeHelpers::stringFromNumber(engine, value.int_32());
default: // double
return RuntimeHelpers::stringFromNumber(engine, value.doubleValue());
} // switch
@@ -481,14 +482,14 @@ static Heap::String *convert_to_string_add(ExecutionEngine *engine, const Value
case Value::Empty_Type:
Q_ASSERT(!"empty Value encountered");
case Value::Undefined_Type:
- return engine->id_undefined->d();
+ return engine->id_undefined()->d();
case Value::Null_Type:
- return engine->id_null->d();
+ return engine->id_null()->d();
case Value::Boolean_Type:
if (value.booleanValue())
- return engine->id_true->d();
+ return engine->id_true()->d();
else
- return engine->id_false->d();
+ return engine->id_false()->d();
case Value::Managed_Type:
if (value.isString())
return value.stringValue()->d();
@@ -498,7 +499,7 @@ static Heap::String *convert_to_string_add(ExecutionEngine *engine, const Value
return RuntimeHelpers::convertToString(engine, prim);
}
case Value::Integer_Type:
- return RuntimeHelpers::stringFromNumber(engine, value.int_32);
+ return RuntimeHelpers::stringFromNumber(engine, value.int_32());
default: // double
return RuntimeHelpers::stringFromNumber(engine, value.doubleValue());
} // switch
@@ -563,7 +564,7 @@ QV4::ReturnedValue Runtime::addString(ExecutionEngine *engine, const Value &left
void Runtime::setProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject o(scope, object.toObject(engine));
if (!o)
return;
@@ -578,7 +579,7 @@ ReturnedValue Runtime::getElement(ExecutionEngine *engine, const Value &object,
ScopedObject o(scope, object);
if (!o) {
if (idx < UINT_MAX) {
- if (String *str = object.asString()) {
+ if (const String *str = object.as<String>()) {
if (idx >= (uint)str->toQString().length()) {
return Encode::undefined();
}
@@ -660,15 +661,14 @@ ReturnedValue Runtime::foreachNextPropertyName(const Value &foreach_iterator)
void Runtime::setActivationProperty(ExecutionEngine *engine, int nameIndex, const Value &value)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- ctx->setProperty(name, value);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ engine->currentContext->setProperty(name, value);
}
ReturnedValue Runtime::getProperty(ExecutionEngine *engine, const Value &object, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject o(scope, object);
if (o)
@@ -688,9 +688,8 @@ ReturnedValue Runtime::getProperty(ExecutionEngine *engine, const Value &object,
ReturnedValue Runtime::getActivationProperty(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- return ctx->getProperty(name);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ return engine->currentContext->getProperty(name);
}
#endif // V4_BOOTSTRAP
@@ -906,13 +905,13 @@ ReturnedValue Runtime::callGlobalLookup(ExecutionEngine *engine, uint index, Cal
Scope scope(engine);
Q_ASSERT(callData->thisObject.isUndefined());
- Lookup *l = engine->currentContext()->lookups + index;
+ Lookup *l = engine->current->lookups + index;
ScopedFunctionObject o(scope, l->globalGetter(l, engine));
if (!o)
return engine->throwTypeError();
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
- if (o->d() == scope.engine->evalFunction && name->equals(scope.engine->id_eval))
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
+ if (o->d() == scope.engine->evalFunction()->d() && name->equals(scope.engine->id_eval()))
return static_cast<EvalFunction *>(o.getPointer())->evalCall(callData, true);
return o->call(callData);
@@ -923,18 +922,17 @@ ReturnedValue Runtime::callActivationProperty(ExecutionEngine *engine, int nameI
{
Q_ASSERT(callData->thisObject.isUndefined());
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject base(scope);
- ScopedContext ctx(scope, engine->currentContext());
- ScopedValue func(scope, ctx->getPropertyAndBase(name, base.getRef()));
+ ScopedValue func(scope, engine->currentContext->getPropertyAndBase(name, base.getRef()));
if (scope.engine->hasException)
return Encode::undefined();
if (base)
callData->thisObject = base;
- FunctionObject *o = func->asFunctionObject();
+ FunctionObject *o = func->as<FunctionObject>();
if (!o) {
QString objectAsString = QStringLiteral("[null]");
if (base)
@@ -943,17 +941,41 @@ ReturnedValue Runtime::callActivationProperty(ExecutionEngine *engine, int nameI
return engine->throwTypeError(msg);
}
- if (o->d() == scope.engine->evalFunction && name->equals(scope.engine->id_eval)) {
+ if (o->d() == scope.engine->evalFunction()->d() && name->equals(scope.engine->id_eval())) {
return static_cast<EvalFunction *>(o)->evalCall(callData, true);
}
return o->call(callData);
}
+ReturnedValue Runtime::callQmlScopeObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData)
+{
+ Scope scope(engine);
+ ScopedFunctionObject o(scope, getQmlScopeObjectProperty(engine, callData->thisObject, propertyIndex));
+ if (!o) {
+ QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(propertyIndex).arg(callData->thisObject.toQStringNoThrow());
+ return engine->throwTypeError(error);
+ }
+
+ return o->call(callData);
+}
+
+ReturnedValue Runtime::callQmlContextObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData)
+{
+ Scope scope(engine);
+ ScopedFunctionObject o(scope, getQmlContextObjectProperty(engine, callData->thisObject, propertyIndex));
+ if (!o) {
+ QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(propertyIndex).arg(callData->thisObject.toQStringNoThrow());
+ return engine->throwTypeError(error);
+ }
+
+ return o->call(callData);
+}
+
ReturnedValue Runtime::callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject baseObject(scope, callData->thisObject);
if (!baseObject) {
Q_ASSERT(!callData->thisObject.isEmpty());
@@ -979,7 +1001,7 @@ ReturnedValue Runtime::callProperty(ExecutionEngine *engine, int nameIndex, Call
ReturnedValue Runtime::callPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData)
{
- Lookup *l = engine->currentContext()->lookups + index;
+ Lookup *l = engine->current->lookups + index;
Value v;
v = l->getter(l, engine, callData->thisObject);
if (!v.isObject())
@@ -1019,7 +1041,7 @@ ReturnedValue Runtime::constructGlobalLookup(ExecutionEngine *engine, uint index
Scope scope(engine);
Q_ASSERT(callData->thisObject.isUndefined());
- Lookup *l = engine->currentContext()->lookups + index;
+ Lookup *l = engine->current->lookups + index;
ScopedObject f(scope, l->globalGetter(l, engine));
if (!f)
return engine->throwTypeError();
@@ -1031,13 +1053,12 @@ ReturnedValue Runtime::constructGlobalLookup(ExecutionEngine *engine, uint index
ReturnedValue Runtime::constructActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData)
{
Scope scope(engine);
- ScopedContext ctx(scope, engine->currentContext());
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedValue func(scope, ctx->getProperty(name));
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedValue func(scope, engine->currentContext->getProperty(name));
if (scope.engine->hasException)
return Encode::undefined();
- Object *f = func->asObject();
+ Object *f = func->as<Object>();
if (!f)
return engine->throwTypeError();
@@ -1046,7 +1067,7 @@ ReturnedValue Runtime::constructActivationProperty(ExecutionEngine *engine, int
ReturnedValue Runtime::constructValue(ExecutionEngine *engine, const Value &func, CallData *callData)
{
- Object *f = func.asObject();
+ const Object *f = func.as<Object>();
if (!f)
return engine->throwTypeError();
@@ -1057,7 +1078,7 @@ ReturnedValue Runtime::constructProperty(ExecutionEngine *engine, int nameIndex,
{
Scope scope(engine);
ScopedObject thisObject(scope, callData->thisObject.toObject(engine));
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
if (scope.engine->hasException)
return Encode::undefined();
@@ -1070,7 +1091,7 @@ ReturnedValue Runtime::constructProperty(ExecutionEngine *engine, int nameIndex,
ReturnedValue Runtime::constructPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData)
{
- Lookup *l = engine->currentContext()->lookups + index;
+ Lookup *l = engine->current->lookups + index;
Value v;
v = l->getter(l, engine, callData->thisObject);
if (!v.isObject())
@@ -1092,24 +1113,24 @@ ReturnedValue Runtime::typeofValue(ExecutionEngine *engine, const Value &value)
ScopedString res(scope);
switch (value.type()) {
case Value::Undefined_Type:
- res = engine->id_undefined;
+ res = engine->id_undefined();
break;
case Value::Null_Type:
- res = engine->id_object;
+ res = engine->id_object();
break;
case Value::Boolean_Type:
- res = engine->id_boolean;
+ res = engine->id_boolean();
break;
case Value::Managed_Type:
if (value.isString())
- res = engine->id_string;
- else if (value.objectValue()->asFunctionObject())
- res = engine->id_function;
+ res = engine->id_string();
+ else if (value.objectValue()->as<FunctionObject>())
+ res = engine->id_function();
else
- res = engine->id_object; // ### implementation-defined
+ res = engine->id_object(); // ### implementation-defined
break;
default:
- res = engine->id_number;
+ res = engine->id_number();
break;
}
return res.asReturnedValue();
@@ -1118,18 +1139,39 @@ ReturnedValue Runtime::typeofValue(ExecutionEngine *engine, const Value &value)
QV4::ReturnedValue Runtime::typeofName(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- ScopedValue prop(scope, ctx->getProperty(name));
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedValue prop(scope, engine->currentContext->getProperty(name));
// typeof doesn't throw. clear any possible exception
scope.engine->hasException = false;
return Runtime::typeofValue(engine, prop);
}
+#ifndef V4_BOOTSTRAP
+ReturnedValue Runtime::typeofScopeObjectProperty(ExecutionEngine *engine, const Value &context,
+ int propertyIndex)
+{
+ Scope scope(engine);
+ ScopedValue prop(scope, getQmlScopeObjectProperty(engine, context, propertyIndex));
+ if (scope.engine->hasException)
+ return Encode::undefined();
+ return Runtime::typeofValue(engine, prop);
+}
+
+ReturnedValue Runtime::typeofContextObjectProperty(ExecutionEngine *engine, const Value &context,
+ int propertyIndex)
+{
+ Scope scope(engine);
+ ScopedValue prop(scope, getQmlContextObjectProperty(engine, context, propertyIndex));
+ if (scope.engine->hasException)
+ return Encode::undefined();
+ return Runtime::typeofValue(engine, prop);
+}
+#endif // V4_BOOTSTRAP
+
QV4::ReturnedValue Runtime::typeofMember(ExecutionEngine *engine, const Value &base, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject obj(scope, base.toObject(engine));
if (scope.engine->hasException)
return Encode::undefined();
@@ -1148,14 +1190,6 @@ QV4::ReturnedValue Runtime::typeofElement(ExecutionEngine *engine, const Value &
return Runtime::typeofValue(engine, prop);
}
-void Runtime::pushWithScope(const Value &o, ExecutionEngine *engine)
-{
- Scope scope(engine);
- ScopedObject obj(scope, o.toObject(engine));
- ScopedContext ctx(scope, engine->currentContext());
- ctx->newWithContext(obj);
-}
-
ReturnedValue Runtime::unwindException(ExecutionEngine *engine)
{
if (!engine->hasException)
@@ -1163,46 +1197,48 @@ ReturnedValue Runtime::unwindException(ExecutionEngine *engine)
return engine->catchException(0);
}
+/* The next three methods are a bit tricky. They can't open up a Scope, as that
+ * would mess up the pushing of the context.
+ *
+ * Instead the push/pop pair acts as a non local scope.
+ */
+void Runtime::pushWithScope(const Value &o, ExecutionEngine *engine)
+{
+ engine->pushContext(engine->currentContext->newWithContext(o.toObject(engine)));
+ Q_ASSERT(engine->jsStackTop = engine->currentContext + 2);
+}
+
void Runtime::pushCatchScope(NoThrowEngine *engine, int exceptionVarNameIndex)
{
- Scope scope(engine);
- ScopedValue v(scope, engine->catchException(0));
- ScopedString exceptionVarName(scope, engine->currentContext()->compilationUnit->runtimeStrings[exceptionVarNameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- ctx->newCatchContext(exceptionVarName, v);
+ ExecutionContext *c = engine->currentContext;
+ engine->pushContext(c->newCatchContext(c->d()->compilationUnit->runtimeStrings[exceptionVarNameIndex], engine->catchException(0)));
+ Q_ASSERT(engine->jsStackTop = engine->currentContext + 2);
}
void Runtime::popScope(ExecutionEngine *engine)
{
+ Q_ASSERT(engine->jsStackTop = engine->currentContext + 2);
engine->popContext();
+ engine->jsStackTop -= 2;
}
void Runtime::declareVar(ExecutionEngine *engine, bool deletable, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- ctx->createMutableBinding(name, deletable);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ engine->currentContext->createMutableBinding(name, deletable);
}
ReturnedValue Runtime::arrayLiteral(ExecutionEngine *engine, Value *values, uint length)
{
- Scope scope(engine);
- ScopedArrayObject a(scope, engine->newArrayObject());
-
- if (length) {
- a->arrayReserve(length);
- a->arrayPut(0, values, length);
- a->setArrayLengthUnchecked(length);
- }
- return a.asReturnedValue();
+ return engine->newArrayObject(values, length)->asReturnedValue();
}
ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags)
{
Scope scope(engine);
- QV4::InternalClass *klass = engine->currentContext()->compilationUnit->runtimeClasses[classId];
- ScopedObject o(scope, engine->newObject(klass, engine->objectPrototype.asObject()));
+ QV4::InternalClass *klass = engine->current->compilationUnit->runtimeClasses[classId];
+ ScopedObject o(scope, engine->newObject(klass, engine->objectPrototype()));
{
bool needSparseArray = arrayGetterSetterCountAndFlags >> 30;
@@ -1211,7 +1247,7 @@ ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value *
}
for (uint i = 0; i < klass->size; ++i)
- o->memberData()->data[i] = *args++;
+ *o->propertyData(i) = *args++;
if (arrayValueCount > 0) {
ScopedValue entry(scope);
@@ -1242,10 +1278,10 @@ ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value *
QV4::ReturnedValue Runtime::setupArgumentsObject(ExecutionEngine *engine)
{
- Q_ASSERT(engine->currentContext()->type >= Heap::ExecutionContext::Type_CallContext);
- Scope scope(engine);
- Scoped<CallContext> c(scope, static_cast<Heap::CallContext *>(engine->currentContext()));
- return (engine->memoryManager->alloc<ArgumentsObject>(c))->asReturnedValue();
+ Q_ASSERT(engine->current->type == Heap::ExecutionContext::Type_CallContext);
+ QV4::CallContext *c = static_cast<QV4::CallContext *>(engine->currentContext);
+ QV4::InternalClass *ic = c->d()->strictMode ? engine->strictArgumentsObjectClass : engine->argumentsObjectClass;
+ return engine->memoryManager->allocObject<ArgumentsObject>(ic, engine->objectPrototype(), c)->asReturnedValue();
}
#endif // V4_BOOTSTRAP
@@ -1329,32 +1365,14 @@ unsigned Runtime::doubleToUInt(const double &d)
#ifndef V4_BOOTSTRAP
-ReturnedValue Runtime::regexpLiteral(ExecutionEngine *engine, int id)
-{
- return engine->currentContext()->compilationUnit->runtimeRegularExpressions[id].asReturnedValue();
-}
-
-ReturnedValue Runtime::getQmlIdArray(NoThrowEngine *engine)
-{
- Q_ASSERT(engine->qmlContextObject());
- Scope scope(engine);
- Scoped<QmlContextWrapper> wrapper(scope, engine->qmlContextObject());
- return wrapper->idObjectsArray();
-}
-
-ReturnedValue Runtime::getQmlContextObject(NoThrowEngine *engine)
+ReturnedValue Runtime::getQmlContext(NoThrowEngine *engine)
{
- QQmlContextData *context = QmlContextWrapper::callingContext(engine);
- if (!context)
- return Encode::undefined();
- return QObjectWrapper::wrap(engine, context->contextObject);
+ return engine->qmlContext()->asReturnedValue();
}
-ReturnedValue Runtime::getQmlScopeObject(NoThrowEngine *engine)
+ReturnedValue Runtime::regexpLiteral(ExecutionEngine *engine, int id)
{
- Scope scope(engine);
- QV4::Scoped<QmlContextWrapper> c(scope, engine->qmlContextObject());
- return QObjectWrapper::wrap(engine, c->getScopeObject());
+ return engine->current->compilationUnit->runtimeRegularExpressions[id].asReturnedValue();
}
ReturnedValue Runtime::getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)
@@ -1365,21 +1383,29 @@ ReturnedValue Runtime::getQmlQObjectProperty(ExecutionEngine *engine, const Valu
engine->throwTypeError(QStringLiteral("Cannot read property of null"));
return Encode::undefined();
}
- ScopedContext ctx(scope, engine->currentContext());
- return QV4::QObjectWrapper::getProperty(wrapper->object(), ctx, propertyIndex, captureRequired);
+ return QV4::QObjectWrapper::getProperty(scope.engine, wrapper->object(), propertyIndex, captureRequired);
}
QV4::ReturnedValue Runtime::getQmlAttachedProperty(ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex)
{
- Scope scope(engine);
- QV4::Scoped<QmlContextWrapper> c(scope, engine->qmlContextObject());
- QObject *scopeObject = c->getScopeObject();
+ QObject *scopeObject = engine->qmlScopeObject();
QObject *attachedObject = qmlAttachedPropertiesObjectById(attachedPropertiesId, scopeObject);
QJSEngine *jsEngine = engine->jsEngine();
QQmlData::ensurePropertyCache(jsEngine, attachedObject);
- ScopedContext ctx(scope, engine->currentContext());
- return QV4::QObjectWrapper::getProperty(attachedObject, ctx, propertyIndex, /*captureRequired*/true);
+ return QV4::QObjectWrapper::getProperty(engine, attachedObject, propertyIndex, /*captureRequired*/true);
+}
+
+ReturnedValue Runtime::getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex)
+{
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->scopeObject, propertyIndex, false);
+}
+
+ReturnedValue Runtime::getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex)
+{
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->context->contextObject, propertyIndex, false);
}
ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)
@@ -1390,8 +1416,34 @@ ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionEngine *engine, c
scope.engine->throwTypeError(QStringLiteral("Cannot read property of null"));
return Encode::undefined();
}
- ScopedContext ctx(scope, engine->currentContext());
- return QV4::QObjectWrapper::getProperty(wrapper->singletonObject(), ctx, propertyIndex, captureRequired);
+ return QV4::QObjectWrapper::getProperty(scope.engine, wrapper->singletonObject(), propertyIndex, captureRequired);
+}
+
+ReturnedValue Runtime::getQmlIdObject(ExecutionEngine *engine, const Value &c, uint index)
+{
+ Scope scope(engine);
+ const QmlContext &qmlContext = static_cast<const QmlContext &>(c);
+ QQmlContextData *context = qmlContext.d()->qml->context;
+ if (!context || index >= (uint)context->idValueCount)
+ return Encode::undefined();
+
+ QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
+ if (ep && ep->propertyCapture)
+ ep->propertyCapture->captureProperty(&context->idValues[index].bindings);
+
+ return QObjectWrapper::wrap(engine, context->idValues[index].data());
+}
+
+void Runtime::setQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)
+{
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ return QV4::QObjectWrapper::setProperty(engine, c.d()->qml->scopeObject, propertyIndex, value);
+}
+
+void Runtime::setQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)
+{
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ return QV4::QObjectWrapper::setProperty(engine, c.d()->qml->context->contextObject, propertyIndex, value);
}
void Runtime::setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value)
@@ -1402,13 +1454,12 @@ void Runtime::setQmlQObjectProperty(ExecutionEngine *engine, const Value &object
engine->throwTypeError(QStringLiteral("Cannot write property of null"));
return;
}
- ScopedContext ctx(scope, engine->currentContext());
- wrapper->setProperty(ctx, propertyIndex, value);
+ wrapper->setProperty(engine, propertyIndex, value);
}
ReturnedValue Runtime::getQmlImportedScripts(NoThrowEngine *engine)
{
- QQmlContextData *context = QmlContextWrapper::callingContext(engine);
+ QQmlContextData *context = engine->callingQmlContext();
if (!context)
return Encode::undefined();
return context->importedScripts.value();
@@ -1417,18 +1468,17 @@ ReturnedValue Runtime::getQmlImportedScripts(NoThrowEngine *engine)
QV4::ReturnedValue Runtime::getQmlSingleton(QV4::NoThrowEngine *engine, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- Scoped<QmlContextWrapper> wrapper(scope, engine->qmlContextObject());
- return wrapper->qmlSingletonWrapper(engine, name);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ return engine->qmlSingletonWrapper(name);
}
void Runtime::convertThisToObject(ExecutionEngine *engine)
{
- Value *t = &engine->currentContext()->callData->thisObject;
+ Value *t = &engine->current->callData->thisObject;
if (t->isObject())
return;
if (t->isNullOrUndefined()) {
- *t = engine->globalObject()->asReturnedValue();
+ *t = engine->globalObject->asReturnedValue();
} else {
*t = t->toObject(engine)->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index f2f90bbc15..0d81edca1e 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -33,9 +33,21 @@
#ifndef QMLJS_RUNTIME_H
#define QMLJS_RUNTIME_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#include "qv4context_p.h"
+#include "qv4engine_p.h"
#include "qv4math_p.h"
#include <QtCore/qnumeric.h>
@@ -90,6 +102,8 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
// call
static ReturnedValue callGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData);
static ReturnedValue callActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData);
+ static ReturnedValue callQmlScopeObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData);
+ static ReturnedValue callQmlContextObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData);
static ReturnedValue callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData);
static ReturnedValue callPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData);
static ReturnedValue callElement(ExecutionEngine *engine, const Value &index, CallData *callData);
@@ -113,6 +127,8 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
// typeof
static ReturnedValue typeofValue(ExecutionEngine *engine, const Value &val);
static ReturnedValue typeofName(ExecutionEngine *engine, int nameIndex);
+ static ReturnedValue typeofScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex);
+ static ReturnedValue typeofContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex);
static ReturnedValue typeofMember(ExecutionEngine *engine, const Value &base, int nameIndex);
static ReturnedValue typeofElement(ExecutionEngine *engine, const Value &base, const Value &index);
@@ -206,19 +222,23 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
static unsigned doubleToUInt(const double &d);
// qml
- static ReturnedValue getQmlIdArray(NoThrowEngine *ctx);
- static ReturnedValue getQmlImportedScripts(NoThrowEngine *ctx);
- static ReturnedValue getQmlContextObject(NoThrowEngine *ctx);
- static ReturnedValue getQmlScopeObject(NoThrowEngine *ctx);
- static ReturnedValue getQmlSingleton(NoThrowEngine *ctx, int nameIndex);
+ static ReturnedValue getQmlContext(NoThrowEngine *engine);
+ static ReturnedValue getQmlImportedScripts(NoThrowEngine *engine);
+ static ReturnedValue getQmlSingleton(NoThrowEngine *engine, int nameIndex);
static ReturnedValue getQmlAttachedProperty(ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex);
+ static ReturnedValue getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex);
+ static ReturnedValue getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex);
static ReturnedValue getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired);
static ReturnedValue getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired);
+ static ReturnedValue getQmlIdObject(ExecutionEngine *engine, const Value &context, uint index);
+
+ static void setQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value);
+ static void setQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value);
static void setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value);
};
struct Q_QML_PRIVATE_EXPORT RuntimeHelpers {
- static ReturnedValue objectDefaultValue(Object *object, int typeHint);
+ static ReturnedValue objectDefaultValue(const Object *object, int typeHint);
static ReturnedValue toPrimitive(const Value &value, int typeHint);
static double stringToNumber(const QString &s);
@@ -243,7 +263,7 @@ struct Q_QML_PRIVATE_EXPORT RuntimeHelpers {
#ifndef V4_BOOTSTRAP
inline ReturnedValue RuntimeHelpers::toPrimitive(const Value &value, int typeHint)
{
- Object *o = value.asObject();
+ const Object *o = value.as<Object>();
if (!o)
return value.asReturnedValue();
return RuntimeHelpers::objectDefaultValue(o, typeHint);
@@ -262,7 +282,7 @@ inline ReturnedValue Runtime::uPlus(const Value &value)
if (value.isNumber())
return value.asReturnedValue();
if (value.integerCompatible())
- return Encode(value.int_32);
+ return Encode(value.int_32());
double n = value.toNumberImpl();
return Encode(n);
@@ -369,6 +389,15 @@ inline ReturnedValue Runtime::div(const Value &left, const Value &right)
{
TRACE2(left, right);
+ if (Value::integerCompatible(left, right)) {
+ int lval = left.integerValue();
+ int rval = right.integerValue();
+ if (rval != 0 && (lval % rval == 0))
+ return Encode(int(lval / rval));
+ else
+ return Encode(double(lval) / rval);
+ }
+
double lval = left.toNumber();
double rval = right.toNumber();
return Primitive::fromDouble(lval / rval).asReturnedValue();
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index 908248f0f0..d7fd44e1d6 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -33,6 +33,17 @@
#ifndef QV4SCOPEDVALUE_P_H
#define QV4SCOPEDVALUE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4engine_p.h"
#include "qv4value_p.h"
#include "qv4persistent_p.h"
@@ -54,18 +65,12 @@ struct ScopedValue;
struct Scope {
inline Scope(ExecutionContext *ctx)
: engine(ctx->d()->engine)
-#ifndef QT_NO_DEBUG
- , size(0)
-#endif
{
mark = engine->jsStackTop;
}
explicit Scope(ExecutionEngine *e)
: engine(e)
-#ifndef QT_NO_DEBUG
- , size(0)
-#endif
{
mark = engine->jsStackTop;
}
@@ -73,6 +78,7 @@ struct Scope {
~Scope() {
#ifndef QT_NO_DEBUG
Q_ASSERT(engine->jsStackTop >= mark);
+ Q_ASSERT(engine->currentContext < mark);
memset(mark, 0, (engine->jsStackTop - mark)*sizeof(Value));
#endif
#ifdef V4_USE_VALGRIND
@@ -82,13 +88,7 @@ struct Scope {
}
Value *alloc(int nValues) {
-#ifndef QT_NO_DEBUG
- size += nValues;
-#endif
- Value *ptr = engine->jsStackTop;
- engine->jsStackTop = ptr + nValues;
- memset(ptr, 0, nValues*sizeof(Value));
- return ptr;
+ return engine->jsAlloca(nValues);
}
bool hasException() const {
@@ -97,9 +97,6 @@ struct Scope {
ExecutionEngine *engine;
Value *mark;
-#ifndef QT_NO_DEBUG
- mutable int size;
-#endif
private:
Q_DISABLE_COPY(Scope)
@@ -110,49 +107,34 @@ struct ScopedValue
ScopedValue(const Scope &scope)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = 0;
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ ptr->setRawValue(0);
}
ScopedValue(const Scope &scope, const Value &v)
{
ptr = scope.engine->jsStackTop++;
*ptr = v;
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
ScopedValue(const Scope &scope, Heap::Base *o)
{
ptr = scope.engine->jsStackTop++;
- ptr->m = o;
-#if QT_POINTER_SIZE == 4
- ptr->tag = QV4::Value::Managed_Type;
-#endif
-#ifndef QT_NO_DEBUG
- ++scope.size;
+ ptr->setM(o);
+#ifndef QV4_USE_64_BIT_VALUE_ENCODING
+ ptr->setTag(QV4::Value::Managed_Type);
#endif
}
ScopedValue(const Scope &scope, Managed *m)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = m->asReturnedValue();
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ ptr->setRawValue(m->asReturnedValue());
}
ScopedValue(const Scope &scope, const ReturnedValue &v)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = v;
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ ptr->setRawValue(v);
}
ScopedValue &operator=(const Value &v) {
@@ -161,9 +143,9 @@ struct ScopedValue
}
ScopedValue &operator=(Heap::Base *o) {
- ptr->m = o;
-#if QT_POINTER_SIZE == 4
- ptr->tag = QV4::Value::Managed_Type;
+ ptr->setM(o);
+#ifndef QV4_USE_64_BIT_VALUE_ENCODING
+ ptr->setTag(QV4::Value::Managed_Type);
#endif
return *this;
}
@@ -174,7 +156,7 @@ struct ScopedValue
}
ScopedValue &operator=(const ReturnedValue &v) {
- ptr->val = v;
+ ptr->setRawValue(v);
return *this;
}
@@ -200,111 +182,78 @@ struct ScopedValue
template<typename T>
struct Scoped
{
- enum _Convert { Convert };
+ enum ConvertType { Convert };
- inline void setPointer(Managed *p) {
- ptr->m = p ? p->m : 0;
-#if QT_POINTER_SIZE == 4
- ptr->tag = QV4::Value::Managed_Type;
+ inline void setPointer(const Managed *p) {
+ ptr->setM(p ? p->m() : 0);
+#ifndef QV4_USE_64_BIT_VALUE_ENCODING
+ ptr->setTag(QV4::Value::Managed_Type);
#endif
}
Scoped(const Scope &scope)
{
ptr = scope.engine->jsStackTop++;
- ptr->m = 0;
-#if QT_POINTER_SIZE == 4
- ptr->tag = QV4::Value::Managed_Type;
-#endif
-#ifndef QT_NO_DEBUG
- ++scope.size;
+ ptr->setM(0);
+#ifndef QV4_USE_64_BIT_VALUE_ENCODING
+ ptr->setTag(QV4::Value::Managed_Type);
#endif
}
- // ### GC FIX casting below to be safe
Scoped(const Scope &scope, const Value &v)
{
ptr = scope.engine->jsStackTop++;
- setPointer(value_cast<T>(v));
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ setPointer(v.as<T>());
}
Scoped(const Scope &scope, Heap::Base *o)
{
Value v;
v = o;
ptr = scope.engine->jsStackTop++;
- setPointer(value_cast<T>(v));
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ setPointer(v.as<T>());
}
Scoped(const Scope &scope, const ScopedValue &v)
{
ptr = scope.engine->jsStackTop++;
- setPointer(value_cast<T>(*v.ptr));
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ setPointer(v.ptr->as<T>());
}
- Scoped(const Scope &scope, const Value &v, _Convert)
+ Scoped(const Scope &scope, const Value &v, ConvertType)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = value_convert<T>(scope.engine, v);
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ ptr->setRawValue(value_convert<T>(scope.engine, v));
}
Scoped(const Scope &scope, const Value *v)
{
ptr = scope.engine->jsStackTop++;
- setPointer(v ? value_cast<T>(*v) : 0);
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ setPointer(v ? v->as<T>() : 0);
}
Scoped(const Scope &scope, T *t)
{
ptr = scope.engine->jsStackTop++;
setPointer(t);
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, typename T::Data *t)
{
ptr = scope.engine->jsStackTop++;
*ptr = t;
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, const ReturnedValue &v)
{
ptr = scope.engine->jsStackTop++;
- setPointer(value_cast<T>(QV4::Value::fromReturnedValue(v)));
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ setPointer(QV4::Value::fromReturnedValue(v).as<T>());
}
- Scoped(const Scope &scope, const ReturnedValue &v, _Convert)
+ Scoped(const Scope &scope, const ReturnedValue &v, ConvertType)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = value_convert<T>(scope.engine, QV4::Value::fromReturnedValue(v));
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ ptr->setRawValue(value_convert<T>(scope.engine, QV4::Value::fromReturnedValue(v)));
}
Scoped<T> &operator=(Heap::Base *o) {
- Value v;
- v = o;
- setPointer(value_cast<T>(v));
+ setPointer(Value::fromHeapObject(o).as<T>());
return *this;
}
Scoped<T> &operator=(typename T::Data *t) {
@@ -312,16 +261,16 @@ struct Scoped
return *this;
}
Scoped<T> &operator=(const Value &v) {
- setPointer(value_cast<T>(v));
+ setPointer(v.as<T>());
return *this;
}
Scoped<T> &operator=(Value *v) {
- setPointer(v ? value_cast<T>(*v) : 0);
+ setPointer(v ? v->as<T>() : 0);
return *this;
}
Scoped<T> &operator=(const ReturnedValue &v) {
- setPointer(value_cast<T>(QV4::Value::fromReturnedValue(v)));
+ setPointer(QV4::Value::fromReturnedValue(v).as<T>());
return *this;
}
@@ -347,21 +296,21 @@ struct Scoped
}
bool operator!() const {
- return !ptr->m;
+ return !ptr->m();
}
operator void *() const {
- return ptr->m;
+ return ptr->m();
}
T *getPointer() {
return ptr->cast<T>();
}
- typename T::Data **getRef() {
- return reinterpret_cast<typename T::Data **>(&ptr->m);
+ Value *getRef() {
+ return ptr;
}
ReturnedValue asReturnedValue() const {
- return ptr->m ? ptr->val : Encode::undefined();
+ return ptr->m() ? ptr->rawValue() : Encode::undefined();
}
Value *ptr;
@@ -390,41 +339,14 @@ struct ScopedCallData {
inline Value &Value::operator =(const ScopedValue &v)
{
- val = v.ptr->val;
+ _val = v.ptr->val();
return *this;
}
template<typename T>
inline Value &Value::operator=(const Scoped<T> &t)
{
- val = t.ptr->val;
- return *this;
-}
-
-template<typename T>
-inline TypedValue<T> &TypedValue<T>::operator =(T *t)
-{
- m = t ? t->m : 0;
-#if QT_POINTER_SIZE == 4
- tag = Managed_Type;
-#endif
- return *this;
-}
-
-template<typename T>
-inline TypedValue<T> &TypedValue<T>::operator =(const Scoped<T> &v)
-{
- m = v.ptr->m;
-#if QT_POINTER_SIZE == 4
- tag = Managed_Type;
-#endif
- return *this;
-}
-
-template<typename T>
-inline TypedValue<T> &TypedValue<T>::operator=(const TypedValue<T> &t)
-{
- val = t.val;
+ _val = t.ptr->val();
return *this;
}
@@ -447,29 +369,18 @@ struct ScopedProperty
struct ExecutionContextSaver
{
ExecutionEngine *engine;
- Value *savedContext;
+ ExecutionContext *savedContext;
- ExecutionContextSaver(Scope &scope, ExecutionContext *context)
- : engine(context->d()->engine)
- , savedContext(scope.alloc(1))
+ ExecutionContextSaver(Scope &scope)
+ : engine(scope.engine)
{
- savedContext->m = context->d();
-#if QT_POINTER_SIZE == 4
- savedContext->tag = QV4::Value::Managed_Type;
-#endif
- }
- ExecutionContextSaver(Scope &scope, Heap::ExecutionContext *context)
- : engine(context->engine)
- , savedContext(scope.alloc(1))
- {
- savedContext->m = context;
-#if QT_POINTER_SIZE == 4
- savedContext->tag = QV4::Value::Managed_Type;
-#endif
+ savedContext = engine->currentContext;
}
~ExecutionContextSaver()
{
- engine->current = static_cast<Heap::ExecutionContext *>(savedContext->heapObject());
+ Q_ASSERT(engine->jsStackTop > engine->currentContext);
+ engine->currentContext = savedContext;
+ engine->current = savedContext->d();
}
};
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 4fde0e2445..7f2f22780e 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -32,11 +32,12 @@
****************************************************************************/
#include "qv4script_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4functionobject_p.h"
#include "qv4function_p.h"
#include "qv4context_p.h"
#include "qv4debugging_p.h"
+#include "qv4profiling_p.h"
#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
@@ -44,6 +45,7 @@
#include <private/qqmljsparser_p.h>
#include <private/qqmljsast_p.h>
#include <private/qqmlengine_p.h>
+#include <private/qv4profiling_p.h>
#include <qv4jsir_p.h>
#include <qv4codegen_p.h>
#include <private/qqmlcontextwrapper_p.h>
@@ -57,11 +59,15 @@ namespace QV4 {
namespace Heap {
struct CompilationUnitHolder : Object {
- inline CompilationUnitHolder(ExecutionEngine *engine, CompiledData::CompilationUnit *unit);
+ inline CompilationUnitHolder(CompiledData::CompilationUnit *unit);
QQmlRefPointer<CompiledData::CompilationUnit> unit;
};
+struct QmlBindingWrapper : FunctionObject {
+ QmlBindingWrapper(QV4::QmlContext *scope, Function *f);
+};
+
}
struct CompilationUnitHolder : public Object
@@ -71,12 +77,17 @@ struct CompilationUnitHolder : public Object
};
inline
-Heap::CompilationUnitHolder::CompilationUnitHolder(ExecutionEngine *engine, CompiledData::CompilationUnit *unit)
- : Heap::Object(engine)
- , unit(unit)
+Heap::CompilationUnitHolder::CompilationUnitHolder(CompiledData::CompilationUnit *unit)
+ : unit(unit)
{
}
+struct QmlBindingWrapper : FunctionObject {
+ V4_OBJECT2(QmlBindingWrapper, FunctionObject)
+
+ static ReturnedValue call(const Managed *that, CallData *callData);
+};
+
}
QT_END_NAMESPACE
@@ -86,117 +97,52 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlBindingWrapper);
DEFINE_OBJECT_VTABLE(CompilationUnitHolder);
-Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::Object *qml)
- : Heap::FunctionObject(scope, scope->d()->engine->id_eval, /*createProto = */ false)
- , qml(qml->d())
+Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::QmlContext *scope, Function *f)
+ : Heap::FunctionObject(scope, scope->d()->engine->id_eval(), /*createProto = */ false)
{
Q_ASSERT(scope->inUse());
function = f;
if (function)
function->compilationUnit->addref();
-
- Scope s(scope);
- Scoped<QV4::QmlBindingWrapper> o(s, this);
-
- o->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(1));
-
- ScopedContext ctx(s, s.engine->currentContext());
- o->d()->qmlContext = ctx->newQmlContext(o, qml);
- s.engine->popContext();
}
-Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::Object *qml)
- : Heap::FunctionObject(scope, scope->d()->engine->id_eval, /*createProto = */ false)
- , qml(qml->d())
+ReturnedValue QmlBindingWrapper::call(const Managed *that, CallData *callData)
{
- Q_ASSERT(scope->inUse());
-
- Scope s(scope);
- Scoped<QV4::QmlBindingWrapper> o(s, this);
-
- o->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(1));
-
- ScopedContext ctx(s, s.engine->currentContext());
- o->d()->qmlContext = ctx->newQmlContext(o, qml);
- s.engine->popContext();
-}
+ const QmlBindingWrapper *This = static_cast<const QmlBindingWrapper *>(that);
+ ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
+ if (v4->hasException)
+ return Encode::undefined();
+ CHECK_STACK_LIMITS(v4);
-ReturnedValue QmlBindingWrapper::call(Managed *that, CallData *)
-{
- ExecutionEngine *engine = static_cast<Object *>(that)->engine();
- CHECK_STACK_LIMITS(engine);
+ Scope scope(v4);
+ ExecutionContextSaver ctxSaver(scope);
- Scope scope(engine);
- QmlBindingWrapper *This = static_cast<QmlBindingWrapper *>(that);
- if (!This->function())
+ QV4::Function *f = This->function();
+ if (!f)
return QV4::Encode::undefined();
- Scoped<CallContext> ctx(scope, This->d()->qmlContext);
- std::fill(ctx->d()->locals, ctx->d()->locals + ctx->d()->function->varCount(), Primitive::undefinedValue());
- engine->pushContext(ctx);
- ScopedValue result(scope, This->function()->code(engine, This->function()->codeData));
- engine->popContext();
+ Scoped<CallContext> ctx(scope, v4->currentContext->newCallContext(This, callData));
+ v4->pushContext(ctx);
- return result->asReturnedValue();
-}
-
-void QmlBindingWrapper::markObjects(Heap::Base *m, ExecutionEngine *e)
-{
- QmlBindingWrapper::Data *wrapper = static_cast<QmlBindingWrapper::Data *>(m);
- if (wrapper->qml)
- wrapper->qml->mark(e);
- FunctionObject::markObjects(m, e);
- if (wrapper->qmlContext)
- wrapper->qmlContext->mark(e);
-}
-
-static ReturnedValue signalParameterGetter(QV4::CallContext *ctx, uint parameterIndex)
-{
- QV4::Scope scope(ctx);
- QV4::Scoped<CallContext> signalEmittingContext(scope, static_cast<Heap::CallContext *>(ctx->d()->parent));
- Q_ASSERT(signalEmittingContext && signalEmittingContext->d()->type >= QV4::Heap::ExecutionContext::Type_SimpleCallContext);
- return signalEmittingContext->argument(parameterIndex);
-}
+ ScopedValue result(scope, Q_V4_PROFILE(v4, f));
-Heap::FunctionObject *QmlBindingWrapper::createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, Function *runtimeFunction, const QList<QByteArray> &signalParameters, QString *error)
-{
- ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(qmlContext->engine);
- QV4::Scope valueScope(engine);
- QV4::ScopedObject qmlScopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(engine, qmlContext, scopeObject));
- ScopedContext global(valueScope, valueScope.engine->rootContext());
- QV4::Scoped<QV4::QmlBindingWrapper> wrapper(valueScope, engine->memoryManager->alloc<QV4::QmlBindingWrapper>(global, qmlScopeObject));
- QV4::Scoped<CallContext> wrapperContext(valueScope, wrapper->context());
-
- if (!signalParameters.isEmpty()) {
- if (error)
- QQmlPropertyCache::signalParameterStringForJS(engine, signalParameters, error);
- QV4::ScopedProperty p(valueScope);
- QV4::ScopedString s(valueScope);
- int index = 0;
- foreach (const QByteArray &param, signalParameters) {
- QV4::ScopedFunctionObject g(valueScope, engine->memoryManager->alloc<QV4::IndexedBuiltinFunction>(wrapperContext, index++, signalParameterGetter));
- p->setGetter(g);
- p->setSetter(0);
- s = engine->newString(QString::fromUtf8(param));
- qmlScopeObject->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
- }
- }
-
- QV4::ScopedFunctionObject function(valueScope, QV4::FunctionObject::createScriptFunction(wrapperContext, runtimeFunction));
- return function->d();
+ return result->asReturnedValue();
}
-Script::Script(ExecutionEngine *v4, Object *qml, CompiledData::CompilationUnit *compilationUnit)
+Script::Script(ExecutionEngine *v4, QmlContext *qml, CompiledData::CompilationUnit *compilationUnit)
: line(0), column(0), scope(v4->rootContext()), strictMode(false), inheritContext(true), parsed(false)
- , qml(v4, qml), vmFunction(0), parseAsBinding(true)
+ , vmFunction(0), parseAsBinding(true)
{
+ if (qml)
+ qmlContext.set(v4, *qml);
+
parsed = true;
vmFunction = compilationUnit ? compilationUnit->linkToEngine(v4) : 0;
if (vmFunction) {
Scope valueScope(v4);
- ScopedObject holder(valueScope, v4->memoryManager->alloc<CompilationUnitHolder>(v4, compilationUnit));
+ ScopedObject holder(valueScope, v4->memoryManager->allocObject<CompilationUnitHolder>(compilationUnit));
compilationUnitHolder.set(v4, holder);
}
}
@@ -214,7 +160,7 @@ void Script::parse()
parsed = true;
- ExecutionEngine *v4 = scope->engine;
+ ExecutionEngine *v4 = scope->engine();
Scope valueScope(v4);
MemoryManager::GCBlocker gcBlocker(v4->memoryManager);
@@ -267,7 +213,7 @@ void Script::parse()
isel->setUseFastLookups(false);
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = isel->compile();
vmFunction = compilationUnit->linkToEngine(v4);
- ScopedObject holder(valueScope, v4->memoryManager->alloc<CompilationUnitHolder>(v4, compilationUnit));
+ ScopedObject holder(valueScope, v4->memoryManager->allocObject<CompilationUnitHolder>(compilationUnit));
compilationUnitHolder.set(v4, holder);
}
@@ -285,23 +231,22 @@ ReturnedValue Script::run()
if (!vmFunction)
return Encode::undefined();
- QV4::ExecutionEngine *engine = scope->engine;
+ QV4::ExecutionEngine *engine = scope->engine();
QV4::Scope valueScope(engine);
- if (qml.isUndefined()) {
+ if (qmlContext.isUndefined()) {
TemporaryAssignment<Function*> savedGlobalCode(engine->globalCode, vmFunction);
- ExecutionContextSaver ctxSaver(valueScope, scope);
+ ExecutionContextSaver ctxSaver(valueScope);
ContextStateSaver stateSaver(valueScope, scope);
- scope->strictMode = vmFunction->isStrict();
- scope->lookups = vmFunction->compilationUnit->runtimeLookups;
- scope->compilationUnit = vmFunction->compilationUnit;
+ scope->d()->strictMode = vmFunction->isStrict();
+ scope->d()->lookups = vmFunction->compilationUnit->runtimeLookups;
+ scope->d()->compilationUnit = vmFunction->compilationUnit;
- return vmFunction->code(engine, vmFunction->codeData);
+ return Q_V4_PROFILE(engine, vmFunction);
} else {
- ScopedObject qmlObj(valueScope, qml.value());
- ScopedContext ctx(valueScope, scope);
- ScopedFunctionObject f(valueScope, engine->memoryManager->alloc<QmlBindingWrapper>(ctx, vmFunction, qmlObj));
+ Scoped<QmlContext> qml(valueScope, qmlContext.value());
+ ScopedFunctionObject f(valueScope, engine->memoryManager->allocObject<QmlBindingWrapper>(qml, vmFunction));
ScopedCallData callData(valueScope);
callData->thisObject = Primitive::undefinedValue();
return f->call(callData);
@@ -376,18 +321,17 @@ ReturnedValue Script::qmlBinding()
{
if (!parsed)
parse();
- ExecutionEngine *v4 = scope->engine;
+ ExecutionEngine *v4 = scope->engine();
Scope valueScope(v4);
- ScopedObject qmlObj(valueScope, qml.value());
- ScopedContext ctx(valueScope, scope);
- ScopedObject v(valueScope, v4->memoryManager->alloc<QmlBindingWrapper>(ctx, vmFunction, qmlObj));
+ Scoped<QmlContext> qml(valueScope, qmlContext.value());
+ ScopedObject v(valueScope, v4->memoryManager->allocObject<QmlBindingWrapper>(qml, vmFunction));
return v.asReturnedValue();
}
-QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject)
+QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &script, QmlContext *qmlContext)
{
QV4::Scope scope(engine);
- QV4::Script qmlScript(engine, scopeObject, script, QString());
+ QV4::Script qmlScript(engine, qmlContext, script, QString());
qmlScript.parse();
QV4::ScopedValue result(scope);
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index 05a9e45f45..4fecf62082 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -33,9 +33,21 @@
#ifndef QV4SCRIPT_H
#define QV4SCRIPT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4engine_p.h"
#include "qv4functionobject_p.h"
+#include "qv4context_p.h"
#include <QQmlError>
@@ -63,7 +75,7 @@ struct ContextStateSaver {
, compilationUnit(context->d()->compilationUnit)
, lineNumber(context->d()->lineNumber)
{
- savedContext->m = context->d();
+ savedContext->setM(context->d());
}
ContextStateSaver(Scope &scope, Heap::ExecutionContext *context)
: savedContext(scope.alloc(1))
@@ -72,12 +84,12 @@ struct ContextStateSaver {
, compilationUnit(context->compilationUnit)
, lineNumber(context->lineNumber)
{
- savedContext->m = context;
+ savedContext->setM(context);
}
~ContextStateSaver()
{
- Heap::ExecutionContext *ctx = static_cast<Heap::ExecutionContext *>(savedContext->m);
+ Heap::ExecutionContext *ctx = static_cast<Heap::ExecutionContext *>(savedContext->m());
ctx->strictMode = strictMode;
ctx->lookups = lookups;
ctx->compilationUnit = compilationUnit;
@@ -85,52 +97,29 @@ struct ContextStateSaver {
}
};
-namespace Heap {
-struct QmlBindingWrapper : Heap::FunctionObject {
- QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::Object *qml);
- // Constructor for QML functions and signal handlers, resulting binding wrapper is not callable!
- QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::Object *qml);
- Object *qml;
- CallContext *qmlContext;
-};
-
-}
-
-struct Q_QML_EXPORT QmlBindingWrapper : FunctionObject {
- V4_OBJECT2(QmlBindingWrapper, FunctionObject)
-
- static ReturnedValue call(Managed *that, CallData *);
- static void markObjects(Heap::Base *m, ExecutionEngine *e);
-
- Heap::CallContext *context() const { return d()->qmlContext; }
-
- static Heap::FunctionObject *createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction,
- const QList<QByteArray> &signalParameters = QList<QByteArray>(), QString *error = 0);
-
-private:
-};
-
struct Q_QML_EXPORT Script {
Script(ExecutionContext *scope, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
- , scope(scope->d()), strictMode(false), inheritContext(false), parsed(false)
+ , scope(scope), strictMode(false), inheritContext(false), parsed(false)
, vmFunction(0), parseAsBinding(false) {}
- Script(ExecutionEngine *engine, Object *qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
+ Script(ExecutionEngine *engine, QmlContext *qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
, scope(engine->rootContext()), strictMode(false), inheritContext(true), parsed(false)
- , qml(engine, qml), vmFunction(0), parseAsBinding(true) {}
- Script(ExecutionEngine *engine, Object *qml, CompiledData::CompilationUnit *compilationUnit);
+ , vmFunction(0), parseAsBinding(true) {
+ if (qml)
+ qmlContext.set(engine, *qml);
+ }
+ Script(ExecutionEngine *engine, QmlContext *qml, CompiledData::CompilationUnit *compilationUnit);
~Script();
QString sourceFile;
int line;
int column;
QString sourceCode;
- // ### GC
- Heap::ExecutionContext *scope;
+ ExecutionContext *scope;
bool strictMode;
bool inheritContext;
bool parsed;
- QV4::PersistentValue qml;
+ QV4::PersistentValue qmlContext;
QV4::PersistentValue compilationUnitHolder;
Function *vmFunction;
bool parseAsBinding;
@@ -144,7 +133,7 @@ struct Q_QML_EXPORT Script {
static QQmlRefPointer<CompiledData::CompilationUnit> precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source,
QList<QQmlError> *reportedErrors = 0, QQmlJS::Directives *directivesCollector = 0);
- static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject);
+ static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, QmlContext *qmlContext);
};
}
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index f1f546bece..36ee848d00 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -175,7 +175,7 @@ template <> QUrl convertValueToElement(const Value &value)
template <> QModelIndex convertValueToElement(const Value &value)
{
- const QQmlValueTypeWrapper *v = value_cast<QQmlValueTypeWrapper>(value);
+ const QQmlValueTypeWrapper *v = value.as<QQmlValueTypeWrapper>();
if (v)
return v->toVariant().toModelIndex();
return QModelIndex();
@@ -183,7 +183,7 @@ template <> QModelIndex convertValueToElement(const Value &value)
template <> QItemSelectionRange convertValueToElement(const Value &value)
{
- const QQmlValueTypeWrapper *v = value_cast<QQmlValueTypeWrapper>(value);
+ const QQmlValueTypeWrapper *v = value.as<QQmlValueTypeWrapper>();
if (v)
return v->toVariant().value<QItemSelectionRange>();
return QItemSelectionRange();
@@ -207,8 +207,8 @@ namespace Heap {
template <typename Container>
struct QQmlSequence : Object {
- QQmlSequence(QV4::ExecutionEngine *engine, const Container &container);
- QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex);
+ QQmlSequence(const Container &container);
+ QQmlSequence(QObject *object, int propertyIndex);
mutable Container container;
QPointer<QObject> object;
@@ -223,6 +223,7 @@ struct QQmlSequence : public QV4::Object
{
V4_OBJECT2(QQmlSequence<Container>, QV4::Object)
Q_MANAGED_TYPE(QmlSequence)
+ V4_PROTOTYPE(sequencePrototype)
V4_NEEDS_DESTROY
public:
@@ -231,7 +232,7 @@ public:
defineAccessorProperty(QStringLiteral("length"), method_get_length, method_set_length);
}
- QV4::ReturnedValue containerGetIndexed(uint index, bool *hasProperty)
+ QV4::ReturnedValue containerGetIndexed(uint index, bool *hasProperty) const
{
/* Qt containers have int (rather than uint) allowable indexes. */
if (index > INT_MAX) {
@@ -316,9 +317,9 @@ public:
return (signedIdx < d()->container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid;
}
- void containerAdvanceIterator(ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
+ void containerAdvanceIterator(ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{
- *name = (Heap::String *)0;
+ name->setM(0);
*index = UINT_MAX;
if (d()->isReference) {
@@ -400,7 +401,7 @@ public:
ScopedCallData callData(scope, 2);
callData->args[0] = convertElementToValue(this->m_ctx->d()->engine, lhs);
callData->args[1] = convertElementToValue(this->m_ctx->d()->engine, rhs);
- callData->thisObject = this->m_ctx->d()->engine->globalObject();
+ callData->thisObject = this->m_ctx->d()->engine->globalObject;
QV4::ScopedValue result(scope, compare->call(callData));
return result->toNumber() < 0;
}
@@ -419,7 +420,7 @@ public:
}
QV4::Scope scope(ctx);
- if (ctx->argc() == 1 && ctx->args()[0].asFunctionObject()) {
+ if (ctx->argc() == 1 && ctx->args()[0].as<FunctionObject>()) {
CompareFunctor cf(ctx, ctx->args()[0]);
std::sort(d()->container.begin(), d()->container.end(), cf);
} else {
@@ -526,8 +527,8 @@ public:
QMetaObject::metacall(d()->object, QMetaObject::WriteProperty, d()->propertyIndex, a);
}
- static QV4::ReturnedValue getIndexed(QV4::Managed *that, uint index, bool *hasProperty)
- { return static_cast<QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty); }
+ static QV4::ReturnedValue getIndexed(const QV4::Managed *that, uint index, bool *hasProperty)
+ { return static_cast<const QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty); }
static void putIndexed(Managed *that, uint index, const QV4::Value &value)
{ static_cast<QQmlSequence<Container> *>(that)->containerPutIndexed(index, value); }
static QV4::PropertyAttributes queryIndexed(const QV4::Managed *that, uint index)
@@ -536,33 +537,31 @@ public:
{ return static_cast<QQmlSequence<Container> *>(that)->containerDeleteIndexedProperty(index); }
static bool isEqualTo(Managed *that, Managed *other)
{ return static_cast<QQmlSequence<Container> *>(that)->containerIsEqualTo(other); }
- static void advanceIterator(Managed *that, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
+ static void advanceIterator(Managed *that, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{ return static_cast<QQmlSequence<Container> *>(that)->containerAdvanceIterator(it, name, index, p, attrs); }
};
template <typename Container>
-Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, const Container &container)
- : Heap::Object(engine->emptyClass, engine->sequencePrototype.asObject())
- , container(container)
+Heap::QQmlSequence<Container>::QQmlSequence(const Container &container)
+ : container(container)
, propertyIndex(-1)
, isReference(false)
{
- QV4::Scope scope(engine);
+ QV4::Scope scope(internalClass->engine);
QV4::Scoped<QV4::QQmlSequence<Container> > o(scope, this);
o->setArrayType(Heap::ArrayData::Custom);
o->init();
}
template <typename Container>
-Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex)
- : Heap::Object(engine->emptyClass, engine->sequencePrototype.asObject())
- , object(object)
+Heap::QQmlSequence<Container>::QQmlSequence(QObject *object, int propertyIndex)
+ : object(object)
, propertyIndex(propertyIndex)
, isReference(true)
{
- QV4::Scope scope(engine);
+ QV4::Scope scope(internalClass->engine);
QV4::Scoped<QV4::QQmlSequence<Container> > o(scope, this);
o->setArrayType(Heap::ArrayData::Custom);
o->loadReference();
@@ -605,7 +604,7 @@ void SequencePrototype::init()
{
FOREACH_QML_SEQUENCE_TYPE(REGISTER_QML_SEQUENCE_METATYPE)
defineDefaultProperty(QStringLiteral("sort"), method_sort, 1);
- defineDefaultProperty(engine()->id_valueOf, method_valueOf, 0);
+ defineDefaultProperty(engine()->id_valueOf(), method_valueOf, 0);
}
#undef REGISTER_QML_SEQUENCE_METATYPE
@@ -644,7 +643,7 @@ bool SequencePrototype::isSequenceType(int sequenceTypeId)
#define NEW_REFERENCE_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
if (sequenceType == qMetaTypeId<SequenceType>()) { \
- QV4::ScopedObject obj(scope, engine->memoryManager->alloc<QQml##ElementTypeName##List>(engine, object, propertyIndex)); \
+ QV4::ScopedObject obj(scope, engine->memoryManager->allocObject<QQml##ElementTypeName##List>(object, propertyIndex)); \
return obj.asReturnedValue(); \
} else
@@ -662,7 +661,7 @@ ReturnedValue SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int s
#define NEW_COPY_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
if (sequenceType == qMetaTypeId<SequenceType>()) { \
- QV4::ScopedObject obj(scope, engine->memoryManager->alloc<QQml##ElementTypeName##List>(engine, v.value<SequenceType >())); \
+ QV4::ScopedObject obj(scope, engine->memoryManager->allocObject<QQml##ElementTypeName##List>(v.value<SequenceType >())); \
return obj.asReturnedValue(); \
} else
@@ -700,11 +699,11 @@ QVariant SequencePrototype::toVariant(const QV4::Value &array, int typeHint, boo
{
*succeeded = true;
- if (!array.asArrayObject()) {
+ if (!array.as<ArrayObject>()) {
*succeeded = false;
return QVariant();
}
- QV4::Scope scope(array.asObject()->engine());
+ QV4::Scope scope(array.as<Object>()->engine());
QV4::ScopedArrayObject a(scope, array);
FOREACH_QML_SEQUENCE_TYPE(SEQUENCE_TO_VARIANT) { /* else */ *succeeded = false; return QVariant(); }
@@ -717,7 +716,7 @@ QVariant SequencePrototype::toVariant(const QV4::Value &array, int typeHint, boo
return qMetaTypeId<SequenceType>(); \
} else
-int SequencePrototype::metaTypeForSequence(QV4::Object *object)
+int SequencePrototype::metaTypeForSequence(const QV4::Object *object)
{
FOREACH_QML_SEQUENCE_TYPE(MAP_META_TYPE)
/*else*/ {
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index 9949278a89..560c3c27ca 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -48,9 +48,10 @@
#include <QtCore/qglobal.h>
#include <QtCore/qvariant.h>
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#include "qv4object_p.h"
#include "qv4context_p.h"
+#include "qv4string_p.h"
QT_BEGIN_NAMESPACE
@@ -70,7 +71,7 @@ struct SequencePrototype : public QV4::Object
static bool isSequenceType(int sequenceTypeId);
static ReturnedValue newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded);
static ReturnedValue fromVariant(QV4::ExecutionEngine *engine, const QVariant& v, bool *succeeded);
- static int metaTypeForSequence(Object *object);
+ 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/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp
index 31d85df13e..33b40796a4 100644
--- a/src/qml/jsruntime/qv4serialize.cpp
+++ b/src/qml/jsruntime/qv4serialize.cpp
@@ -37,7 +37,7 @@
#include <private/qqmllistmodel_p.h>
#include <private/qqmllistmodelworkeragent_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4dateobject_p.h>
#include <private/qv4regexpobject_p.h>
#include <private/qv4sequenceobject_p.h>
@@ -168,11 +168,11 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
char *buffer = data.data() + offset;
memcpy(buffer, qstr.constData(), length*sizeof(QChar));
- } else if (v.asFunctionObject()) {
+ } else if (v.as<FunctionObject>()) {
// XXX TODO: Implement passing function objects between the main and
// worker scripts
push(data, valueheader(WorkerUndefined));
- } else if (QV4::ArrayObject *array = v.asArrayObject()) {
+ } else if (const QV4::ArrayObject *array = v.as<ArrayObject>()) {
uint length = array->getLength();
if (length > 0xFFFFFF) {
push(data, valueheader(WorkerUndefined));
@@ -195,11 +195,11 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
reserve(data, sizeof(quint32) + sizeof(double));
push(data, valueheader(WorkerNumber));
push(data, v.asDouble());
- } else if (QV4::DateObject *d = v.asDateObject()) {
+ } else if (const QV4::DateObject *d = v.as<DateObject>()) {
reserve(data, sizeof(quint32) + sizeof(double));
push(data, valueheader(WorkerDate));
- push(data, d->date().asDouble());
- } else if (RegExpObject *re = v.as<RegExpObject>()) {
+ push(data, d->date());
+ } else if (const RegExpObject *re = v.as<RegExpObject>()) {
quint32 flags = re->flags();
QString pattern = re->source();
int length = pattern.length() + 1;
@@ -218,7 +218,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
char *buffer = data.data() + offset;
memcpy(buffer, pattern.constData(), length*sizeof(QChar));
- } else if (QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) {
+ } else if (const QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) {
// XXX TODO: Generalize passing objects between the main thread and worker scripts so
// that others can trivially plug in their elements.
QQmlListModel *lm = qobject_cast<QQmlListModel *>(qobjectWrapper->object());
@@ -231,10 +231,10 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
}
// No other QObject's are allowed to be sent
push(data, valueheader(WorkerUndefined));
- } else if (Object *o = v.asObject()) {
+ } else if (const Object *o = v.as<Object>()) {
if (o->isListType()) {
// valid sequence. we generate a length (sequence length + 1 for the sequence type)
- uint seqLength = ScopedValue(scope, o->get(engine->id_length))->toUInt32();
+ uint seqLength = ScopedValue(scope, o->get(engine->id_length()))->toUInt32();
uint length = seqLength + 1;
if (length > 0xFFFFFF) {
push(data, valueheader(WorkerUndefined));
@@ -265,7 +265,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
s = properties->getIndexed(ii);
serialize(data, s, engine);
- QV4::String *str = s->asString();
+ QV4::String *str = s->as<String>();
val = o->get(str);
if (scope.hasException())
scope.engine->catchException();
@@ -356,7 +356,7 @@ ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine)
QVariant var = qVariantFromValue(ref);
QV4::ScopedValue v(scope, scope.engine->fromVariant(var));
QV4::ScopedString s(scope, engine->newString(QStringLiteral("__qml:hidden:ref")));
- rv->asObject()->defineReadonlyProperty(s, v);
+ rv->as<Object>()->defineReadonlyProperty(s, v);
agent->release();
agent->setEngine(engine);
diff --git a/src/qml/jsruntime/qv4serialize_p.h b/src/qml/jsruntime/qv4serialize_p.h
index 06eaffe4c4..d5d48edee7 100644
--- a/src/qml/jsruntime/qv4serialize_p.h
+++ b/src/qml/jsruntime/qv4serialize_p.h
@@ -46,7 +46,7 @@
//
#include <QtCore/qbytearray.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4sparsearray.cpp b/src/qml/jsruntime/qv4sparsearray.cpp
index 01f94eeac6..bb1d3aeb69 100644
--- a/src/qml/jsruntime/qv4sparsearray.cpp
+++ b/src/qml/jsruntime/qv4sparsearray.cpp
@@ -246,15 +246,12 @@ void SparseArray::deleteNode(SparseArrayNode *z)
x->setParent(y->parent());
if (root == y)
root = x;
- else if (y->parent()->left == y) {
+ else if (y->parent()->left == y)
y->parent()->left = x;
- if (x)
- x->size_left += y->size_left;
- } else {
+ else
y->parent()->right = x;
- if (x)
- x->size_left += y->size_left;
- }
+ if (x && x == y->right)
+ x->size_left += y->size_left;
y->size_left = 0;
}
if (y->color() != SparseArrayNode::Red) {
diff --git a/src/qml/jsruntime/qv4sparsearray_p.h b/src/qml/jsruntime/qv4sparsearray_p.h
index 861c7dd28d..136f26a25c 100644
--- a/src/qml/jsruntime/qv4sparsearray_p.h
+++ b/src/qml/jsruntime/qv4sparsearray_p.h
@@ -34,12 +34,19 @@
#ifndef QV4SPARSEARRAY_H
#define QV4SPARSEARRAY_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
-#include <QtCore/qmap.h>
-#include "qv4value_inl_p.h"
-#include "qv4scopedvalue_p.h"
-#include "qv4property_p.h"
-#include <assert.h>
+#include <QtCore/qlist.h>
//#define Q_MAP_DEBUG
#ifdef Q_MAP_DEBUG
@@ -188,7 +195,7 @@ public:
typedef qptrdiff difference_type;
typedef int size_type;
-#ifndef QT_NO_DEBUG
+#ifdef Q_MAP_DEBUG
void dump() const;
#endif
};
@@ -261,7 +268,7 @@ inline void SparseArray::push_back(uint index, uint len)
n->value = index;
}
-#ifndef QT_NO_DEBUG
+#ifdef Q_MAP_DEBUG
inline void SparseArray::dump() const
{
const SparseArrayNode *it = begin();
@@ -344,4 +351,4 @@ inline SparseArrayNode *SparseArray::upperBound(uint akey)
QT_END_NAMESPACE
-#endif // QMAP_H
+#endif
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index 6d55eb2c18..24a13ddd10 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -32,7 +32,7 @@
****************************************************************************/
#include "qv4string_p.h"
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#ifndef V4_BOOTSTRAP
#include "qv4identifiertable_p.h"
#include "qv4runtime_p.h"
@@ -110,7 +110,7 @@ bool String::isEqualTo(Managed *t, Managed *o)
if (t == o)
return true;
- if (!o->d()->vtable->isString)
+ if (!o->d()->vtable()->isString)
return false;
return static_cast<String *>(t)->isEqualTo(static_cast<String *>(o));
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index 1cf8f51a29..85433369fc 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -33,6 +33,17 @@
#ifndef QV4STRING_H
#define QV4STRING_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qstring.h>
#include "qv4managed_p.h"
@@ -188,6 +199,20 @@ public:
static uint toArrayIndex(const QString &str);
};
+template<>
+inline const String *Value::as() const {
+ return isManaged() && m() && m()->vtable()->isString ? static_cast<const String *>(this) : 0;
+}
+
+#ifndef V4_BOOTSTRAP
+template<>
+inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v)
+{
+ return v.toString(e)->asReturnedValue();
+}
+#endif
+
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index e0b84f6da3..757ec6c6bf 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -36,7 +36,7 @@
#include "qv4regexp_p.h"
#include "qv4regexpobject_p.h"
#include "qv4objectproto_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4scopedvalue_p.h"
#include "qv4alloca_p.h"
#include <QtCore/QDateTime>
@@ -67,68 +67,62 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(StringObject);
-Heap::StringObject::StringObject(InternalClass *ic, QV4::Object *prototype)
- : Heap::Object(ic, prototype)
+Heap::StringObject::StringObject()
{
- Q_ASSERT(vtable == QV4::StringObject::staticVTable());
- value = ic->engine->newString()->asReturnedValue();
- tmpProperty.value = Primitive::undefinedValue();
-
- Scope scope(ic->engine);
- ScopedObject s(scope, this);
- s->defineReadonlyProperty(ic->engine->id_length, Primitive::fromInt32(0));
+ Q_ASSERT(vtable() == QV4::StringObject::staticVTable());
+ string = internalClass->engine->id_empty()->d();
+ *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0);
}
-Heap::StringObject::StringObject(ExecutionEngine *engine, const Value &val)
- : Heap::Object(engine->emptyClass, engine->stringPrototype.asObject())
+Heap::StringObject::StringObject(const QV4::String *str)
{
- value = val;
- Q_ASSERT(value.isString());
- tmpProperty.value = Primitive::undefinedValue();
-
- Scope scope(engine);
- ScopedObject s(scope, this);
- s->defineReadonlyProperty(engine->id_length, Primitive::fromUInt32(value.stringValue()->toQString().length()));
+ string = str->d();
+ *propertyData(LengthPropertyIndex) = Primitive::fromInt32(length());
}
-Property *Heap::StringObject::getIndex(uint index) const
+Heap::String *Heap::StringObject::getIndex(uint index) const
{
- QString str = value.stringValue()->toQString();
+ QString str = string->toQString();
if (index >= (uint)str.length())
return 0;
- tmpProperty.value = Encode(internalClass->engine->newString(str.mid(index, 1)));
- return &tmpProperty;
+ return internalClass->engine->newString(str.mid(index, 1));
+}
+
+uint Heap::StringObject::length() const
+{
+ return string->len;
}
bool StringObject::deleteIndexedProperty(Managed *m, uint index)
{
ExecutionEngine *v4 = static_cast<StringObject *>(m)->engine();
Scope scope(v4);
- Scoped<StringObject> o(scope, m->asStringObject());
+ Scoped<StringObject> o(scope, m->as<StringObject>());
Q_ASSERT(!!o);
- if (index < static_cast<uint>(o->d()->value.stringValue()->toQString().length())) {
- if (v4->currentContext()->strictMode)
+ if (index < static_cast<uint>(o->d()->string->toQString().length())) {
+ if (v4->current->strictMode)
v4->throwTypeError();
return false;
}
return true;
}
-void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
+void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{
- *name = (Heap::String *)0;
+ name->setM(0);
StringObject *s = static_cast<StringObject *>(m);
- uint slen = s->d()->value.stringValue()->toQString().length();
+ uint slen = s->d()->string->toQString().length();
if (it->arrayIndex <= slen) {
while (it->arrayIndex < slen) {
*index = it->arrayIndex;
++it->arrayIndex;
PropertyAttributes a;
- Property *pd = s->__getOwnProperty__(*index, &a);
+ Property pd;
+ s->getOwnProperty(*index, &a, &pd);
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
*attrs = a;
- p->copy(pd, a);
+ p->copy(&pd, a);
return;
}
}
@@ -146,8 +140,7 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Heap::String
void StringObject::markObjects(Heap::Base *that, ExecutionEngine *e)
{
StringObject::Data *o = static_cast<StringObject::Data *>(that);
- o->value.stringValue()->mark(e);
- o->tmpProperty.value.mark(e);
+ o->string->mark(e);
Object::markObjects(that, e);
}
@@ -158,11 +151,11 @@ Heap::StringCtor::StringCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue StringCtor::construct(Managed *m, CallData *callData)
+ReturnedValue StringCtor::construct(const Managed *m, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(m)->engine();
Scope scope(v4);
- ScopedValue value(scope);
+ ScopedString value(scope);
if (callData->argc)
value = callData->args[0].toString(v4);
else
@@ -170,9 +163,9 @@ ReturnedValue StringCtor::construct(Managed *m, CallData *callData)
return Encode(v4->newStringObject(value));
}
-ReturnedValue StringCtor::call(Managed *m, CallData *callData)
+ReturnedValue StringCtor::call(const Managed *m, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(m)->engine();
Scope scope(v4);
ScopedValue value(scope);
if (callData->argc)
@@ -187,13 +180,13 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor)
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineDefaultProperty(QStringLiteral("fromCharCode"), method_fromCharCode, 1);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString);
- defineDefaultProperty(engine->id_valueOf, method_toString); // valueOf and toString are identical
+ defineDefaultProperty(engine->id_toString(), method_toString);
+ defineDefaultProperty(engine->id_valueOf(), method_toString); // valueOf and toString are identical
defineDefaultProperty(QStringLiteral("charAt"), method_charAt, 1);
defineDefaultProperty(QStringLiteral("charCodeAt"), method_charCodeAt, 1);
defineDefaultProperty(QStringLiteral("concat"), method_concat, 1);
@@ -220,8 +213,8 @@ static QString getThisString(ExecutionContext *ctx)
ScopedValue t(scope, ctx->thisObject());
if (t->isString())
return t->stringValue()->toQString();
- if (StringObject *thisString = t->asStringObject())
- return thisString->d()->value.stringValue()->toQString();
+ if (StringObject *thisString = t->as<StringObject>())
+ return thisString->d()->string->toQString();
if (t->isUndefined() || t->isNull()) {
scope.engine->throwTypeError();
return QString();
@@ -234,10 +227,10 @@ ReturnedValue StringPrototype::method_toString(CallContext *context)
if (context->thisObject().isString())
return context->thisObject().asReturnedValue();
- StringObject *o = context->thisObject().asStringObject();
+ StringObject *o = context->thisObject().as<StringObject>();
if (!o)
return context->engine()->throwTypeError();
- return o->d()->value.asReturnedValue();
+ return Encode(o->d()->string);
}
ReturnedValue StringPrototype::method_charAt(CallContext *context)
@@ -368,7 +361,7 @@ ReturnedValue StringPrototype::method_match(CallContext *context)
if (!rx) {
ScopedCallData callData(scope, 1);
callData->args[0] = regexp;
- rx = context->d()->engine->regExpCtor.asFunctionObject()->construct(callData);
+ rx = context->d()->engine->regExpCtor()->construct(callData);
}
if (!rx)
@@ -379,7 +372,7 @@ ReturnedValue StringPrototype::method_match(CallContext *context)
// ### use the standard builtin function, not the one that might be redefined in the proto
ScopedString execString(scope, scope.engine->newString(QStringLiteral("exec")));
- ScopedFunctionObject exec(scope, scope.engine->regExpPrototype.asObject()->get(execString));
+ ScopedFunctionObject exec(scope, scope.engine->regExpPrototype()->get(execString));
ScopedCallData callData(scope, 1);
callData->thisObject = rx;
@@ -470,8 +463,8 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
{
Scope scope(ctx);
QString string;
- if (StringObject *thisString = ctx->thisObject().asStringObject())
- string = thisString->d()->value.stringValue()->toQString();
+ if (StringObject *thisString = ctx->thisObject().as<StringObject>())
+ string = thisString->d()->string->toQString();
else
string = ctx->thisObject().toQString();
@@ -481,12 +474,12 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
uint allocatedMatchOffsets = 64;
uint _matchOffsets[64];
uint *matchOffsets = _matchOffsets;
- uint nMatchOffsets = 0;
ScopedValue searchValue(scope, ctx->argument(0));
Scoped<RegExpObject> regExp(scope, searchValue);
if (regExp) {
uint offset = 0;
+ uint nMatchOffsets = 0;
// We extract the pointer here to work around a compiler bug on Android.
Scoped<RegExp> re(scope, regExp->value());
@@ -510,7 +503,7 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
offset = qMax(offset + 1, matchOffsets[oldSize + 1]);
}
if (regExp->global())
- regExp->lastIndexProperty()->value = Primitive::fromUInt32(0);
+ *regExp->lastIndexProperty() = Primitive::fromUInt32(0);
numStringMatches = nMatchOffsets / (regExp->value()->captureCount() * 2);
numCaptures = regExp->value()->captureCount();
} else {
@@ -519,7 +512,6 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
int idx = string.indexOf(searchString);
if (idx != -1) {
numStringMatches = 1;
- nMatchOffsets = 2;
matchOffsets[0] = idx;
matchOffsets[1] = idx + searchString.length();
}
@@ -593,7 +585,7 @@ ReturnedValue StringPrototype::method_search(CallContext *ctx)
if (!regExp) {
ScopedCallData callData(scope, 1);
callData->args[0] = regExpValue;
- regExpValue = ctx->d()->engine->regExpCtor.asFunctionObject()->construct(callData);
+ regExpValue = ctx->d()->engine->regExpCtor()->construct(callData);
if (scope.engine->hasException)
return Encode::undefined();
regExp = regExpValue->as<RegExpObject>();
diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h
index 459dc1322e..7d4f78d3c5 100644
--- a/src/qml/jsruntime/qv4stringobject_p.h
+++ b/src/qml/jsruntime/qv4stringobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4STRINGOBJECT_P_H
#define QV4STRINGOBJECT_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include <QtCore/qnumeric.h>
@@ -44,13 +55,16 @@ namespace QV4 {
namespace Heap {
struct StringObject : Object {
- StringObject(InternalClass *ic, QV4::Object *prototype);
- StringObject(ExecutionEngine *engine, const Value &value);
- Value value;
+ enum {
+ LengthPropertyIndex = 0
+ };
+
+ StringObject();
+ StringObject(const QV4::String *string);
+ String *string;
- Property *getIndex(uint index) const;
- // ### get rid of tmpProperty
- mutable Property tmpProperty;
+ Heap::String *getIndex(uint index) const;
+ uint length() const;
};
struct StringCtor : FunctionObject {
@@ -62,15 +76,20 @@ struct StringCtor : FunctionObject {
struct StringObject: Object {
V4_OBJECT2(StringObject, Object)
Q_MANAGED_TYPE(StringObject)
+ V4_INTERNALCLASS(stringClass)
+ V4_PROTOTYPE(stringPrototype)
- Property *getIndex(uint index) const {
+ Heap::String *getIndex(uint index) const {
return d()->getIndex(index);
}
+ uint length() const {
+ return d()->length();
+ }
static bool deleteIndexedProperty(Managed *m, uint index);
protected:
- static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
@@ -78,8 +97,8 @@ struct StringCtor: FunctionObject
{
V4_OBJECT2(StringCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct StringPrototype: StringObject
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index 19e541dba8..b45bbb713c 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -32,6 +32,7 @@
****************************************************************************/
#include "qv4typedarray_p.h"
#include "qv4arraybuffer_p.h"
+#include "qv4string_p.h"
#include <cmath>
@@ -201,10 +202,10 @@ Heap::TypedArrayCtor::TypedArrayCtor(QV4::ExecutionContext *scope, TypedArray::T
{
}
-ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
+ReturnedValue TypedArrayCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<Object *>(m)->engine());
- Scoped<TypedArrayCtor> that(scope, static_cast<TypedArrayCtor *>(m));
+ Scope scope(static_cast<const Object *>(m)->engine());
+ Scoped<TypedArrayCtor> that(scope, static_cast<const TypedArrayCtor *>(m));
if (!callData->argc || !callData->args[0].isObject()) {
// ECMA 6 22.2.1.1
@@ -215,11 +216,11 @@ ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
if (l != len)
scope.engine->throwRangeError(QStringLiteral("Non integer length for typed array."));
uint byteLength = len * operations[that->d()->type].bytesPerElement;
- Scoped<ArrayBuffer> buffer(scope, scope.engine->memoryManager->alloc<ArrayBuffer>(scope.engine, byteLength));
+ Scoped<ArrayBuffer> buffer(scope, scope.engine->newArrayBuffer(byteLength));
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<TypedArray > array(scope, scope.engine->memoryManager->alloc<TypedArray>(scope.engine, that->d()->type));
+ Scoped<TypedArray > array(scope, TypedArray::create(scope.engine, that->d()->type));
array->d()->buffer = buffer->d();
array->d()->byteLength = byteLength;
array->d()->byteOffset = 0;
@@ -235,11 +236,11 @@ ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
uint byteLength = typedArray->d()->byteLength;
uint destByteLength = byteLength*destElementSize/srcElementSize;
- Scoped<ArrayBuffer> newBuffer(scope, scope.engine->memoryManager->alloc<ArrayBuffer>(scope.engine, destByteLength));
+ Scoped<ArrayBuffer> newBuffer(scope, scope.engine->newArrayBuffer(destByteLength));
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<TypedArray > array(scope, scope.engine->memoryManager->alloc<TypedArray>(scope.engine, that->d()->type));
+ Scoped<TypedArray > array(scope, TypedArray::create(scope.engine, that->d()->type));
array->d()->buffer = newBuffer->d();
array->d()->byteLength = destByteLength;
array->d()->byteOffset = 0;
@@ -257,7 +258,7 @@ ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
TypedArrayWrite write =array->d()->type->write;
for (uint i = 0; i < l; ++i) {
Primitive val;
- val.val = read(src, i*srcElementSize);
+ val.setRawValue(read(src, i*srcElementSize));
write(scope.engine, dest, i*destElementSize, val);
}
}
@@ -289,7 +290,7 @@ ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
byteLength = (uint)l;
}
- Scoped<TypedArray > array(scope, scope.engine->memoryManager->alloc<TypedArray>(scope.engine, that->d()->type));
+ Scoped<TypedArray > array(scope, TypedArray::create(scope.engine, that->d()->type));
array->d()->buffer = buffer->d();
array->d()->byteLength = byteLength;
array->d()->byteOffset = byteOffset;
@@ -299,16 +300,16 @@ ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
// ECMA 6 22.2.1.3
ScopedObject o(scope, callData->argument(0));
- uint l = (uint) qBound(0., ScopedValue(scope, o->get(scope.engine->id_length))->toInteger(), (double)UINT_MAX);
+ uint l = (uint) qBound(0., ScopedValue(scope, o->get(scope.engine->id_length()))->toInteger(), (double)UINT_MAX);
if (scope.engine->hasException)
return scope.engine->throwTypeError();
uint elementSize = operations[that->d()->type].bytesPerElement;
- Scoped<ArrayBuffer> newBuffer(scope, scope.engine->memoryManager->alloc<ArrayBuffer>(scope.engine, l * elementSize));
+ Scoped<ArrayBuffer> newBuffer(scope, scope.engine->newArrayBuffer(l * elementSize));
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<TypedArray > array(scope, scope.engine->memoryManager->alloc<TypedArray>(scope.engine, that->d()->type));
+ Scoped<TypedArray > array(scope, TypedArray::create(scope.engine, that->d()->type));
array->d()->buffer = newBuffer->d();
array->d()->byteLength = l * elementSize;
array->d()->byteOffset = 0;
@@ -329,28 +330,32 @@ ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
return array.asReturnedValue();
}
-ReturnedValue TypedArrayCtor::call(Managed *that, CallData *callData)
+ReturnedValue TypedArrayCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
-Heap::TypedArray::TypedArray(ExecutionEngine *e, Type t)
- : Heap::Object(e->emptyClass, e->typedArrayPrototype[t].asObject()),
- type(operations + t),
+Heap::TypedArray::TypedArray(Type t)
+ : type(operations + t),
arrayType(t)
{
}
+Heap::TypedArray *TypedArray::create(ExecutionEngine *e, Heap::TypedArray::Type t)
+{
+ return e->memoryManager->allocObject<TypedArray>(e->emptyClass, e->typedArrayPrototype + t, t);
+}
+
void TypedArray::markObjects(Heap::Base *that, ExecutionEngine *e)
{
static_cast<TypedArray::Data *>(that)->buffer->mark(e);
Object::markObjects(that, e);
}
-ReturnedValue TypedArray::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue TypedArray::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
- Scope scope(static_cast<Object *>(m)->engine());
- Scoped<TypedArray> a(scope, static_cast<TypedArray *>(m));
+ Scope scope(static_cast<const Object *>(m)->engine());
+ Scoped<TypedArray> a(scope, static_cast<const TypedArray *>(m));
uint bytesPerElement = a->d()->type->bytesPerElement;
uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
@@ -382,7 +387,7 @@ void TypedArray::putIndexed(Managed *m, uint index, const Value &value)
return;
reject:
- if (scope.engine->currentContext()->strictMode)
+ if (scope.engine->current->strictMode)
scope.engine->throwTypeError();
}
@@ -390,10 +395,10 @@ void TypedArrayPrototype::init(ExecutionEngine *engine, TypedArrayCtor *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(3));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(3));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
ctor->defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Primitive::fromInt32(operations[ctor->d()->type].bytesPerElement));
- defineDefaultProperty(engine->id_constructor, (o = ctor));
+ defineDefaultProperty(engine->id_constructor(), (o = ctor));
defineAccessorProperty(QStringLiteral("buffer"), method_get_buffer, 0);
defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, 0);
defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, 0);
@@ -470,7 +475,7 @@ ReturnedValue TypedArrayPrototype::method_set(CallContext *ctx)
if (scope.engine->hasException || !o)
return scope.engine->throwTypeError();
- double len = ScopedValue(scope, o->get(scope.engine->id_length))->toNumber();
+ double len = ScopedValue(scope, o->get(scope.engine->id_length()))->toNumber();
uint l = (uint)len;
if (scope.engine->hasException || l != len)
return scope.engine->throwTypeError();
@@ -523,7 +528,7 @@ ReturnedValue TypedArrayPrototype::method_set(CallContext *ctx)
TypedArrayWrite write = a->d()->type->write;
for (uint i = 0; i < l; ++i) {
Primitive val;
- val.val = read(src, i*srcElementSize);
+ val.setRawValue(read(src, i*srcElementSize));
write(scope.engine, dest, i*elementSize, val);
}
@@ -563,7 +568,7 @@ ReturnedValue TypedArrayPrototype::method_subarray(CallContext *ctx)
int newLen = end - begin;
- ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor));
+ ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor()));
if (!constructor)
return scope.engine->throwTypeError();
diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h
index afd1bb97e7..67e04c8ac0 100644
--- a/src/qml/jsruntime/qv4typedarray_p.h
+++ b/src/qml/jsruntime/qv4typedarray_p.h
@@ -33,6 +33,17 @@
#ifndef QV4TYPEDARRAY_H
#define QV4TYPEDARRAY_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include "qv4arraybuffer_p.h"
@@ -69,10 +80,10 @@ struct TypedArray : Object {
NTypes
};
- TypedArray(ExecutionEngine *e, Type t);
+ TypedArray(Type t);
const TypedArrayOperations *type;
- ArrayBuffer *buffer;
+ Pointer<ArrayBuffer> buffer;
uint byteLength;
uint byteOffset;
Type arrayType;
@@ -85,7 +96,7 @@ struct TypedArrayCtor : FunctionObject {
};
struct TypedArrayPrototype : Object {
- inline TypedArrayPrototype(ExecutionEngine *e, TypedArray::Type t);
+ inline TypedArrayPrototype(TypedArray::Type t);
TypedArray::Type type;
};
@@ -96,6 +107,8 @@ struct Q_QML_PRIVATE_EXPORT TypedArray : Object
{
V4_OBJECT2(TypedArray, Object)
+ static Heap::TypedArray *create(QV4::ExecutionEngine *e, Heap::TypedArray::Type t);
+
uint byteLength() const {
return d()->byteLength;
}
@@ -113,7 +126,7 @@ struct Q_QML_PRIVATE_EXPORT TypedArray : Object
}
static void markObjects(Heap::Base *that, ExecutionEngine *e);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static void putIndexed(Managed *m, uint index, const Value &value);
};
@@ -121,8 +134,8 @@ struct TypedArrayCtor: FunctionObject
{
V4_OBJECT2(TypedArrayCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
@@ -142,9 +155,8 @@ struct TypedArrayPrototype : Object
};
inline
-Heap::TypedArrayPrototype::TypedArrayPrototype(ExecutionEngine *e, TypedArray::Type t)
- : Heap::Object(e)
- , type(t)
+Heap::TypedArrayPrototype::TypedArrayPrototype(TypedArray::Type t)
+ : type(t)
{
}
diff --git a/src/qml/jsruntime/qv4util_p.h b/src/qml/jsruntime/qv4util_p.h
index f9ae37855e..329831f134 100644
--- a/src/qml/jsruntime/qv4util_p.h
+++ b/src/qml/jsruntime/qv4util_p.h
@@ -33,6 +33,17 @@
#ifndef QV4UTIL_H
#define QV4UTIL_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp
index 68228f06bb..4c81199a07 100644
--- a/src/qml/jsruntime/qv4value.cpp
+++ b/src/qml/jsruntime/qv4value.cpp
@@ -32,10 +32,11 @@
****************************************************************************/
#include <qv4engine_p.h>
#include <qv4runtime_p.h>
+#include <qv4string_p.h>
#ifndef V4_BOOTSTRAP
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#endif
#include <wtf/MathExtras.h>
@@ -68,10 +69,32 @@ int Value::toUInt16() const
return (unsigned short)number;
}
+bool Value::toBoolean() const
+{
+ switch (type()) {
+ case Value::Undefined_Type:
+ case Value::Null_Type:
+ return false;
+ case Value::Boolean_Type:
+ case Value::Integer_Type:
+ return (bool)int_32();
+ case Value::Managed_Type:
+#ifdef V4_BOOTSTRAP
+ Q_UNIMPLEMENTED();
+#else
+ if (isString())
+ return stringValue()->toQString().length() > 0;
+#endif
+ return true;
+ default: // double
+ return doubleValue() && !std::isnan(doubleValue());
+ }
+}
+
double Value::toInteger() const
{
if (integerCompatible())
- return int_32;
+ return int_32();
return Primitive::toInteger(toNumber());
}
@@ -87,10 +110,10 @@ double Value::toNumberImpl() const
#else
if (isString())
return RuntimeHelpers::stringToNumber(stringValue()->toQString());
- {
- Q_ASSERT(isObject());
- Scope scope(objectValue()->engine());
- ScopedValue prim(scope, RuntimeHelpers::toPrimitive(*this, NUMBER_HINT));
+ {
+ Q_ASSERT(isObject());
+ Scope scope(objectValue()->engine());
+ ScopedValue prim(scope, RuntimeHelpers::toPrimitive(*this, NUMBER_HINT));
if (scope.engine->hasException)
return 0;
return prim->toNumber();
@@ -99,7 +122,7 @@ double Value::toNumberImpl() const
case QV4::Value::Null_Type:
case QV4::Value::Boolean_Type:
case QV4::Value::Integer_Type:
- return int_32;
+ return int_32();
default: // double
Q_UNREACHABLE();
}
@@ -148,7 +171,7 @@ QString Value::toQStringNoThrow() const
}
case Value::Integer_Type: {
QString str;
- RuntimeHelpers::numberToString(&str, (double)int_32, 10);
+ RuntimeHelpers::numberToString(&str, (double)int_32(), 10);
return str;
}
default: { // double
@@ -184,7 +207,7 @@ QString Value::toQString() const
}
case Value::Integer_Type: {
QString str;
- RuntimeHelpers::numberToString(&str, (double)int_32, 10);
+ RuntimeHelpers::numberToString(&str, (double)int_32(), 10);
return str;
}
default: { // double
@@ -197,14 +220,14 @@ QString Value::toQString() const
#endif // V4_BOOTSTRAP
bool Value::sameValue(Value other) const {
- if (val == other.val)
+ if (_val == other._val)
return true;
if (isString() && other.isString())
return stringValue()->isEqualTo(other.stringValue());
if (isInteger() && other.isDouble())
- return int_32 ? (double(int_32) == other.doubleValue()) : (other.val == 0);
+ return int_32() ? (double(int_32()) == other.doubleValue()) : (other._val == 0);
if (isDouble() && other.isInteger())
- return other.int_32 ? (doubleValue() == double(other.int_32)) : (val == 0);
+ return other.int_32() ? (doubleValue() == double(other.int_32())) : (_val == 0);
return false;
}
@@ -281,4 +304,35 @@ Heap::Object *Value::toObject(ExecutionEngine *e) const
return RuntimeHelpers::convertToObject(e, *this);
}
+uint Value::asArrayLength(bool *ok) const
+{
+ *ok = true;
+ if (isInteger()) {
+ if (int_32() >= 0) {
+ return (uint)int_32();
+ } else {
+ *ok = false;
+ return UINT_MAX;
+ }
+ }
+ if (isNumber()) {
+ double d = doubleValue();
+ uint idx = (uint)d;
+ if (idx != d) {
+ *ok = false;
+ return UINT_MAX;
+ }
+ return idx;
+ }
+ if (isString())
+ return stringValue()->toUInt(ok);
+
+ uint idx = toUInt32();
+ double d = toNumber();
+ if (d != idx) {
+ *ok = false;
+ return UINT_MAX;
+ }
+ return idx;
+}
#endif // V4_BOOTSTRAP
diff --git a/src/qml/jsruntime/qv4value_inl_p.h b/src/qml/jsruntime/qv4value_inl_p.h
deleted file mode 100644
index f3026900d6..0000000000
--- a/src/qml/jsruntime/qv4value_inl_p.h
+++ /dev/null
@@ -1,293 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#ifndef QV4VALUE_INL_H
-#define QV4VALUE_INL_H
-
-#include <cmath> // this HAS to come
-
-#include "qv4value_p.h"
-
-#include "qv4string_p.h"
-#include "qv4managed_p.h"
-#include "qv4engine_p.h"
-
-QT_BEGIN_NAMESPACE
-
-namespace QV4 {
-
-inline bool Value::isString() const
-{
- if (!isManaged())
- return false;
- return m && m->vtable->isString;
-}
-inline bool Value::isObject() const
-{
- if (!isManaged())
- return false;
- return m && m->vtable->isObject;
-}
-
-inline bool Value::isPrimitive() const
-{
- return !isObject();
-}
-
-inline String *Value::asString() const
-{
- if (isString())
- return stringValue();
- return 0;
-}
-
-inline void Value::mark(ExecutionEngine *e) const
-{
- if (!val)
- return;
- Managed *m = asManaged();
- if (m)
- m->mark(e);
-}
-
-inline Primitive Primitive::nullValue()
-{
- Primitive v;
-#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- v.val = quint64(_Null_Type) << Tag_Shift;
-#else
- v.tag = _Null_Type;
- v.int_32 = 0;
-#endif
- return v;
-}
-
-inline Primitive Primitive::fromBoolean(bool b)
-{
- Primitive v;
- v.tag = _Boolean_Type;
- v.int_32 = (bool)b;
- return v;
-}
-
-inline Primitive Primitive::fromDouble(double d)
-{
- Primitive v;
- v.setDouble(d);
- return v;
-}
-
-inline Primitive Primitive::fromInt32(int i)
-{
- Primitive v;
- v.tag = _Integer_Type;
- v.int_32 = i;
- return v;
-}
-
-inline Primitive Primitive::fromUInt32(uint i)
-{
- Primitive v;
- if (i < INT_MAX) {
- v.tag = _Integer_Type;
- v.int_32 = (int)i;
- } else {
- v.setDouble(i);
- }
- return v;
-}
-
-inline double Value::toNumber() const
-{
- if (isInteger())
- return int_32;
- if (isDouble())
- return doubleValue();
- return toNumberImpl();
-}
-
-inline int Value::toInt32() const
-{
- if (isInteger())
- return int_32;
- double d = isNumber() ? doubleValue() : toNumberImpl();
-
- const double D32 = 4294967296.0;
- const double D31 = D32 / 2.0;
-
- if ((d >= -D31 && d < D31))
- return static_cast<int>(d);
-
- return Primitive::toInt32(d);
-}
-
-inline unsigned int Value::toUInt32() const
-{
- return (unsigned int)toInt32();
-}
-
-
-inline bool Value::toBoolean() const
-{
- switch (type()) {
- case Value::Undefined_Type:
- case Value::Null_Type:
- return false;
- case Value::Boolean_Type:
- case Value::Integer_Type:
- return (bool)int_32;
- case Value::Managed_Type:
-#ifdef V4_BOOTSTRAP
- Q_UNIMPLEMENTED();
-#else
- if (isString())
- return stringValue()->toQString().length() > 0;
-#endif
- return true;
- default: // double
- return doubleValue() && !std::isnan(doubleValue());
- }
-}
-
-#ifndef V4_BOOTSTRAP
-inline uint Value::asArrayIndex() const
-{
-#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- if (!isNumber())
- return UINT_MAX;
- if (isInteger())
- return int_32 >= 0 ? (uint)int_32 : UINT_MAX;
-#else
- if (isInteger() && int_32 >= 0)
- return (uint)int_32;
- if (!isDouble())
- return UINT_MAX;
-#endif
- double d = doubleValue();
- uint idx = (uint)d;
- if (idx != d)
- return UINT_MAX;
- return idx;
-}
-
-inline uint Value::asArrayLength(bool *ok) const
-{
- *ok = true;
- if (isInteger()) {
- if (int_32 >= 0) {
- return (uint)int_32;
- } else {
- *ok = false;
- return UINT_MAX;
- }
- }
- if (isNumber()) {
- double d = doubleValue();
- uint idx = (uint)d;
- if (idx != d) {
- *ok = false;
- return UINT_MAX;
- }
- return idx;
- }
- if (isString())
- return stringValue()->toUInt(ok);
-
- uint idx = toUInt32();
- double d = toNumber();
- if (d != idx) {
- *ok = false;
- return UINT_MAX;
- }
- return idx;
-}
-
-inline Object *Value::asObject() const
-{
- return isObject() ? objectValue() : 0;
-}
-
-inline FunctionObject *Value::asFunctionObject() const
-{
- return isObject() ? managed()->asFunctionObject() : 0;
-}
-
-inline NumberObject *Value::asNumberObject() const
-{
- return isObject() ? managed()->asNumberObject() : 0;
-}
-
-inline StringObject *Value::asStringObject() const
-{
- return isObject() ? managed()->asStringObject() : 0;
-}
-
-inline DateObject *Value::asDateObject() const
-{
- return isObject() ? managed()->asDateObject() : 0;
-}
-
-inline ArrayObject *Value::asArrayObject() const
-{
- return isObject() ? managed()->asArrayObject() : 0;
-}
-
-inline ErrorObject *Value::asErrorObject() const
-{
- return isObject() ? managed()->asErrorObject() : 0;
-}
-
-template<typename T>
-inline T *Value::as() const { Managed *m = isObject() ? managed() : 0; return m ? m->as<T>() : 0; }
-
-#ifndef V4_BOOTSTRAP
-
-template<>
-inline String *value_cast(const Value &v) {
- return v.asString();
-}
-
-template<>
-inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v)
-{
- return v.toString(e)->asReturnedValue();
-}
-
-#endif
-
-#endif
-
-} // namespace QV4
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 628950784a..089b2bbd34 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -33,10 +33,22 @@
#ifndef QV4VALUE_P_H
#define QV4VALUE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <limits.h>
#include <QtCore/QString>
#include "qv4global_p.h"
+#include <private/qv4heap_p.h>
/* We cannot rely on QT_POINTER_SIZE to be set correctly on host builds. In qmldevtools the Value objects
are only used to store primitives, never object pointers. So we can use the 64-bit encoding. */
@@ -50,56 +62,12 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-typedef uint Bool;
-
namespace Heap {
-
-struct Q_QML_EXPORT Base {
- union {
- const ManagedVTable *vtable;
- quintptr mm_data;
- };
-
- inline ReturnedValue asReturnedValue() const;
- inline void mark(QV4::ExecutionEngine *engine);
-
- enum {
- MarkBit = 0x1,
- NotInUse = 0x2,
- PointerMask = ~0x3
- };
-
- ManagedVTable *gcGetVtable() const {
- return reinterpret_cast<ManagedVTable *>(mm_data & PointerMask);
- }
- inline bool isMarked() const {
- return mm_data & MarkBit;
- }
- inline void setMarkBit() {
- mm_data |= MarkBit;
- }
- inline void clearMarkBit() {
- mm_data &= ~MarkBit;
- }
-
- inline bool inUse() const {
- return !(mm_data & NotInUse);
- }
-
- Base *nextFree() {
- return reinterpret_cast<Base *>(mm_data & PointerMask);
- }
- void setNextFree(Base *m) {
- mm_data = (reinterpret_cast<quintptr>(m) | NotInUse);
- }
-
- void *operator new(size_t, Managed *m) { return m; }
- void *operator new(size_t, Heap::Base *m) { return m; }
- void operator delete(void *, Heap::Base *) {}
-};
-
+ struct Base;
}
+typedef uint Bool;
+
struct Q_QML_PRIVATE_EXPORT Value
{
/*
@@ -124,30 +92,38 @@ struct Q_QML_PRIVATE_EXPORT Value
Bit 15-17 is then used to encode other immediates.
*/
+ quint64 _val;
+
+ Q_ALWAYS_INLINE quint64 val() const { return _val; }
+ Q_ALWAYS_INLINE void setVal(quint64 v) { _val = v; }
+ Q_ALWAYS_INLINE void setValue(quint32 v) { memcpy(&_val, &v, 4); }
+ Q_ALWAYS_INLINE void setTag(quint32 t) { memcpy(4 + (quint8 *)&_val, &t, 4); }
- union {
- quint64 val;
-#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- Heap::Base *m;
-#else
- double dbl;
-#endif
- struct {
-#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN
- uint tag;
-#endif
- union {
- uint uint_32;
- int int_32;
-#ifndef QV4_USE_64_BIT_VALUE_ENCODING
- Heap::Base *m;
-#endif
- };
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- uint tag;
+ static inline int valueOffset() { return 0; }
+ static inline int tagOffset() { return 4; }
+ Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(tag) << 32 | value; }
+ Q_ALWAYS_INLINE quint32 value() const { return _val & quint64(~quint32(0)); }
+ Q_ALWAYS_INLINE quint32 tag() const { return _val >> 32; }
+#else // !Q_LITTLE_ENDIAN
+ static inline int valueOffset() { return 4; }
+ static inline int tagOffset() { return 0; }
+ Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(value) << 32 | tag; }
+ Q_ALWAYS_INLINE quint32 tag() const { return _val & quint64(~quint32(0)); }
+ Q_ALWAYS_INLINE quint32 value() const { return _val >> 32; }
+#endif
+
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
+ Q_ALWAYS_INLINE Heap::Base *m() const { Heap::Base *b; memcpy(&b, &_val, 8); return b; }
+ Q_ALWAYS_INLINE void setM(Heap::Base *b) { memcpy(&_val, &b, 8); }
+#else // !QV4_USE_64_BIT_VALUE_ENCODING
+ Q_ALWAYS_INLINE Heap::Base *m() const { Heap::Base *b; quint32 v = value(); memcpy(&b, &v, 4); return b; }
+ Q_ALWAYS_INLINE void setM(Heap::Base *b) { quint32 v; memcpy(&v, &b, 4); setValue(v); }
#endif
- };
- };
+
+ Q_ALWAYS_INLINE int int_32() const { int i; quint32 v = value(); memcpy(&i, &v, 4); return i; }
+ Q_ALWAYS_INLINE void setInt_32(int i) { quint32 u; memcpy(&u, &i, 4); setValue(u); }
+ Q_ALWAYS_INLINE uint uint_32() const { return value(); }
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
enum Masks {
@@ -173,9 +149,9 @@ struct Q_QML_PRIVATE_EXPORT Value
};
enum ValueTypeInternal {
- _Null_Type = Null_Type | ConvertibleToInt,
- _Boolean_Type = Boolean_Type | ConvertibleToInt,
- _Integer_Type = Integer_Type | ConvertibleToInt,
+ Null_Type_Internal = Null_Type | ConvertibleToInt,
+ Boolean_Type_Internal = Boolean_Type | ConvertibleToInt,
+ Integer_Type_Internal = Integer_Type | ConvertibleToInt,
};
#else
@@ -213,134 +189,134 @@ struct Q_QML_PRIVATE_EXPORT Value
enum ValueTypeInternal {
- _Null_Type = Null_Type,
- _Boolean_Type = Boolean_Type,
- _Integer_Type = Integer_Type
+ Null_Type_Internal = Null_Type,
+ Boolean_Type_Internal = Boolean_Type,
+ Integer_Type_Internal = Integer_Type
};
#endif
inline unsigned type() const {
- return tag & Type_Mask;
+ return tag() & Type_Mask;
}
// used internally in property
- inline bool isEmpty() const { return tag == Empty_Type; }
+ inline bool isEmpty() const { return tag() == Empty_Type; }
- inline bool isUndefined() const { return tag == Undefined_Type; }
- inline bool isNull() const { return tag == _Null_Type; }
- inline bool isBoolean() const { return tag == _Boolean_Type; }
+ inline bool isUndefined() const { return tag() == Undefined_Type; }
+ inline bool isNull() const { return tag() == Null_Type_Internal; }
+ inline bool isBoolean() const { return tag ()== Boolean_Type_Internal; }
#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- inline bool isInteger() const { return (val >> IsNumber_Shift) == 1; }
- inline bool isDouble() const { return (val >> IsDouble_Shift); }
- inline bool isNumber() const { return (val >> IsNumber_Shift); }
- inline bool isManaged() const { return !(val >> IsManaged_Shift); }
- inline bool isNullOrUndefined() const { return ((val >> IsManaged_Shift) & ~2) == 1; }
- inline bool integerCompatible() const { return ((val >> IsConvertibleToInt_Shift) & ~2) == 1; }
+ inline bool isInteger() const { return (_val >> IsNumber_Shift) == 1; }
+ inline bool isDouble() const { return (_val >> IsDouble_Shift); }
+ inline bool isNumber() const { return (_val >> IsNumber_Shift); }
+ inline bool isManaged() const { return !(_val >> IsManaged_Shift); }
+ inline bool isNullOrUndefined() const { return ((_val >> IsManaged_Shift) & ~2) == 1; }
+ inline bool integerCompatible() const { return ((_val >> IsConvertibleToInt_Shift) & ~2) == 1; }
static inline bool integerCompatible(Value a, Value b) {
return a.integerCompatible() && b.integerCompatible();
}
static inline bool bothDouble(Value a, Value b) {
return a.isDouble() && b.isDouble();
}
- double doubleValue() const {
- Q_ASSERT(isDouble());
- union {
- quint64 i;
- double d;
- } v;
- v.i = val ^ NaNEncodeMask;
- return v.d;
- }
- void setDouble(double d) {
- union {
- quint64 i;
- double d;
- } v;
- v.d = d;
- val = v.i ^ NaNEncodeMask;
- Q_ASSERT(isDouble());
- }
- inline bool isNaN() const { return (tag & 0x7fff8000) == 0x00078000; }
+ inline bool isNaN() const { return (tag() & 0x7fff8000) == 0x00078000; }
#else
- inline bool isInteger() const { return tag == _Integer_Type; }
- inline bool isDouble() const { return (tag & NotDouble_Mask) != NotDouble_Mask; }
- inline bool isNumber() const { return tag == _Integer_Type || (tag & NotDouble_Mask) != NotDouble_Mask; }
- inline bool isManaged() const { return tag == Managed_Type; }
- inline bool isNullOrUndefined() const { return (tag & IsNullOrUndefined_Mask) == Undefined_Type; }
- inline bool integerCompatible() const { return (tag & ConvertibleToInt) == ConvertibleToInt; }
+ inline bool isInteger() const { return tag() == Integer_Type_Internal; }
+ inline bool isDouble() const { return (tag() & NotDouble_Mask) != NotDouble_Mask; }
+ inline bool isNumber() const { return tag() == Integer_Type_Internal || (tag() & NotDouble_Mask) != NotDouble_Mask; }
+ inline bool isManaged() const { return tag() == Managed_Type; }
+ inline bool isNullOrUndefined() const { return (tag() & IsNullOrUndefined_Mask) == Undefined_Type; }
+ inline bool integerCompatible() const { return (tag() & ConvertibleToInt) == ConvertibleToInt; }
static inline bool integerCompatible(Value a, Value b) {
- return ((a.tag & b.tag) & ConvertibleToInt) == ConvertibleToInt;
+ return ((a.tag() & b.tag()) & ConvertibleToInt) == ConvertibleToInt;
}
static inline bool bothDouble(Value a, Value b) {
- return ((a.tag | b.tag) & NotDouble_Mask) != NotDouble_Mask;
+ return ((a.tag() | b.tag()) & NotDouble_Mask) != NotDouble_Mask;
}
- double doubleValue() const { Q_ASSERT(isDouble()); return dbl; }
- void setDouble(double d) { dbl = d; Q_ASSERT(isDouble()); }
- inline bool isNaN() const { return (tag & QV4::Value::NotDouble_Mask) == QV4::Value::NaN_Mask; }
+ inline bool isNaN() const { return (tag() & QV4::Value::NotDouble_Mask) == QV4::Value::NaN_Mask; }
#endif
+ Q_ALWAYS_INLINE double doubleValue() const {
+ Q_ASSERT(isDouble());
+ double d;
+ quint64 v = _val;
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
+ v ^= NaNEncodeMask;
+#endif
+ memcpy(&d, &v, 8);
+ return d;
+ }
+ Q_ALWAYS_INLINE void setDouble(double d) {
+ memcpy(&_val, &d, 8);
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
+ _val ^= NaNEncodeMask;
+#endif
+ Q_ASSERT(isDouble());
+ }
inline bool isString() const;
inline bool isObject() const;
inline bool isInt32() {
- if (tag == _Integer_Type)
+ if (tag() == Integer_Type_Internal)
return true;
if (isDouble()) {
double d = doubleValue();
int i = (int)d;
if (i == d) {
- int_32 = i;
- tag = _Integer_Type;
+ setInt_32(i);
+ setTag(Integer_Type_Internal);
return true;
}
}
return false;
}
double asDouble() const {
- if (tag == _Integer_Type)
- return int_32;
+ if (tag() == Integer_Type_Internal)
+ return int_32();
return doubleValue();
}
bool booleanValue() const {
- return int_32;
+ return int_32();
}
int integerValue() const {
- return int_32;
+ return int_32();
}
- String *stringValue() const {
- return m ? reinterpret_cast<String*>(const_cast<Value *>(this)) : 0;
+ Q_ALWAYS_INLINE String *stringValue() const {
+ return m() ? reinterpret_cast<String*>(const_cast<Value *>(this)) : 0;
}
- Object *objectValue() const {
- return m ? reinterpret_cast<Object*>(const_cast<Value *>(this)) : 0;
+ Q_ALWAYS_INLINE Object *objectValue() const {
+ return m() ? reinterpret_cast<Object*>(const_cast<Value *>(this)) : 0;
}
- Managed *managed() const {
- return m ? reinterpret_cast<Managed*>(const_cast<Value *>(this)) : 0;
+ Q_ALWAYS_INLINE Managed *managed() const {
+ return m() ? reinterpret_cast<Managed*>(const_cast<Value *>(this)) : 0;
}
- Heap::Base *heapObject() const {
- return m;
+ Q_ALWAYS_INLINE Heap::Base *heapObject() const {
+ return m();
}
- quint64 rawValue() const {
- return val;
+ Q_ALWAYS_INLINE quint64 &rawValueRef() {
+ return _val;
+ }
+ Q_ALWAYS_INLINE quint64 rawValue() const {
+ return _val;
}
+ Q_ALWAYS_INLINE void setRawValue(quint64 raw) { _val = raw; }
static inline Value fromHeapObject(Heap::Base *m)
{
Value v;
- v.m = m;
+ v.setRawValue(0);
+ v.setM(m);
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
- v.tag = Managed_Type;
+ v.setTag(Managed_Type);
#endif
return v;
}
- static inline Value fromManaged(Managed *m);
-
int toUInt16() const;
inline int toInt32() const;
inline unsigned int toUInt32() const;
- inline bool toBoolean() const;
+ bool toBoolean() const;
double toInteger() const;
inline double toNumber() const;
double toNumberImpl() const;
@@ -353,21 +329,32 @@ struct Q_QML_PRIVATE_EXPORT Value
inline bool tryIntegerConversion() {
bool b = integerCompatible();
if (b)
- tag = _Integer_Type;
+ setTag(Integer_Type_Internal);
return b;
}
- inline String *asString() const;
- inline Managed *asManaged() const;
- inline Object *asObject() const;
- inline FunctionObject *asFunctionObject() const;
- inline NumberObject *asNumberObject() const;
- inline StringObject *asStringObject() const;
- inline DateObject *asDateObject() const;
- inline ArrayObject *asArrayObject() const;
- inline ErrorObject *asErrorObject() const;
+ template <typename T>
+ const T *as() const {
+ if (!m() || !isManaged())
+ return 0;
+
+ Q_ASSERT(m()->vtable());
+#if !defined(QT_NO_QOBJECT_CHECK)
+ static_cast<const T *>(this)->qt_check_for_QMANAGED_macro(static_cast<const T *>(this));
+#endif
+ const VTable *vt = m()->vtable();
+ while (vt) {
+ if (vt == T::staticVTable())
+ return static_cast<const T *>(this);
+ vt = vt->parent;
+ }
+ return 0;
+ }
+ template <typename T>
+ T *as() {
+ return const_cast<T *>(const_cast<const Value *>(this)->as<T>());
+ }
- template<typename T> inline T *as() const;
template<typename T> inline T *cast() {
return static_cast<T *>(managed());
}
@@ -376,26 +363,32 @@ struct Q_QML_PRIVATE_EXPORT Value
}
inline uint asArrayIndex() const;
- inline uint asArrayLength(bool *ok) const;
+#ifndef V4_BOOTSTRAP
+ uint asArrayLength(bool *ok) const;
+#endif
- ReturnedValue asReturnedValue() const { return val; }
- static Value fromReturnedValue(ReturnedValue val) { Value v; v.val = val; return v; }
+ ReturnedValue asReturnedValue() const { return _val; }
+ static Value fromReturnedValue(ReturnedValue val) { Value v; v._val = val; return v; }
// Section 9.12
bool sameValue(Value other) const;
- inline void mark(ExecutionEngine *e) const;
+ inline void mark(ExecutionEngine *e);
Value &operator =(const ScopedValue &v);
- Value &operator=(ReturnedValue v) { val = v; return *this; }
+ Value &operator=(ReturnedValue v) { _val = v; return *this; }
Value &operator=(Managed *m) {
- val = Value::fromManaged(m).val;
+ if (!m) {
+ setTagValue(Undefined_Type, 0);
+ } else {
+ _val = reinterpret_cast<Value *>(m)->_val;
+ }
return *this;
}
Value &operator=(Heap::Base *o) {
- m = o;
+ setM(o);
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
- tag = Managed_Type;
+ setTag(Managed_Type);
#endif
return *this;
}
@@ -403,18 +396,69 @@ struct Q_QML_PRIVATE_EXPORT Value
template<typename T>
Value &operator=(const Scoped<T> &t);
Value &operator=(const Value &v) {
- val = v.val;
+ _val = v._val;
return *this;
}
};
-inline Managed *Value::asManaged() const
+inline bool Value::isString() const
{
- if (isManaged())
- return managed();
- return 0;
+ if (!isManaged())
+ return false;
+ return m() && m()->vtable()->isString;
+}
+inline bool Value::isObject() const
+{
+ if (!isManaged())
+ return false;
+ return m() && m()->vtable()->isObject;
}
+inline bool Value::isPrimitive() const
+{
+ return !isObject();
+}
+
+inline double Value::toNumber() const
+{
+ if (isInteger())
+ return int_32();
+ if (isDouble())
+ return doubleValue();
+ return toNumberImpl();
+}
+
+
+#ifndef V4_BOOTSTRAP
+inline uint Value::asArrayIndex() const
+{
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
+ if (!isNumber())
+ return UINT_MAX;
+ if (isInteger())
+ return int_32() >= 0 ? (uint)int_32() : UINT_MAX;
+#else
+ if (isInteger() && int_32() >= 0)
+ return (uint)int_32();
+ if (!isDouble())
+ return UINT_MAX;
+#endif
+ double d = doubleValue();
+ uint idx = (uint)d;
+ if (idx != d)
+ return UINT_MAX;
+ return idx;
+}
+#endif
+
+inline
+ReturnedValue Heap::Base::asReturnedValue() const
+{
+ return Value::fromHeapObject(const_cast<Heap::Base *>(this)).asReturnedValue();
+}
+
+
+
struct Q_QML_PRIVATE_EXPORT Primitive : public Value
{
inline static Primitive emptyValue();
@@ -437,10 +481,11 @@ inline Primitive Primitive::undefinedValue()
{
Primitive v;
#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- v.val = quint64(Undefined_Type) << Tag_Shift;
+ v.setRawValue(quint64(Undefined_Type) << Tag_Shift);
#else
- v.tag = Undefined_Type;
- v.int_32 = 0;
+ v.setRawValue(0);
+ v.setTag(Undefined_Type);
+ v.setValue(0);
#endif
return v;
}
@@ -448,66 +493,81 @@ inline Primitive Primitive::undefinedValue()
inline Primitive Primitive::emptyValue()
{
Primitive v;
- v.tag = Value::Empty_Type;
- v.uint_32 = 0;
+ v.setTagValue(Value::Empty_Type, 0);
return v;
}
-template <typename T>
-struct TypedValue : public Value
+inline Primitive Primitive::nullValue()
{
- template<typename X>
- TypedValue &operator =(X *x) {
- m = x;
+ Primitive v;
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
- tag = Managed_Type;
+ v.setRawValue(quint64(Null_Type_Internal) << Tag_Shift);
+#else
+ v.setTagValue(Null_Type_Internal, 0);
#endif
- return *this;
- }
- TypedValue &operator =(T *t);
- TypedValue &operator =(const Scoped<T> &v);
-// TypedValue &operator =(const ManagedRef<T> &v);
-
- TypedValue &operator =(const TypedValue<T> &t);
+ return v;
+}
- bool operator!() const { return !managed(); }
+inline Primitive Primitive::fromBoolean(bool b)
+{
+ Primitive v;
+ v.setTagValue(Boolean_Type_Internal, b);
+ return v;
+}
- operator T *() { return static_cast<T *>(managed()); }
- T *operator->() { return static_cast<T *>(managed()); }
- const T *operator->() const { return static_cast<T *>(managed()); }
- T *getPointer() const { return static_cast<T *>(managed()); }
+inline Primitive Primitive::fromDouble(double d)
+{
+ Primitive v;
+ v.setDouble(d);
+ return v;
+}
- void mark(ExecutionEngine *e) { if (managed()) managed()->mark(e); }
-};
-typedef TypedValue<String> StringValue;
+inline Primitive Primitive::fromInt32(int i)
+{
+ Primitive v;
+ v.setTagValue(Integer_Type_Internal, 0); // For mingw482, because it complains, and for VS9, because of internal compiler errors.
+ v.setInt_32(i);
+ return v;
+}
+inline Primitive Primitive::fromUInt32(uint i)
+{
+ Primitive v;
+ if (i < INT_MAX) {
+ v.setTagValue(Integer_Type_Internal, 0); // For mingw482, because it complains, and for VS9, because of internal compiler errors.
+ v.setInt_32((int)i);
+ } else {
+ v.setDouble(i);
+ }
+ return v;
+}
struct Encode {
static ReturnedValue undefined() {
return quint64(Value::Undefined_Type) << Value::Tag_Shift;
}
static ReturnedValue null() {
- return quint64(Value::_Null_Type) << Value::Tag_Shift;
+ return quint64(Value::Null_Type_Internal) << Value::Tag_Shift;
}
Encode(bool b) {
- val = (quint64(Value::_Boolean_Type) << Value::Tag_Shift) | (uint)b;
+ val = (quint64(Value::Boolean_Type_Internal) << Value::Tag_Shift) | (uint)b;
}
Encode(double d) {
Value v;
v.setDouble(d);
- val = v.val;
+ val = v.rawValue();
}
Encode(int i) {
- val = (quint64(Value::_Integer_Type) << Value::Tag_Shift) | (uint)i;
+ val = (quint64(Value::Integer_Type_Internal) << Value::Tag_Shift) | (uint)i;
}
Encode(uint i) {
if (i <= INT_MAX) {
- val = (quint64(Value::_Integer_Type) << Value::Tag_Shift) | i;
+ val = (quint64(Value::Integer_Type_Internal) << Value::Tag_Shift) | i;
} else {
Value v;
v.setDouble(i);
- val = v.val;
+ val = v.rawValue();
}
}
Encode(ReturnedValue v) {
@@ -527,21 +587,29 @@ private:
Encode(void *);
};
-inline
-ReturnedValue Heap::Base::asReturnedValue() const
+template<typename T>
+ReturnedValue value_convert(ExecutionEngine *e, const Value &v);
+
+inline int Value::toInt32() const
{
- return Value::fromHeapObject(const_cast<Heap::Base *>(this)).asReturnedValue();
-}
+ if (isInteger())
+ return int_32();
+ double d = isNumber() ? doubleValue() : toNumberImpl();
+ const double D32 = 4294967296.0;
+ const double D31 = D32 / 2.0;
-template<typename T>
-T *value_cast(const Value &v)
+ if ((d >= -D31 && d < D31))
+ return static_cast<int>(d);
+
+ return Primitive::toInt32(d);
+}
+
+inline unsigned int Value::toUInt32() const
{
- return v.as<T>();
+ return (unsigned int)toInt32();
}
-template<typename T>
-ReturnedValue value_convert(ExecutionEngine *e, const Value &v);
}
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index 966f83acef..4609373cc9 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -43,12 +43,15 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(VariantObject);
-Heap::VariantObject::VariantObject(QV4::ExecutionEngine *engine, const QVariant &value)
- : Heap::Object(engine->emptyClass, engine->variantPrototype.asObject())
+Heap::VariantObject::VariantObject()
+{
+}
+
+Heap::VariantObject::VariantObject(const QVariant &value)
{
data = value;
if (isScarce())
- engine->scarceResources.insert(this);
+ internalClass->engine->scarceResources.insert(this);
}
bool VariantObject::Data::isScarce() const
@@ -96,8 +99,8 @@ void VariantPrototype::init()
{
defineDefaultProperty(QStringLiteral("preserve"), method_preserve, 0);
defineDefaultProperty(QStringLiteral("destroy"), method_destroy, 0);
- defineDefaultProperty(engine()->id_valueOf, method_valueOf, 0);
- defineDefaultProperty(engine()->id_toString, method_toString, 0);
+ defineDefaultProperty(engine()->id_valueOf(), method_valueOf, 0);
+ defineDefaultProperty(engine()->id_toString(), method_toString, 0);
}
QV4::ReturnedValue VariantPrototype::method_preserve(CallContext *ctx)
@@ -129,7 +132,7 @@ QV4::ReturnedValue VariantPrototype::method_toString(CallContext *ctx)
return Encode::undefined();
QString result = o->d()->data.toString();
if (result.isEmpty() && !o->d()->data.canConvert(QVariant::String))
- result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(o->d()->data.typeName()));
+ result = QStringLiteral("QVariant(%0)").arg(QString::fromLatin1(o->d()->data.typeName()));
return Encode(ctx->d()->engine->newString(result));
}
diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h
index 2b48412c4d..4680912354 100644
--- a/src/qml/jsruntime/qv4variantobject_p.h
+++ b/src/qml/jsruntime/qv4variantobject_p.h
@@ -49,7 +49,7 @@
#include <QtQml/qqmllist.h>
#include <QtCore/qvariant.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
@@ -60,10 +60,8 @@ namespace Heap {
struct VariantObject : Object, public ExecutionEngine::ScarceResourceData
{
- VariantObject(InternalClass *ic, QV4::Object *prototype)
- : Object(ic, prototype)
- {}
- VariantObject(QV4::ExecutionEngine *engine, const QVariant &value);
+ VariantObject();
+ VariantObject(const QVariant &value);
~VariantObject() {
if (isScarce())
node.remove();
@@ -77,6 +75,7 @@ struct VariantObject : Object, public ExecutionEngine::ScarceResourceData
struct VariantObject : Object
{
V4_OBJECT2(VariantObject, Object)
+ V4_PROTOTYPE(variantPrototype)
V4_NEEDS_DESTROY
void addVmePropertyReference();
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 390bbf5ee3..024a72bde2 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -37,13 +37,14 @@
#include <QtCore/qjsondocument.h>
#include <QtCore/qjsonobject.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4debugging_p.h>
#include <private/qv4function_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4math_p.h>
#include <private/qv4scopedvalue_p.h>
#include <private/qv4lookup_p.h>
+#include <private/qv4string_p.h>
#include <iostream>
#include "qv4alloca_p.h"
@@ -374,8 +375,8 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
const uchar *exceptionHandler = 0;
QV4::Scope scope(engine);
- QV4::ScopedContext context(scope, engine->currentContext());
- engine->currentContext()->lineNumber = -1;
+ QV4::ExecutionContext *context = engine->currentContext;
+ engine->current->lineNumber = -1;
#ifdef DO_TRACE_INSTR
qDebug("Starting VME with context=%p and code=%p", context, code);
@@ -512,6 +513,28 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
STOREVALUE(instr.result, Runtime::getQmlQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired));
MOTH_END_INSTR(LoadQObjectProperty)
+ MOTH_BEGIN_INSTR(StoreScopeObjectProperty)
+ Runtime::setQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source));
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(StoreScopeObjectProperty)
+
+ MOTH_BEGIN_INSTR(LoadScopeObjectProperty)
+ STOREVALUE(instr.result, Runtime::getQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex));
+ MOTH_END_INSTR(LoadScopeObjectProperty)
+
+ MOTH_BEGIN_INSTR(StoreContextObjectProperty)
+ Runtime::setQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source));
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(StoreContextObjectProperty)
+
+ MOTH_BEGIN_INSTR(LoadContextObjectProperty)
+ STOREVALUE(instr.result, Runtime::getQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex));
+ MOTH_END_INSTR(LoadContextObjectProperty)
+
+ MOTH_BEGIN_INSTR(LoadIdObject)
+ STOREVALUE(instr.result, Runtime::getQmlIdObject(engine, VALUE(instr.base), instr.index));
+ MOTH_END_INSTR(LoadIdObject)
+
MOTH_BEGIN_INSTR(LoadAttachedQObjectProperty)
STOREVALUE(instr.result, Runtime::getQmlAttachedProperty(engine, instr.attachedPropertiesId, instr.propertyIndex));
MOTH_END_INSTR(LoadAttachedQObjectProperty)
@@ -565,6 +588,26 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
STOREVALUE(instr.result, Runtime::callPropertyLookup(engine, instr.lookupIndex, callData));
MOTH_END_INSTR(CallPropertyLookup)
+ MOTH_BEGIN_INSTR(CallScopeObjectProperty)
+ TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = QV4::Value::Integer_Type;
+ callData->argc = instr.argc;
+ callData->thisObject = VALUE(instr.base);
+ STOREVALUE(instr.result, Runtime::callQmlScopeObjectProperty(engine, instr.index, callData));
+ MOTH_END_INSTR(CallScopeObjectProperty)
+
+ MOTH_BEGIN_INSTR(CallContextObjectProperty)
+ TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = QV4::Value::Integer_Type;
+ callData->argc = instr.argc;
+ callData->thisObject = VALUE(instr.base);
+ STOREVALUE(instr.result, Runtime::callQmlContextObjectProperty(engine, instr.index, callData));
+ MOTH_END_INSTR(CallContextObjectProperty)
+
MOTH_BEGIN_INSTR(CallElement)
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
@@ -607,18 +650,18 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_BEGIN_INSTR(CallBuiltinPushCatchScope)
Runtime::pushCatchScope(static_cast<QV4::NoThrowEngine*>(engine), instr.name);
- context = engine->currentContext();
+ context = engine->currentContext;
MOTH_END_INSTR(CallBuiltinPushCatchScope)
MOTH_BEGIN_INSTR(CallBuiltinPushScope)
Runtime::pushWithScope(VALUE(instr.arg), engine);
- context = engine->currentContext();
+ context = engine->currentContext;
CHECK_EXCEPTION;
MOTH_END_INSTR(CallBuiltinPushScope)
MOTH_BEGIN_INSTR(CallBuiltinPopScope)
Runtime::popScope(engine);
- context = engine->currentContext();
+ context = engine->currentContext;
MOTH_END_INSTR(CallBuiltinPopScope)
MOTH_BEGIN_INSTR(CallBuiltinForeachIteratorObject)
@@ -641,6 +684,14 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
STOREVALUE(instr.result, Runtime::deleteName(engine, instr.name));
MOTH_END_INSTR(CallBuiltinDeleteName)
+ MOTH_BEGIN_INSTR(CallBuiltinTypeofScopeObjectProperty)
+ STOREVALUE(instr.result, Runtime::typeofScopeObjectProperty(engine, VALUE(instr.base), instr.index));
+ MOTH_END_INSTR(CallBuiltinTypeofMember)
+
+ MOTH_BEGIN_INSTR(CallBuiltinTypeofContextObjectProperty)
+ STOREVALUE(instr.result, Runtime::typeofContextObjectProperty(engine, VALUE(instr.base), instr.index));
+ MOTH_END_INSTR(CallBuiltinTypeofMember)
+
MOTH_BEGIN_INSTR(CallBuiltinTypeofMember)
STOREVALUE(instr.result, Runtime::typeofMember(engine, VALUE(instr.base), instr.member));
MOTH_END_INSTR(CallBuiltinTypeofMember)
@@ -846,7 +897,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_END_INSTR(Ret)
MOTH_BEGIN_INSTR(Debug)
- engine->currentContext()->lineNumber = instr.lineNumber;
+ engine->current->lineNumber = instr.lineNumber;
QV4::Debugging::Debugger *debugger = context->engine()->debugger;
if (debugger && debugger->pauseAtNextOpportunity())
debugger->maybeBreakAtInstruction();
@@ -855,31 +906,23 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_END_INSTR(Debug)
MOTH_BEGIN_INSTR(Line)
- engine->currentContext()->lineNumber = instr.lineNumber;
+ engine->current->lineNumber = instr.lineNumber;
if (qt_v4IsDebugging)
qt_v4CheckForBreak(context, scopes, scopeDepth);
- MOTH_END_INSTR(Debug)
+ MOTH_END_INSTR(Line)
MOTH_BEGIN_INSTR(LoadThis)
VALUE(instr.result) = context->thisObject();
MOTH_END_INSTR(LoadThis)
- MOTH_BEGIN_INSTR(LoadQmlIdArray)
- VALUE(instr.result) = Runtime::getQmlIdArray(static_cast<QV4::NoThrowEngine*>(engine));
- MOTH_END_INSTR(LoadQmlIdArray)
+ MOTH_BEGIN_INSTR(LoadQmlContext)
+ VALUE(instr.result) = Runtime::getQmlContext(static_cast<QV4::NoThrowEngine*>(engine));
+ MOTH_END_INSTR(LoadQmlContext)
MOTH_BEGIN_INSTR(LoadQmlImportedScripts)
VALUE(instr.result) = Runtime::getQmlImportedScripts(static_cast<QV4::NoThrowEngine*>(engine));
MOTH_END_INSTR(LoadQmlImportedScripts)
- MOTH_BEGIN_INSTR(LoadQmlContextObject)
- VALUE(instr.result) = Runtime::getQmlContextObject(static_cast<QV4::NoThrowEngine*>(engine));
- MOTH_END_INSTR(LoadContextObject)
-
- MOTH_BEGIN_INSTR(LoadQmlScopeObject)
- VALUE(instr.result) = Runtime::getQmlScopeObject(static_cast<QV4::NoThrowEngine*>(engine));
- MOTH_END_INSTR(LoadScopeObject)
-
MOTH_BEGIN_INSTR(LoadQmlSingleton)
VALUE(instr.result) = Runtime::getQmlSingleton(static_cast<QV4::NoThrowEngine*>(engine), instr.name);
MOTH_END_INSTR(LoadQmlSingleton)
diff --git a/src/qml/jsruntime/qv4vme_moth_p.h b/src/qml/jsruntime/qv4vme_moth_p.h
index 55cac75a66..c0421022d2 100644
--- a/src/qml/jsruntime/qv4vme_moth_p.h
+++ b/src/qml/jsruntime/qv4vme_moth_p.h
@@ -34,6 +34,17 @@
#ifndef QV4VME_MOTH_P_H
#define QV4VME_MOTH_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qv4runtime_p.h>
#include <private/qv4instr_moth_p.h>
diff --git a/src/qml/memory/memory.pri b/src/qml/memory/memory.pri
new file mode 100644
index 0000000000..04b7566ccc
--- /dev/null
+++ b/src/qml/memory/memory.pri
@@ -0,0 +1,14 @@
+INCLUDEPATH += $$PWD
+INCLUDEPATH += $$OUT_PWD
+
+!qmldevtools_build {
+SOURCES += \
+ $$PWD/qv4mm.cpp \
+
+HEADERS += \
+ $$PWD/qv4mm_p.h
+
+}
+
+HEADERS += \
+ $$PWD/qv4heap_p.h
diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h
new file mode 100644
index 0000000000..a3db71fee1
--- /dev/null
+++ b/src/qml/memory/qv4heap_p.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4HEAP_P_H
+#define QV4HEAP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QString>
+#include <private/qv4global_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+struct VTable
+{
+ const VTable * const parent;
+ uint isExecutionContext : 1;
+ uint isString : 1;
+ uint isObject : 1;
+ uint isFunctionObject : 1;
+ uint isErrorObject : 1;
+ uint isArrayData : 1;
+ uint unused : 18;
+ uint type : 8;
+ const char *className;
+ void (*destroy)(Heap::Base *);
+ void (*markObjects)(Heap::Base *, ExecutionEngine *e);
+ bool (*isEqualTo)(Managed *m, Managed *other);
+};
+
+namespace Heap {
+
+struct Q_QML_EXPORT Base {
+ quintptr mm_data; // vtable and markbit
+
+ inline ReturnedValue asReturnedValue() const;
+ inline void mark(QV4::ExecutionEngine *engine);
+
+ enum {
+ MarkBit = 0x1,
+ NotInUse = 0x2,
+ PointerMask = ~0x3
+ };
+
+ void setVtable(const VTable *v) {
+ Q_ASSERT(!(mm_data & MarkBit));
+ mm_data = reinterpret_cast<quintptr>(v);
+ }
+ VTable *vtable() const {
+ return reinterpret_cast<VTable *>(mm_data & PointerMask);
+ }
+ inline bool isMarked() const {
+ return mm_data & MarkBit;
+ }
+ inline void setMarkBit() {
+ mm_data |= MarkBit;
+ }
+ inline void clearMarkBit() {
+ mm_data &= ~MarkBit;
+ }
+
+ inline bool inUse() const {
+ return !(mm_data & NotInUse);
+ }
+
+ Base *nextFree() {
+ return reinterpret_cast<Base *>(mm_data & PointerMask);
+ }
+ void setNextFree(Base *m) {
+ mm_data = (reinterpret_cast<quintptr>(m) | NotInUse);
+ }
+
+ void *operator new(size_t, Managed *m) { return m; }
+ void *operator new(size_t, Heap::Base *m) { return m; }
+ void operator delete(void *, Heap::Base *) {}
+};
+
+template <typename T>
+struct Pointer {
+ Pointer() {}
+ Pointer(T *t) : ptr(t) {}
+
+ T *operator->() const { return ptr; }
+ operator T *() const { return ptr; }
+
+ Pointer &operator =(T *t) { ptr = t; return *this; }
+
+ template <typename Type>
+ Type *cast() { return static_cast<Type *>(ptr); }
+
+ T *ptr;
+};
+
+}
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 64491e1376..5181bf912b 100644
--- a/src/qml/jsruntime/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -64,10 +64,42 @@
#include <pthread_np.h>
#endif
+#define MIN_UNMANAGED_HEAPSIZE_GC_LIMIT (std::size_t)128*1024
+
using namespace WTF;
QT_BEGIN_NAMESPACE
+static uint maxShiftValue()
+{
+ static uint result = 0;
+ if (!result) {
+ result = 6;
+ if (Q_UNLIKELY(qEnvironmentVariableIsSet("QV4_MM_MAXBLOCK_SHIFT"))) {
+ bool ok;
+ const uint overrideValue = qgetenv("QV4_MM_MAXBLOCK_SHIFT").toUInt(&ok);
+ if (ok && overrideValue <= 11 && overrideValue > 0)
+ result = overrideValue;
+ }
+ }
+ return result;
+}
+
+static std::size_t maxChunkSizeValue()
+{
+ static std::size_t result = 0;
+ if (!result) {
+ result = 32 * 1024;
+ if (Q_UNLIKELY(qEnvironmentVariableIsSet("QV4_MM_MAX_CHUNK_SIZE"))) {
+ bool ok;
+ const std::size_t overrideValue = qgetenv("QV4_MM_MAX_CHUNK_SIZE").toUInt(&ok);
+ if (ok)
+ result = overrideValue;
+ }
+ }
+ return result;
+}
+
using namespace QV4;
struct MemoryManager::Data
@@ -111,8 +143,6 @@ struct MemoryManager::Data
LargeItem *largeItems;
std::size_t totalLargeItemsAllocated;
- GCDeletable *deletable;
-
// statistics:
#ifdef DETAILED_MM_STATS
QVector<unsigned> allocSizeCounters;
@@ -120,34 +150,22 @@ struct MemoryManager::Data
Data()
: gcBlocked(false)
+ , aggressiveGC(!qEnvironmentVariableIsEmpty("QV4_MM_AGGRESSIVE_GC"))
+ , gcStats(!qEnvironmentVariableIsEmpty("QV4_MM_STATS"))
, engine(0)
, totalItems(0)
, totalAlloc(0)
- , maxShift(6)
- , maxChunkSize(32*1024)
+ , maxShift(maxShiftValue())
+ , maxChunkSize(maxChunkSizeValue())
, unmanagedHeapSize(0)
- , unmanagedHeapSizeGCLimit(64 * 1024)
+ , unmanagedHeapSizeGCLimit(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT)
, largeItems(0)
, totalLargeItemsAllocated(0)
- , deletable(0)
{
memset(nonFullChunks, 0, sizeof(nonFullChunks));
memset(nChunks, 0, sizeof(nChunks));
memset(availableItems, 0, sizeof(availableItems));
memset(allocCount, 0, sizeof(allocCount));
- aggressiveGC = !qgetenv("QV4_MM_AGGRESSIVE_GC").isEmpty();
- gcStats = !qgetenv("QV4_MM_STATS").isEmpty();
-
- QByteArray overrideMaxShift = qgetenv("QV4_MM_MAXBLOCK_SHIFT");
- bool ok;
- uint override = overrideMaxShift.toUInt(&ok);
- if (ok && override <= 11 && override > 0)
- maxShift = override;
-
- QByteArray maxChunkString = qgetenv("QV4_MM_MAX_CHUNK_SIZE");
- std::size_t tmpMaxChunkSize = maxChunkString.toUInt(&ok);
- if (ok)
- maxChunkSize = tmpMaxChunkSize;
}
~Data()
@@ -189,15 +207,15 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec
#ifdef V4_USE_VALGRIND
VALGRIND_ENABLE_ERROR_REPORTING;
#endif
- if (std::size_t(header->itemSize) == MemoryManager::align(sizeof(Heap::String)) && m->gcGetVtable()->isString) {
+ if (std::size_t(header->itemSize) == MemoryManager::align(sizeof(Heap::String)) && m->vtable()->isString) {
std::size_t heapBytes = static_cast<Heap::String *>(m)->retainedTextSize();
Q_ASSERT(*unmanagedHeapSize >= heapBytes);
// qDebug() << "-- it's a string holding on to" << heapBytes << "bytes";
*unmanagedHeapSize -= heapBytes;
}
- if (m->gcGetVtable()->destroy)
- m->gcGetVtable()->destroy(m);
+ if (m->vtable()->destroy)
+ m->vtable()->destroy(m);
memset(m, 0, header->itemSize);
#ifdef V4_USE_VALGRIND
@@ -222,7 +240,8 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec
} // namespace
MemoryManager::MemoryManager(ExecutionEngine *engine)
- : m_d(new Data)
+ : engine(engine)
+ , m_d(new Data)
, m_persistentValues(new PersistentValueStorage(engine))
, m_weakValues(new PersistentValueStorage(engine))
{
@@ -249,13 +268,12 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
if (m_d->unmanagedHeapSize > m_d->unmanagedHeapSizeGCLimit) {
runGC();
- if (m_d->unmanagedHeapSizeGCLimit <= m_d->unmanagedHeapSize)
+ if (3*m_d->unmanagedHeapSizeGCLimit <= 4*m_d->unmanagedHeapSize)
+ // more than 75% full, raise limit
m_d->unmanagedHeapSizeGCLimit = std::max(m_d->unmanagedHeapSizeGCLimit, m_d->unmanagedHeapSize) * 2;
else if (m_d->unmanagedHeapSize * 4 <= m_d->unmanagedHeapSizeGCLimit)
- m_d->unmanagedHeapSizeGCLimit /= 2;
- else if (m_d->unmanagedHeapSizeGCLimit - m_d->unmanagedHeapSize < 5 * unmanagedSize)
- // try preventing running the GC all the time when we're just below the threshold limit and manage to collect just enough to do this one allocation
- m_d->unmanagedHeapSizeGCLimit += std::max(std::size_t(8 * 1024), 5 * unmanagedSize);
+ // less than 25% full, lower limit
+ m_d->unmanagedHeapSizeGCLimit = qMax(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT, m_d->unmanagedHeapSizeGCLimit/2);
didGCRun = true;
}
@@ -268,7 +286,7 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
// we use malloc for this
MemoryManager::Data::LargeItem *item = static_cast<MemoryManager::Data::LargeItem *>(
- malloc(Q_V4_PROFILE_ALLOC(m_d->engine, size + sizeof(MemoryManager::Data::LargeItem),
+ malloc(Q_V4_PROFILE_ALLOC(engine, size + sizeof(MemoryManager::Data::LargeItem),
Profiling::LargeItem)));
memset(item, 0, size + sizeof(MemoryManager::Data::LargeItem));
item->next = m_d->largeItems;
@@ -304,10 +322,9 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
std::size_t allocSize = m_d->maxChunkSize*(size_t(1) << shift);
allocSize = roundUpToMultipleOf(WTF::pageSize(), allocSize);
PageAllocation allocation = PageAllocation::allocate(
- Q_V4_PROFILE_ALLOC(m_d->engine, allocSize, Profiling::HeapPage),
+ Q_V4_PROFILE_ALLOC(engine, allocSize, Profiling::HeapPage),
OSAllocator::JSGCHeapPages);
m_d->heapChunks.append(allocation);
- std::sort(m_d->heapChunks.begin(), m_d->heapChunks.end());
header = reinterpret_cast<Data::ChunkHeader *>(allocation.base());
header->itemSize = int(size);
@@ -339,7 +356,7 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
#ifdef V4_USE_VALGRIND
VALGRIND_MEMPOOL_ALLOC(this, m, size);
#endif
- Q_V4_PROFILE_ALLOC(m_d->engine, size, Profiling::SmallItem);
+ Q_V4_PROFILE_ALLOC(engine, size, Profiling::SmallItem);
++m_d->allocCount[pos];
++m_d->totalAlloc;
@@ -353,21 +370,21 @@ static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase)
{
while (engine->jsStackTop > markBase) {
Heap::Base *h = engine->popForGC();
- Q_ASSERT (h->gcGetVtable()->markObjects);
- h->gcGetVtable()->markObjects(h, engine);
+ Q_ASSERT (h->vtable()->markObjects);
+ h->vtable()->markObjects(h, engine);
}
}
void MemoryManager::mark()
{
- Value *markBase = m_d->engine->jsStackTop;
-
- m_d->engine->markObjects();
+ Value *markBase = engine->jsStackTop;
- m_persistentValues->mark(m_d->engine);
+ engine->markObjects();
collectFromJSStack();
+ m_persistentValues->mark(engine);
+
// Preserve QObject ownership rules within JavaScript: A parent with c++ ownership
// keeps all of its children alive in JavaScript.
@@ -377,11 +394,9 @@ void MemoryManager::mark()
for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) {
if (!(*it).isManaged())
continue;
- if ((*it).managed()->d()->gcGetVtable() != QObjectWrapper::staticVTable())
+ if (!(*it).as<QObjectWrapper>())
continue;
QObjectWrapper *qobjectWrapper = static_cast<QObjectWrapper*>((*it).managed());
- if (!qobjectWrapper)
- continue;
QObject *qobject = qobjectWrapper->object();
if (!qobject)
continue;
@@ -397,27 +412,32 @@ void MemoryManager::mark()
}
if (keepAlive)
- qobjectWrapper->mark(m_d->engine);
+ qobjectWrapper->mark(engine);
- if (m_d->engine->jsStackTop >= m_d->engine->jsStackLimit)
- drainMarkStack(m_d->engine, markBase);
+ if (engine->jsStackTop >= engine->jsStackLimit)
+ drainMarkStack(engine, markBase);
}
- drainMarkStack(m_d->engine, markBase);
+ drainMarkStack(engine, markBase);
}
void MemoryManager::sweep(bool lastSweep)
{
- if (m_weakValues) {
- for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) {
- if (Managed *m = (*it).asManaged()) {
- if (!m->markBit())
- (*it) = Primitive::undefinedValue();
- }
- }
+ for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) {
+ if (!(*it).isManaged())
+ continue;
+ Managed *m = (*it).as<Managed>();
+ if (m->markBit())
+ continue;
+ // we need to call detroyObject on qobjectwrappers now, so that they can emit the destroyed
+ // signal before we start sweeping the heap
+ if (QObjectWrapper *qobjectWrapper = (*it).as<QObjectWrapper>())
+ qobjectWrapper->destroyObject(lastSweep);
+
+ (*it) = Primitive::undefinedValue();
}
- if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = m_d->engine->m_multiplyWrappedQObjects) {
+ if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = engine->m_multiplyWrappedQObjects) {
for (MultiplyWrappedQObjectMap::Iterator it = multiplyWrappedQObjects->begin(); it != multiplyWrappedQObjects->end();) {
if (!it.value().isNullOrUndefined())
it = multiplyWrappedQObjects->erase(it);
@@ -433,7 +453,7 @@ void MemoryManager::sweep(bool lastSweep)
for (int i = 0; i < m_d->heapChunks.size(); ++i) {
Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(m_d->heapChunks[i].base());
- chunkIsEmpty[i] = sweepChunk(header, &itemsInUse[header->itemSize >> 4], m_d->engine, &m_d->unmanagedHeapSize);
+ chunkIsEmpty[i] = sweepChunk(header, &itemsInUse[header->itemSize >> 4], engine, &m_d->unmanagedHeapSize);
}
QVector<PageAllocation>::iterator chunkIter = m_d->heapChunks.begin();
@@ -445,7 +465,7 @@ void MemoryManager::sweep(bool lastSweep)
// Release that chunk if it could have been spared since the last GC run without any difference.
if (chunkIsEmpty[i] && m_d->availableItems[pos] - decrease >= itemsInUse[pos]) {
- Q_V4_PROFILE_DEALLOC(m_d->engine, 0, chunkIter->size(), Profiling::HeapPage);
+ Q_V4_PROFILE_DEALLOC(engine, 0, chunkIter->size(), Profiling::HeapPage);
#ifdef V4_USE_VALGRIND
VALGRIND_MEMPOOL_FREE(this, header);
#endif
@@ -473,30 +493,21 @@ void MemoryManager::sweep(bool lastSweep)
i = i->next;
continue;
}
- if (m->gcGetVtable()->destroy)
- m->gcGetVtable()->destroy(m);
+ if (m->vtable()->destroy)
+ m->vtable()->destroy(m);
*last = i->next;
- free(Q_V4_PROFILE_DEALLOC(m_d->engine, i, i->size + sizeof(Data::LargeItem),
+ free(Q_V4_PROFILE_DEALLOC(engine, i, i->size + sizeof(Data::LargeItem),
Profiling::LargeItem));
i = *last;
}
- GCDeletable *deletable = m_d->deletable;
- m_d->deletable = 0;
- while (deletable) {
- GCDeletable *next = deletable->next;
- deletable->lastCall = lastSweep;
- delete deletable;
- deletable = next;
- }
-
// some execution contexts are allocated on the stack, make sure we clear their markBit as well
if (!lastSweep) {
- Heap::ExecutionContext *ctx = engine()->current;
+ QV4::ExecutionContext *ctx = engine->currentContext;
while (ctx) {
- ctx->clearMarkBit();
- ctx = ctx->parent;
+ ctx->d()->clearMarkBit();
+ ctx = engine->parentContext(ctx);
}
}
}
@@ -530,9 +541,11 @@ void MemoryManager::runGC()
int markTime = t.elapsed();
t.restart();
const size_t usedBefore = getUsedMem();
+ const size_t largeItemsBefore = getLargeItemsMem();
int chunksBefore = m_d->heapChunks.size();
sweep();
const size_t usedAfter = getUsedMem();
+ const size_t largeItemsAfter = getLargeItemsMem();
int sweepTime = t.elapsed();
qDebug() << "========== GC ==========";
@@ -543,6 +556,9 @@ void MemoryManager::runGC()
qDebug() << "Used memory after GC:" << usedAfter;
qDebug() << "Freed up bytes:" << (usedBefore - usedAfter);
qDebug() << "Released chunks:" << (chunksBefore - m_d->heapChunks.size());
+ qDebug() << "Large item memory before GC:" << largeItemsBefore;
+ qDebug() << "Large item memory after GC:" << largeItemsAfter;
+ qDebug() << "Large item memory freed up:" << (largeItemsBefore - largeItemsAfter);
qDebug() << "======== End GC ========";
}
@@ -554,7 +570,7 @@ void MemoryManager::runGC()
size_t MemoryManager::getUsedMem() const
{
size_t usedMem = 0;
- for (QVector<PageAllocation>::const_iterator i = m_d->heapChunks.begin(), ei = m_d->heapChunks.end(); i != ei; ++i) {
+ for (QVector<PageAllocation>::const_iterator i = m_d->heapChunks.cbegin(), ei = m_d->heapChunks.cend(); i != ei; ++i) {
Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(i->base());
for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) {
Heap::Base *m = reinterpret_cast<Heap::Base *>(item);
@@ -590,19 +606,16 @@ void MemoryManager::growUnmanagedHeapSizeUsage(size_t delta)
MemoryManager::~MemoryManager()
{
delete m_persistentValues;
- delete m_weakValues;
- m_weakValues = 0;
sweep(/*lastSweep*/true);
+
+ delete m_weakValues;
#ifdef V4_USE_VALGRIND
VALGRIND_DESTROY_MEMPOOL(this);
#endif
}
-ExecutionEngine *MemoryManager::engine() const
-{
- return m_d->engine;
-}
+
void MemoryManager::dumpStats() const
{
@@ -618,12 +631,6 @@ void MemoryManager::dumpStats() const
#endif // DETAILED_MM_STATS
}
-void MemoryManager::registerDeletable(GCDeletable *d)
-{
- d->next = m_d->deletable;
- m_d->deletable = d;
-}
-
#ifdef DETAILED_MM_STATS
void MemoryManager::willAllocate(std::size_t size)
{
@@ -638,13 +645,13 @@ void MemoryManager::willAllocate(std::size_t size)
void MemoryManager::collectFromJSStack() const
{
- Value *v = m_d->engine->jsStackBase;
- Value *top = m_d->engine->jsStackTop;
+ Value *v = engine->jsStackBase;
+ Value *top = engine->jsStackTop;
while (v < top) {
- Managed *m = v->asManaged();
+ Managed *m = v->as<Managed>();
if (m && m->inUse())
// Skip pointers to already freed objects, they are bogus as well
- m->mark(m_d->engine);
+ m->mark(engine);
++v;
}
}
diff --git a/src/qml/jsruntime/qv4mm_p.h b/src/qml/memory/qv4mm_p.h
index 7f6d2edba3..3543da0907 100644
--- a/src/qml/jsruntime/qv4mm_p.h
+++ b/src/qml/memory/qv4mm_p.h
@@ -34,9 +34,21 @@
#ifndef QV4GC_H
#define QV4GC_H
-#include "qv4global_p.h"
-#include "qv4value_inl_p.h"
-#include "qv4scopedvalue_p.h"
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qv4global_p.h>
+#include <private/qv4value_p.h>
+#include <private/qv4scopedvalue_p.h>
+#include <private/qv4object_p.h>
//#define DETAILED_MM_STATS
@@ -87,14 +99,153 @@ public:
{
size = align(size);
Heap::Base *o = allocData(size, unmanagedSize);
- o->vtable = ManagedType::staticVTable();
+ o->setVtable(ManagedType::staticVTable());
return static_cast<typename ManagedType::Data *>(o);
}
+ template <typename ObjectType>
+ typename ObjectType::Data *allocateObject(InternalClass *ic)
+ {
+ const int size = (sizeof(typename ObjectType::Data) + (sizeof(Value) - 1)) & ~(sizeof(Value) - 1);
+ typename ObjectType::Data *o = allocManaged<ObjectType>(size + ic->size*sizeof(Value));
+ o->internalClass = ic;
+ o->inlineMemberSize = ic->size;
+ o->inlineMemberOffset = size/sizeof(Value);
+ return o;
+ }
+
+ template <typename ObjectType>
+ typename ObjectType::Data *allocateObject()
+ {
+ InternalClass *ic = ObjectType::defaultInternalClass(engine);
+ const int size = (sizeof(typename ObjectType::Data) + (sizeof(Value) - 1)) & ~(sizeof(Value) - 1);
+ typename ObjectType::Data *o = allocManaged<ObjectType>(size + ic->size*sizeof(Value));
+ Object *prototype = ObjectType::defaultPrototype(engine);
+ o->internalClass = ic;
+ o->prototype = prototype->d();
+ o->inlineMemberSize = ic->size;
+ o->inlineMemberOffset = size/sizeof(Value);
+ return o;
+ }
+
+ template <typename ManagedType, typename Arg1>
+ typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1)
+ {
+ Scope scope(engine);
+ Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data), unmanagedSize));
+ (void)new (t->d()) typename ManagedType::Data(this, arg1);
+ return t->d();
+ }
+
+ template <typename ObjectType>
+ typename ObjectType::Data *allocObject(InternalClass *ic)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ (void)new (t->d()) typename ObjectType::Data();
+ return t->d();
+ }
+
+ template <typename ObjectType>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ t->d()->prototype = prototype->d();
+ (void)new (t->d()) typename ObjectType::Data();
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ t->d()->prototype = prototype->d();
+ (void)new (t->d()) typename ObjectType::Data(arg1);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1, Arg2 arg2)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ t->d()->prototype = prototype->d();
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1, Arg2 arg2, Arg3 arg3)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ t->d()->prototype = prototype->d();
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ t->d()->prototype = prototype->d();
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3, arg4);
+ return t->d();
+ }
+
+ template <typename ObjectType>
+ typename ObjectType::Data *allocObject()
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
+ (void)new (t->d()) typename ObjectType::Data();
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1>
+ typename ObjectType::Data *allocObject(Arg1 arg1)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
+ (void)new (t->d()) typename ObjectType::Data(arg1);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2>
+ typename ObjectType::Data *allocObject(Arg1 arg1, Arg2 arg2)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3>
+ typename ObjectType::Data *allocObject(Arg1 arg1, Arg2 arg2, Arg3 arg3)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+ typename ObjectType::Data *allocObject(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3, arg4);
+ return t->d();
+ }
+
+
template <typename ManagedType>
typename ManagedType::Data *alloc()
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data();
return t->d();
@@ -103,25 +254,16 @@ public:
template <typename ManagedType, typename Arg1>
typename ManagedType::Data *alloc(Arg1 arg1)
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data(arg1);
return t->d();
}
- template <typename ManagedType, typename Arg1>
- typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1)
- {
- Scope scope(engine());
- Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data), unmanagedSize));
- (void)new (t->d()) typename ManagedType::Data(this, arg1);
- return t->d();
- }
-
template <typename ManagedType, typename Arg1, typename Arg2>
typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2)
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data(arg1, arg2);
return t->d();
@@ -130,7 +272,7 @@ public:
template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3>
typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3)
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3);
return t->d();
@@ -139,7 +281,7 @@ public:
template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4);
return t->d();
@@ -148,7 +290,7 @@ public:
template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4, arg5);
return t->d();
@@ -158,12 +300,8 @@ public:
void setGCBlocked(bool blockGC);
void runGC();
- ExecutionEngine *engine() const;
-
void dumpStats() const;
- void registerDeletable(GCDeletable *d);
-
size_t getUsedMem() const;
size_t getAllocatedMem() const;
size_t getLargeItemsMem() const;
@@ -184,9 +322,9 @@ private:
void mark();
void sweep(bool lastSweep = false);
-protected:
- QScopedPointer<Data> m_d;
public:
+ QV4::ExecutionEngine *engine;
+ QScopedPointer<Data> m_d;
PersistentValueStorage *m_persistentValues;
PersistentValueStorage *m_weakValues;
};
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index 71b6978983..96b2b24298 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -506,7 +506,24 @@ bool Parser::parse(int startToken)
token_buffer[0].token = startToken;
first_token = &token_buffer[0];
- last_token = &token_buffer[1];
+ if (startToken == T_FEED_JS_PROGRAM && !lexer->qmlMode()) {
+ Directives ignoreDirectives;
+ Directives *directives = driver->directives();
+ if (!directives)
+ directives = &ignoreDirectives;
+ DiagnosticMessage error;
+ if (!lexer->scanDirectives(directives, &error)) {
+ diagnostic_messages.append(error);
+ return false;
+ }
+ token_buffer[1].token = lexer->tokenKind();
+ token_buffer[1].dval = lexer->tokenValue();
+ token_buffer[1].loc = location(lexer);
+ token_buffer[1].spell = lexer->tokenSpell();
+ last_token = &token_buffer[2];
+ } else {
+ last_token = &token_buffer[1];
+ }
tos = -1;
program = 0;
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index fa6b5d2488..3987f6093a 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -103,11 +103,11 @@ namespace QQmlJS {
namespace AST {
-template <typename _T1, typename _T2>
-_T1 cast(_T2 *ast)
+template <typename T1, typename T2>
+T1 cast(T2 *ast)
{
- if (ast && ast->kind == static_cast<_T1>(0)->K)
- return static_cast<_T1>(ast);
+ if (ast && ast->kind == static_cast<T1>(0)->K)
+ return static_cast<T1>(ast);
return 0;
}
diff --git a/src/qml/parser/qqmljsglobal_p.h b/src/qml/parser/qqmljsglobal_p.h
index fe2cbe7d1d..48ba2b034b 100644
--- a/src/qml/parser/qqmljsglobal_p.h
+++ b/src/qml/parser/qqmljsglobal_p.h
@@ -33,6 +33,17 @@
#ifndef QQMLJSGLOBAL_P_H
#define QQMLJSGLOBAL_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qglobal.h>
#ifdef QT_CREATOR
diff --git a/src/qml/parser/qqmljsmemorypool_p.h b/src/qml/parser/qqmljsmemorypool_p.h
index 16927251c7..ae9f1d8257 100644
--- a/src/qml/parser/qqmljsmemorypool_p.h
+++ b/src/qml/parser/qqmljsmemorypool_p.h
@@ -102,29 +102,7 @@ public:
_ptr = _end = 0;
}
- template <typename _Tp> _Tp *New() { return new (this->allocate(sizeof(_Tp))) _Tp(); }
-
- template <typename PoolContentType, typename Visitor>
- void visitManagedPool(Visitor &visitor)
- {
- for (int i = 0; i <= _blockCount; ++i) {
- char *p = _blocks[i];
- char *end = p + BLOCK_SIZE;
- if (i == _blockCount) {
- Q_ASSERT(_ptr <= end);
- end = _ptr;
- }
-
- Q_ASSERT(p <= end);
-
- const qptrdiff increment = (sizeof(PoolContentType) + 7) & ~7;
-
- while (p + increment <= end) {
- visitor(reinterpret_cast<PoolContentType*>(p));
- p += increment;
- }
- }
- }
+ template <typename Tp> Tp *New() { return new (this->allocate(sizeof(Tp))) Tp(); }
private:
void *allocate_helper(size_t size)
diff --git a/src/qml/qml.pro b/src/qml/qml.pro
index 6e06fb42ef..d75262bf0b 100644
--- a/src/qml/qml.pro
+++ b/src/qml/qml.pro
@@ -8,6 +8,9 @@ win32-msvc*:DEFINES *= _CRT_SECURE_NO_WARNINGS
win32:!wince*:!winrt:LIBS += -lshell32
solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
+# Ensure this gcc optimization is switched off for mips platforms to avoid trouble with JIT.
+gcc:isEqual(QT_ARCH, "mips"): QMAKE_CXXFLAGS += -fno-reorder-blocks
+
MODULE_PLUGIN_TYPES = \
qmltooling
@@ -33,6 +36,7 @@ HEADERS += qtqmlglobal.h \
#modules
include(util/util.pri)
+include(memory/memory.pri)
include(parser/parser.pri)
include(compiler/compiler.pri)
include(jsapi/jsapi.pri)
diff --git a/src/qml/qml/ftw/ftw.pri b/src/qml/qml/ftw/ftw.pri
index 4b109107f9..51697b0aff 100644
--- a/src/qml/qml/ftw/ftw.pri
+++ b/src/qml/qml/ftw/ftw.pri
@@ -4,7 +4,6 @@ HEADERS += \
$$PWD/qpodvector_p.h \
$$PWD/qhashedstring_p.h \
$$PWD/qqmlrefcount_p.h \
- $$PWD/qqmlpool_p.h \
$$PWD/qfieldlist_p.h \
$$PWD/qhashfield_p.h \
$$PWD/qqmlthread_p.h \
@@ -20,7 +19,6 @@ HEADERS += \
SOURCES += \
$$PWD/qintrusivelist.cpp \
$$PWD/qhashedstring.cpp \
- $$PWD/qqmlpool.cpp \
$$PWD/qqmlthread.cpp \
# mirrors logic in $$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri
diff --git a/src/qml/qml/ftw/qqmlpool_p.h b/src/qml/qml/ftw/qqmlpool_p.h
deleted file mode 100644
index 4956cd81d8..0000000000
--- a/src/qml/qml/ftw/qqmlpool_p.h
+++ /dev/null
@@ -1,270 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLPOOL_P_H
-#define QQMLPOOL_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <private/qv4global_p.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qurl.h>
-
-QT_BEGIN_NAMESPACE
-
-class Q_QML_PRIVATE_EXPORT QQmlPool
-{
-public:
- // The class has a destructor that needs to be called
- class Class {
- public:
- inline QQmlPool *pool() const;
-
- private:
- void *operator new(size_t);
- void *operator new(size_t, void *m) { return m; }
- friend class QQmlPool;
-
- QQmlPool *_pool;
- Class *_next;
- void (*_destroy)(Class *);
- };
-
- // The class is plain old data and no destructor needs to
- // be called
- class POD {
- public:
- inline QQmlPool *pool() const;
-
- private:
- void *operator new(size_t);
- void *operator new(size_t, void *m) { return m; }
- friend class QQmlPool;
-
- QQmlPool *_pool;
- };
-
- inline QQmlPool();
- inline ~QQmlPool();
-
- void clear();
-
- template<typename T>
- inline T *New();
- template<typename T>
- inline T *NewRaw();
- template<typename T>
- inline T *NewRawArray(int length);
-
- inline QString *NewString(const QString &);
- inline QByteArray *NewByteArray(const QByteArray &);
- inline QUrl *NewUrl(const QUrl &);
-
- template<typename T>
- struct List {
- List() : m_length(0), m_data(0) {}
- List(const List &o) : m_length(o.m_length), m_data(o.m_data) {}
- List &operator=(const List &o) {
- m_length = o.m_length;
- m_data = o.m_data;
- return *this;
- }
-
- int count() const {
- return m_length;
- }
- int length() const {
- return m_length;
- }
- const T &at(int index) const {
- Q_ASSERT(index < m_length);
- return m_data[index];
- };
- T &operator[](int index) {
- Q_ASSERT(index < m_length);
- return m_data[index];
- };
- const T *data() const { return m_data; }
- private:
- friend class QQmlPool;
- List(T *d, int l) : m_length(l), m_data(d) {}
- int m_length;
- T *m_data;
- };
-
- template<typename T>
- inline List<T> NewRawList(int length);
-
-private:
- struct StringClass : public QString, public Class {
- };
- struct ByteArrayClass : public QByteArray, public Class {
- };
- struct UrlClass : public QUrl, public Class {
- };
-
- inline void *allocate(int size);
- void newpage();
-
- template<typename T>
- inline void initialize(POD *);
- template<typename T>
- inline void initialize(Class *);
- template<typename T>
- static void destroy(Class *c);
-
- struct Page {
- struct Header {
- Page *next;
- char *free;
- } header;
-
- static const int pageSize = 4 * 4096 - sizeof(Header);
-
- char memory[pageSize];
- };
-
- Page *_page;
- Class *_classList;
-};
-
-QQmlPool::QQmlPool()
-: _page(0), _classList(0)
-{
-}
-
-QQmlPool::~QQmlPool()
-{
- clear();
-}
-
-template<typename T>
-T *QQmlPool::New()
-{
- T *rv = new (allocate(sizeof(T))) T;
- initialize<T>(rv);
- rv->_pool = this;
- return rv;
-}
-
-template<typename T>
-T *QQmlPool::NewRaw()
-{
- return (T*)allocate(sizeof(T));
-}
-
-template<typename T>
-T *QQmlPool::NewRawArray(int length)
-{
- return (T*)allocate(length * sizeof(T));
-}
-
-template<typename T>
-QQmlPool::List<T> QQmlPool::NewRawList(int length)
-{
- return List<T>(NewRawArray<T>(length), length);
-}
-
-QString *QQmlPool::NewString(const QString &s)
-{
- QString *rv = New<StringClass>();
- *rv = s;
- return rv;
-}
-
-QByteArray *QQmlPool::NewByteArray(const QByteArray &s)
-{
- QByteArray *rv = New<ByteArrayClass>();
- *rv = s;
- return rv;
-}
-
-QUrl *QQmlPool::NewUrl(const QUrl &s)
-{
- QUrl *rv = New<UrlClass>();
- *rv = s;
- return rv;
-}
-
-void *QQmlPool::allocate(int size)
-{
- if (!_page || (_page->header.free + size) > (_page->memory + Page::pageSize))
- newpage();
-
- void *rv = _page->header.free;
- _page->header.free += size + ((8 - size) & 7); // ensure 8 byte alignment;
- return rv;
-}
-
-template<typename T>
-void QQmlPool::initialize(QQmlPool::POD *)
-{
-}
-
-template<typename T>
-void QQmlPool::initialize(QQmlPool::Class *c)
-{
- c->_next = _classList;
- c->_destroy = &destroy<T>;
- _classList = c;
-}
-
-template<typename T>
-void QQmlPool::destroy(Class *c)
-{
- static_cast<T *>(c)->~T();
-}
-
-QQmlPool *QQmlPool::Class::pool() const
-{
- return _pool;
-}
-
-QQmlPool *QQmlPool::POD::pool() const
-{
- return _pool;
-}
-
-QT_END_NAMESPACE
-
-#endif // QQMLPOOL_P_H
-
diff --git a/src/qml/qml/ftw/qqmlrefcount_p.h b/src/qml/qml/ftw/qqmlrefcount_p.h
index 59ed77b580..ba2ca43990 100644
--- a/src/qml/qml/ftw/qqmlrefcount_p.h
+++ b/src/qml/qml/ftw/qqmlrefcount_p.h
@@ -72,13 +72,16 @@ template<class T>
class QQmlRefPointer
{
public:
+ enum Mode {
+ AddRef,
+ Adopt
+ };
inline QQmlRefPointer();
- inline QQmlRefPointer(T *);
+ inline QQmlRefPointer(T *, Mode m = AddRef);
inline QQmlRefPointer(const QQmlRefPointer<T> &);
inline ~QQmlRefPointer();
inline QQmlRefPointer<T> &operator=(const QQmlRefPointer<T> &o);
- inline QQmlRefPointer<T> &operator=(T *);
inline bool isNull() const { return !o; }
@@ -87,7 +90,7 @@ public:
inline operator T*() const { return o; }
inline T* data() const { return o; }
- inline QQmlRefPointer<T> &take(T *);
+ inline QQmlRefPointer<T> &adopt(T *);
private:
T *o;
@@ -133,10 +136,11 @@ QQmlRefPointer<T>::QQmlRefPointer()
}
template<class T>
-QQmlRefPointer<T>::QQmlRefPointer(T *o)
+QQmlRefPointer<T>::QQmlRefPointer(T *o, Mode m)
: o(o)
{
- if (o) o->addref();
+ if (m == AddRef && o)
+ o->addref();
}
template<class T>
@@ -161,21 +165,12 @@ QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(const QQmlRefPointer<T> &other)
return *this;
}
-template<class T>
-QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(T *other)
-{
- if (other) other->addref();
- if (o) o->release();
- o = other;
- return *this;
-}
-
/*!
Takes ownership of \a other. take() does *not* add a reference, as it assumes ownership
of the callers reference of other.
*/
template<class T>
-QQmlRefPointer<T> &QQmlRefPointer<T>::take(T *other)
+QQmlRefPointer<T> &QQmlRefPointer<T>::adopt(T *other)
{
if (o) o->release();
o = other;
diff --git a/src/qml/qml/ftw/qqmlthread.cpp b/src/qml/qml/ftw/qqmlthread.cpp
index 4addcd9e58..62f6f76a7e 100644
--- a/src/qml/qml/ftw/qqmlthread.cpp
+++ b/src/qml/qml/ftw/qqmlthread.cpp
@@ -377,4 +377,31 @@ void QQmlThread::internalPostMethodToMain(Message *message)
d->unlock();
}
+void QQmlThread::waitForNextMessage()
+{
+ Q_ASSERT(!isThisThread());
+ d->lock();
+ Q_ASSERT(d->m_mainThreadWaiting == false);
+
+ d->m_mainThreadWaiting = true;
+
+ if (d->mainSync || !d->threadList.isEmpty()) {
+ if (d->mainSync) {
+ QQmlThread::Message *message = d->mainSync;
+ unlock();
+ message->call(this);
+ delete message;
+ lock();
+ d->mainSync = 0;
+ wakeOne();
+ } else {
+ d->wait();
+ }
+ }
+
+ d->m_mainThreadWaiting = false;
+ d->unlock();
+}
+
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/ftw/qqmlthread_p.h b/src/qml/qml/ftw/qqmlthread_p.h
index 86d7d2cf19..73658536ac 100644
--- a/src/qml/qml/ftw/qqmlthread_p.h
+++ b/src/qml/qml/ftw/qqmlthread_p.h
@@ -108,6 +108,8 @@ public:
template<typename T, typename T2, class V, class V2, class O>
inline void postMethodToMain(void (O::*Member)(V, V2), const T &, const T2 &);
+ void waitForNextMessage();
+
protected:
virtual void startupThread();
virtual void shutdownThread();
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index e733bcec05..4d84cc82ae 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -23,7 +23,6 @@ SOURCES += \
$$PWD/qqmlvaluetype.cpp \
$$PWD/qqmlaccessors.cpp \
$$PWD/qqmlxmlhttprequest.cpp \
- $$PWD/qqmlwatcher.cpp \
$$PWD/qqmlcleanup.cpp \
$$PWD/qqmlpropertycache.cpp \
$$PWD/qqmlnotifier.cpp \
@@ -35,7 +34,6 @@ SOURCES += \
$$PWD/qqmlimport.cpp \
$$PWD/qqmllist.cpp \
$$PWD/qqmllocale.cpp \
- $$PWD/qqmlabstractexpression.cpp \
$$PWD/qqmljavascriptexpression.cpp \
$$PWD/qqmlabstractbinding.cpp \
$$PWD/qqmlvaluetypeproxybinding.cpp \
@@ -92,7 +90,6 @@ HEADERS += \
$$PWD/qqmlvaluetype_p.h \
$$PWD/qqmlaccessors_p.h \
$$PWD/qqmlxmlhttprequest_p.h \
- $$PWD/qqmlwatcher_p.h \
$$PWD/qqmlcleanup_p.h \
$$PWD/qqmlpropertycache_p.h \
$$PWD/qqmlnotifier_p.h \
@@ -107,7 +104,6 @@ HEADERS += \
$$PWD/qqmlscriptstring_p.h \
$$PWD/qqmllocale_p.h \
$$PWD/qqmlcomponentattached_p.h \
- $$PWD/qqmlabstractexpression_p.h \
$$PWD/qqmljavascriptexpression_p.h \
$$PWD/qqmlabstractbinding_p.h \
$$PWD/qqmlvaluetypeproxybinding_p.h \
diff --git a/src/qml/qml/qqmlabstractbinding.cpp b/src/qml/qml/qqmlabstractbinding.cpp
index 40c8f451b4..4e0763e95a 100644
--- a/src/qml/qml/qqmlabstractbinding.cpp
+++ b/src/qml/qml/qqmlabstractbinding.cpp
@@ -39,24 +39,19 @@
QT_BEGIN_NAMESPACE
-extern QQmlAbstractBinding::VTable QQmlBinding_vtable;
-extern QQmlAbstractBinding::VTable QQmlValueTypeProxyBinding_vtable;
-
-QQmlAbstractBinding::VTable *QQmlAbstractBinding::vTables[] = {
- &QQmlBinding_vtable,
- &QQmlValueTypeProxyBinding_vtable
-};
-
-QQmlAbstractBinding::QQmlAbstractBinding(BindingType bt)
- : m_nextBindingPtr(bt)
+QQmlAbstractBinding::QQmlAbstractBinding()
+ : m_targetIndex(-1)
{
+ Q_ASSERT(!isAddedToObject());
}
QQmlAbstractBinding::~QQmlAbstractBinding()
{
- Q_ASSERT(isAddedToObject() == false);
- Q_ASSERT(nextBinding() == 0);
- Q_ASSERT(*m_mePtr == 0);
+ Q_ASSERT(!ref);
+ Q_ASSERT(!isAddedToObject());
+
+ if (m_nextBinding.data() && !m_nextBinding->ref.deref())
+ delete m_nextBinding.data();
}
/*!
@@ -72,40 +67,45 @@ void QQmlAbstractBinding::addToObject()
Q_ASSERT(!nextBinding());
Q_ASSERT(isAddedToObject() == false);
- QObject *obj = object();
+ QObject *obj = targetObject();
Q_ASSERT(obj);
QQmlData *data = QQmlData::get(obj, true);
int coreIndex;
- if (QQmlPropertyData::decodeValueTypePropertyIndex(propertyIndex(), &coreIndex) != -1) {
+ if (QQmlPropertyData::decodeValueTypePropertyIndex(targetPropertyIndex(), &coreIndex) != -1) {
// Value type
// Find the value type proxy (if there is one)
QQmlValueTypeProxyBinding *proxy = 0;
if (data->hasBindingBit(coreIndex)) {
QQmlAbstractBinding *b = data->bindings;
- while (b && b->propertyIndex() != coreIndex)
+ while (b && b->targetPropertyIndex() != coreIndex)
b = b->nextBinding();
- Q_ASSERT(b && b->bindingType() == QQmlAbstractBinding::ValueTypeProxy);
+ Q_ASSERT(b && b->isValueTypeProxy());
proxy = static_cast<QQmlValueTypeProxyBinding *>(b);
}
if (!proxy) {
proxy = new QQmlValueTypeProxyBinding(obj, coreIndex);
- Q_ASSERT(proxy->propertyIndex() == coreIndex);
- Q_ASSERT(proxy->object() == obj);
+ Q_ASSERT(proxy->targetPropertyIndex() == coreIndex);
+ Q_ASSERT(proxy->targetObject() == obj);
proxy->addToObject();
}
- setNextBinding(proxy->m_bindings);
+ setNextBinding(proxy->m_bindings.data());
proxy->m_bindings = this;
} else {
setNextBinding(data->bindings);
+ if (data->bindings) {
+ data->bindings->ref.deref();
+ Q_ASSERT(data->bindings->ref.refCount > 0);
+ }
data->bindings = this;
+ ref.ref();
data->setBindingBit(obj, coreIndex);
}
@@ -118,95 +118,81 @@ Remove the binding from the object.
*/
void QQmlAbstractBinding::removeFromObject()
{
- if (isAddedToObject()) {
- QObject *obj = object();
- QQmlData *data = QQmlData::get(obj, false);
- Q_ASSERT(data);
-
- int coreIndex;
- if (QQmlPropertyData::decodeValueTypePropertyIndex(propertyIndex(), &coreIndex) != -1) {
-
- // Find the value type binding
- QQmlAbstractBinding *vtbinding = data->bindings;
- while (vtbinding->propertyIndex() != coreIndex) {
- vtbinding = vtbinding->nextBinding();
- Q_ASSERT(vtbinding);
- }
- Q_ASSERT(vtbinding->bindingType() == QQmlAbstractBinding::ValueTypeProxy);
-
- QQmlValueTypeProxyBinding *vtproxybinding =
- static_cast<QQmlValueTypeProxyBinding *>(vtbinding);
-
- QQmlAbstractBinding *binding = vtproxybinding->m_bindings;
- if (binding == this) {
- vtproxybinding->m_bindings = nextBinding();
- } else {
- while (binding->nextBinding() != this) {
- binding = binding->nextBinding();
- Q_ASSERT(binding);
- }
- binding->setNextBinding(nextBinding());
- }
-
- // Value type - we don't remove the proxy from the object. It will sit their happily
- // doing nothing until it is removed by a write, a binding change or it is reused
- // to hold more sub-bindings.
+ if (!isAddedToObject())
+ return;
- } else {
+ setAddedToObject(false);
- if (data->bindings == this) {
- data->bindings = nextBinding();
- } else {
- QQmlAbstractBinding *binding = data->bindings;
- while (binding->nextBinding() != this) {
- binding = binding->nextBinding();
- Q_ASSERT(binding);
- }
- binding->setNextBinding(nextBinding());
- }
-
- data->clearBindingBit(coreIndex);
- }
+ QObject *obj = targetObject();
+ QQmlData *data = QQmlData::get(obj, false);
+ Q_ASSERT(data);
- setNextBinding(0);
- setAddedToObject(false);
- }
-}
+ QQmlAbstractBinding::Ptr next;
+ next = nextBinding();
+ setNextBinding(0);
-void QQmlAbstractBinding::printBindingLoopError(QQmlProperty &prop)
-{
- qmlInfo(prop.object()) << QString(QLatin1String("Binding loop detected for property \"%1\"")).arg(prop.name());
-}
+ int coreIndex;
+ if (QQmlPropertyData::decodeValueTypePropertyIndex(targetPropertyIndex(), &coreIndex) != -1) {
+ // Find the value type binding
+ QQmlAbstractBinding *vtbinding = data->bindings;
+ while (vtbinding->targetPropertyIndex() != coreIndex) {
+ vtbinding = vtbinding->nextBinding();
+ Q_ASSERT(vtbinding);
+ }
+ Q_ASSERT(vtbinding->isValueTypeProxy());
-static void bindingDummyDeleter(QQmlAbstractBinding *)
-{
-}
+ QQmlValueTypeProxyBinding *vtproxybinding =
+ static_cast<QQmlValueTypeProxyBinding *>(vtbinding);
-QQmlAbstractBinding::Pointer QQmlAbstractBinding::weakPointer()
-{
- if (m_mePtr.value().isNull())
- m_mePtr.value() = QSharedPointer<QQmlAbstractBinding>(this, bindingDummyDeleter);
+ QQmlAbstractBinding *binding = vtproxybinding->m_bindings.data();
+ if (binding == this) {
+ vtproxybinding->m_bindings = next;
+ } else {
+ while (binding->nextBinding() != this) {
+ binding = binding->nextBinding();
+ Q_ASSERT(binding);
+ }
+ binding->setNextBinding(next.data());
+ }
- return m_mePtr.value().toWeakRef();
-}
+ // Value type - we don't remove the proxy from the object. It will sit their happily
+ // doing nothing until it is removed by a write, a binding change or it is reused
+ // to hold more sub-bindings.
+ return;
+ }
-void QQmlAbstractBinding::clear()
-{
- if (!m_mePtr.isNull()) {
- **m_mePtr = 0;
- m_mePtr = 0;
+ if (data->bindings == this) {
+ if (next.data())
+ next->ref.ref();
+ data->bindings = next.data();
+ if (!ref.deref())
+ delete this;
+ } else {
+ QQmlAbstractBinding *binding = data->bindings;
+ while (binding->nextBinding() != this) {
+ binding = binding->nextBinding();
+ Q_ASSERT(binding);
+ }
+ binding->setNextBinding(next.data());
}
+
+ data->clearBindingBit(coreIndex);
}
-void QQmlAbstractBinding::default_retargetBinding(QQmlAbstractBinding *, QObject *, int)
+void QQmlAbstractBinding::printBindingLoopError(QQmlProperty &prop)
{
- qFatal("QQmlAbstractBinding::retargetBinding() called on illegal binding.");
+ qmlInfo(prop.object()) << QString(QLatin1String("Binding loop detected for property \"%1\"")).arg(prop.name());
}
-QString QQmlAbstractBinding::default_expression(const QQmlAbstractBinding *)
+QString QQmlAbstractBinding::expression() const
{
return QLatin1String("<Unknown>");
}
+bool QQmlAbstractBinding::isValueTypeProxy() const
+{
+ return false;
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlabstractbinding_p.h b/src/qml/qml/qqmlabstractbinding_p.h
index b5d8181ca5..dd14301aa9 100644
--- a/src/qml/qml/qqmlabstractbinding_p.h
+++ b/src/qml/qml/qqmlabstractbinding_p.h
@@ -46,6 +46,7 @@
//
#include <QtCore/qsharedpointer.h>
+#include <QtCore/qshareddata.h>
#include <private/qtqmlglobal_p.h>
#include <private/qqmlproperty_p.h>
#include <private/qpointervaluepair_p.h>
@@ -56,162 +57,83 @@ class QQmlObjectCreator;
class Q_QML_PRIVATE_EXPORT QQmlAbstractBinding
{
+protected:
+ QQmlAbstractBinding();
public:
- enum DestroyMode {
-
- // The binding should disconnect itself upon destroy
- DisconnectBinding,
-
- // The binding doesn't need to disconnect itself, but it can if it wants to.
- //
- // This is used in QQmlData::destroyed() - at the point at which the bindings are
- // destroyed, the notifiers are already disconnected, so no need to disconnect each
- // binding again.
- //
- // Bindings can use this flag to speed up destruction, especially for v4 bindings
- // disconnecting a single binding might be slow.
- KeepBindingConnected
- };
-
- struct VTable {
- void (*destroy)(QQmlAbstractBinding *, DestroyMode destroyMode);
- QString (*expression)(const QQmlAbstractBinding *);
- int (*propertyIndex)(const QQmlAbstractBinding *);
- QObject *(*object)(const QQmlAbstractBinding *);
- void (*setEnabled)(QQmlAbstractBinding *, bool, QQmlPropertyPrivate::WriteFlags);
- void (*update)(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags);
- void (*retargetBinding)(QQmlAbstractBinding *, QObject *, int);
- };
-
- typedef QWeakPointer<QQmlAbstractBinding> Pointer;
+ virtual ~QQmlAbstractBinding();
- enum BindingType { Binding = 0, ValueTypeProxy = 1 };
- inline BindingType bindingType() const;
+ typedef QExplicitlySharedDataPointer<QQmlAbstractBinding> Ptr;
- // Destroy the binding. Use this instead of calling delete.
- // Bindings are free to implement their own memory management, so the delete operator is
- // not necessarily safe. The default implementation clears the binding, removes it from
- // the object and calls delete.
- void destroy(DestroyMode destroyMode = DisconnectBinding)
- { vtable()->destroy(this, destroyMode); }
+ virtual QString expression() const;
- QString expression() const { return vtable()->expression(this); }
+ virtual bool isValueTypeProxy() const;
// Should return the encoded property index for the binding. Should return this value
// even if the binding is not enabled or added to an object.
// Encoding is: coreIndex | (valueTypeIndex << 16)
- int propertyIndex() const { return vtable()->propertyIndex(this); }
+ int targetPropertyIndex() const { return m_targetIndex; }
// Should return the object for the binding. Should return this object even if the
// binding is not enabled or added to the object.
- QObject *object() const { return vtable()->object(this); }
-
- void setEnabled(bool e) { setEnabled(e, QQmlPropertyPrivate::DontRemoveBinding); }
- void setEnabled(bool e, QQmlPropertyPrivate::WriteFlags f) { vtable()->setEnabled(this, e, f); }
+ QObject *targetObject() const { return m_target.data(); }
- void update() { update(QQmlPropertyPrivate::DontRemoveBinding); }
- void update(QQmlPropertyPrivate::WriteFlags f) { vtable()->update(this, f); }
+ virtual void setEnabled(bool e, QQmlPropertyPrivate::WriteFlags f = QQmlPropertyPrivate::DontRemoveBinding) = 0;
void addToObject();
void removeFromObject();
- static inline Pointer getPointer(QQmlAbstractBinding *p);
static void printBindingLoopError(QQmlProperty &prop);
- // Default implementation for some VTable functions
- template<typename T>
- static void default_destroy(QQmlAbstractBinding *, DestroyMode);
- static QString default_expression(const QQmlAbstractBinding *);
- static void default_retargetBinding(QQmlAbstractBinding *, QObject *, int);
-
-protected:
- QQmlAbstractBinding(BindingType);
- ~QQmlAbstractBinding();
- void clear();
+ inline QQmlAbstractBinding *nextBinding() const;
- // Called by QQmlPropertyPrivate to "move" a binding to a different property.
- // This is only used for alias properties. The default implementation qFatal()'s
- // to ensure that the method is never called for binding types that don't support it.
- void retargetBinding(QObject *o, int i) { vtable()->retargetBinding(this, o, i); }
-private:
- Pointer weakPointer();
+ struct RefCount {
+ RefCount() : refCount(0) {}
+ int refCount;
+ void ref() { ++refCount; }
+ int deref() { return --refCount; }
+ operator int() const { return refCount; }
+ };
+ RefCount ref;
+protected:
friend class QQmlData;
- friend class QQmlComponentPrivate;
friend class QQmlValueTypeProxyBinding;
- friend class QQmlPropertyPrivate;
- friend class QtSharedPointer::ExternalRefCount<QQmlAbstractBinding>;
- friend class QV4Bindings;
friend class QQmlObjectCreator;
- typedef QSharedPointer<QQmlAbstractBinding> SharedPointer;
- // To save memory, we also store the rarely used weakPointer() instance in here
- // We also use the flag bits:
- // m_mePtr.flag1: added to object
- QPointerValuePair<QQmlAbstractBinding*, SharedPointer> m_mePtr;
-
inline void setAddedToObject(bool v);
inline bool isAddedToObject() const;
- inline QQmlAbstractBinding *nextBinding() const;
inline void setNextBinding(QQmlAbstractBinding *);
+ int m_targetIndex;
+ QFlagPointer<QObject> m_target;
// Pointer to the next binding in the linked list of bindings.
- // Being a pointer, the address is always aligned to at least 4 bytes, which means the last two
- // bits of the pointer are free to be used for something else. They are used to store the binding
- // type. The binding type serves as an index into the static vTables array, which is used instead
- // of a compiler-generated vTable. Instead of virtual functions, pointers to static functions in
- // the vTables array are used for dispatching.
- // This saves a compiler-generated pointer to a compiler-generated vTable, and thus reduces
- // the binding object size by sizeof(void*).
- qintptr m_nextBindingPtr;
-
- static VTable *vTables[];
- inline const VTable *vtable() const { return vTables[bindingType()]; }
+ QFlagPointer<QQmlAbstractBinding> m_nextBinding;
};
-QQmlAbstractBinding::Pointer
-QQmlAbstractBinding::getPointer(QQmlAbstractBinding *p)
-{
- return p ? p->weakPointer() : Pointer();
-}
-
void QQmlAbstractBinding::setAddedToObject(bool v)
{
- m_mePtr.setFlagValue(v);
+ m_nextBinding.setFlagValue(v);
}
bool QQmlAbstractBinding::isAddedToObject() const
{
- return m_mePtr.flag();
+ return m_nextBinding.flag();
}
QQmlAbstractBinding *QQmlAbstractBinding::nextBinding() const
{
- return (QQmlAbstractBinding *)(m_nextBindingPtr & ~0x3);
+ return m_nextBinding.data();
}
void QQmlAbstractBinding::setNextBinding(QQmlAbstractBinding *b)
{
- m_nextBindingPtr = qintptr(b) | (m_nextBindingPtr & 0x3);
-}
-
-QQmlAbstractBinding::BindingType QQmlAbstractBinding::bindingType() const
-{
- return (BindingType)(m_nextBindingPtr & 0x3);
-}
-
-template<typename T>
-void QQmlAbstractBinding::default_destroy(QQmlAbstractBinding *This, DestroyMode mode)
-{
- // Assume the binding disconnects itself in the destructor, which for example QQmlBinding
- // does in the destructor of its base class, QQmlJavaScriptExpression
- Q_UNUSED(mode);
-
- This->removeFromObject();
- This->clear();
- delete static_cast<T *>(This);
+ if (b)
+ b->ref.ref();
+ if (m_nextBinding.data() && !m_nextBinding->ref.deref())
+ delete m_nextBinding.data();
+ m_nextBinding = b;
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlabstractexpression.cpp b/src/qml/qml/qqmlabstractexpression.cpp
deleted file mode 100644
index c55c86952c..0000000000
--- a/src/qml/qml/qqmlabstractexpression.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlabstractexpression_p.h"
-
-QT_BEGIN_NAMESPACE
-
-QQmlAbstractExpression::QQmlAbstractExpression()
-: m_prevExpression(0), m_nextExpression(0)
-{
-}
-
-QQmlAbstractExpression::~QQmlAbstractExpression()
-{
- if (m_prevExpression) {
- *m_prevExpression = m_nextExpression;
- if (m_nextExpression)
- m_nextExpression->m_prevExpression = m_prevExpression;
- }
-
- if (m_context.isT2())
- m_context.asT2()->_s = 0;
-}
-
-QQmlContextData *QQmlAbstractExpression::context() const
-{
- if (m_context.isT1()) return m_context.asT1();
- else return m_context.asT2()->_c;
-}
-
-void QQmlAbstractExpression::setContext(QQmlContextData *context)
-{
- if (m_prevExpression) {
- *m_prevExpression = m_nextExpression;
- if (m_nextExpression)
- m_nextExpression->m_prevExpression = m_prevExpression;
- m_prevExpression = 0;
- m_nextExpression = 0;
- }
-
- if (m_context.isT1()) m_context = context;
- else m_context.asT2()->_c = context;
-
- if (context) {
- m_nextExpression = context->expressions;
- if (m_nextExpression)
- m_nextExpression->m_prevExpression = &m_nextExpression;
- m_prevExpression = &context->expressions;
- context->expressions = this;
- }
-}
-
-void QQmlAbstractExpression::refresh()
-{
-}
-
-bool QQmlAbstractExpression::isValid() const
-{
- return context() != 0;
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/qml/qml/qqmlabstractexpression_p.h b/src/qml/qml/qqmlabstractexpression_p.h
deleted file mode 100644
index 82ba010434..0000000000
--- a/src/qml/qml/qqmlabstractexpression_p.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLABSTRACTEXPRESSION_P_H
-#define QQMLABSTRACTEXPRESSION_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <private/qqmlcontext_p.h>
-#include <private/qfieldlist_p.h>
-#include <private/qflagpointer_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class Q_QML_PRIVATE_EXPORT QQmlAbstractExpression
-{
-public:
- QQmlAbstractExpression();
- virtual ~QQmlAbstractExpression();
-
- bool isValid() const;
-
- QQmlContextData *context() const;
- void setContext(QQmlContextData *);
-
- virtual void refresh();
-
- class DeleteWatcher {
- public:
- inline DeleteWatcher(QQmlAbstractExpression *);
- inline ~DeleteWatcher();
- inline bool wasDeleted() const;
- private:
- friend class QQmlAbstractExpression;
- QQmlContextData *_c;
- QQmlAbstractExpression **_w;
- QQmlAbstractExpression *_s;
- };
-
-private:
- friend class QQmlContext;
- friend class QQmlContextData;
- friend class QQmlContextPrivate;
-
- QBiPointer<QQmlContextData, DeleteWatcher> m_context;
- QQmlAbstractExpression **m_prevExpression;
- QQmlAbstractExpression *m_nextExpression;
-};
-
-QQmlAbstractExpression::DeleteWatcher::DeleteWatcher(QQmlAbstractExpression *e)
-: _c(0), _w(0), _s(e)
-{
- if (e->m_context.isT1()) {
- _w = &_s;
- _c = e->m_context.asT1();
- e->m_context = this;
- } else {
- // Another watcher is already registered
- _w = &e->m_context.asT2()->_s;
- }
-}
-
-QQmlAbstractExpression::DeleteWatcher::~DeleteWatcher()
-{
- Q_ASSERT(*_w == 0 || (*_w == _s && _s->m_context.isT2()));
- if (*_w && _s->m_context.asT2() == this)
- _s->m_context = _c;
-}
-
-bool QQmlAbstractExpression::DeleteWatcher::wasDeleted() const
-{
- return *_w == 0;
-}
-
-QT_END_NAMESPACE
-
-#endif // QQMLABSTRACTEXPRESSION_P_H
diff --git a/src/qml/qml/qqmlaccessors_p.h b/src/qml/qml/qqmlaccessors_p.h
index 24cd0b60cb..8b0a587740 100644
--- a/src/qml/qml/qqmlaccessors_p.h
+++ b/src/qml/qml/qqmlaccessors_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLACCESSORS_P_H
#define QQMLACCESSORS_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qtqmlglobal_p.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qvector.h>
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index f223d099e4..f8b737a62a 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -43,43 +43,28 @@
#include <private/qqmlscriptstring_p.h>
#include <private/qqmlcontextwrapper_p.h>
#include <private/qqmlbuiltinfunctions_p.h>
+#include <private/qqmlvmemetaobject_p.h>
+#include <private/qqmlvaluetypewrapper_p.h>
#include <QVariant>
#include <QtCore/qdebug.h>
QT_BEGIN_NAMESPACE
-// Used in qqmlabstractbinding.cpp
-QQmlAbstractBinding::VTable QQmlBinding_vtable = {
- QQmlAbstractBinding::default_destroy<QQmlBinding>,
- QQmlBinding::expression,
- QQmlBinding::propertyIndex,
- QQmlBinding::object,
- QQmlBinding::setEnabled,
- QQmlBinding::update,
- QQmlBinding::retargetBinding
-};
-
-QQmlBinding::Identifier QQmlBinding::Invalid = -1;
-
-static QQmlJavaScriptExpression::VTable QQmlBinding_jsvtable = {
- QQmlBinding::expressionIdentifier,
- QQmlBinding::expressionChanged
-};
-
QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContext *ctxt)
-: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding)
+ : QQmlJavaScriptExpression(),
+ QQmlAbstractBinding()
{
setNotifyOnValueChanged(true);
- QQmlAbstractExpression::setContext(QQmlContextData::get(ctxt));
+ QQmlJavaScriptExpression::setContext(QQmlContextData::get(ctxt));
setScopeObject(obj);
- QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
- v4function.set(v4, qmlBinding(context(), obj, str, QString(), 0));
+ createQmlBinding(context(), obj, str, QString(), 0);
}
QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlContext *ctxt)
-: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding)
+ : QQmlJavaScriptExpression(),
+ QQmlAbstractBinding()
{
if (ctxt && !ctxt->isValid())
return;
@@ -100,51 +85,52 @@ QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlConte
}
setNotifyOnValueChanged(true);
- QQmlAbstractExpression::setContext(QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context));
+ QQmlJavaScriptExpression::setContext(QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context));
setScopeObject(obj ? obj : scriptPrivate->scope);
QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
if (runtimeFunction) {
- v4function.set(v4, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxtdata, scopeObject(), runtimeFunction));
+ m_function.set(v4, QV4::FunctionObject::createQmlFunction(ctxtdata, scopeObject(), runtimeFunction));
} else {
QString code = scriptPrivate->script;
- v4function.set(v4, qmlBinding(context(), scopeObject(), code, url, scriptPrivate->lineNumber));
+ createQmlBinding(context(), scopeObject(), code, url, scriptPrivate->lineNumber);
}
}
QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContextData *ctxt)
-: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding)
+ : QQmlJavaScriptExpression(),
+ QQmlAbstractBinding()
{
setNotifyOnValueChanged(true);
- QQmlAbstractExpression::setContext(ctxt);
+ QQmlJavaScriptExpression::setContext(ctxt);
setScopeObject(obj);
- QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
- v4function.set(v4, qmlBinding(ctxt, obj, str, QString(), 0));
+ createQmlBinding(ctxt, obj, str, QString(), 0);
}
QQmlBinding::QQmlBinding(const QString &str, QObject *obj,
QQmlContextData *ctxt,
const QString &url, quint16 lineNumber, quint16 columnNumber)
-: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding)
+ : QQmlJavaScriptExpression(),
+ QQmlAbstractBinding()
{
Q_UNUSED(columnNumber);
setNotifyOnValueChanged(true);
- QQmlAbstractExpression::setContext(ctxt);
+ QQmlJavaScriptExpression::setContext(ctxt);
setScopeObject(obj);
- QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
- v4function.set(v4, qmlBinding(ctxt, obj, str, url, lineNumber));
+ createQmlBinding(ctxt, obj, str, url, lineNumber);
}
QQmlBinding::QQmlBinding(const QV4::Value &functionPtr, QObject *obj, QQmlContextData *ctxt)
-: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding)
+ : QQmlJavaScriptExpression(),
+ QQmlAbstractBinding()
{
setNotifyOnValueChanged(true);
- QQmlAbstractExpression::setContext(ctxt);
+ QQmlJavaScriptExpression::setContext(ctxt);
setScopeObject(obj);
- v4function.set(functionPtr.asObject()->engine(), functionPtr);
+ m_function.set(functionPtr.as<QV4::Object>()->engine(), functionPtr);
}
QQmlBinding::~QQmlBinding()
@@ -162,90 +148,243 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
return;
// Check that the target has not been deleted
- if (QQmlData::wasDeleted(object()))
+ if (QQmlData::wasDeleted(targetObject()))
return;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
QV4::Scope scope(ep->v4engine());
- QV4::ScopedFunctionObject f(scope, v4function.value());
+ QV4::ScopedFunctionObject f(scope, m_function.value());
Q_ASSERT(f);
- if (!updatingFlag()) {
- QQmlBindingProfiler prof(ep->profiler, f);
- setUpdatingFlag(true);
+ if (updatingFlag()) {
+ QQmlProperty p = QQmlPropertyPrivate::restore(targetObject(), getPropertyData(), 0);
+ QQmlAbstractBinding::printBindingLoopError(p);
+ return;
+ }
+
+ QQmlBindingProfiler prof(ep->profiler, f);
+ setUpdatingFlag(true);
- QQmlAbstractExpression::DeleteWatcher watcher(this);
+ QQmlJavaScriptExpression::DeleteWatcher watcher(this);
- if (m_core.propType == qMetaTypeId<QQmlBinding *>()) {
+ QQmlPropertyData pd = getPropertyData();
- int idx = m_core.coreIndex;
- Q_ASSERT(idx != -1);
+ if (pd.propType == qMetaTypeId<QQmlBinding *>()) {
- QQmlBinding *t = this;
- int status = -1;
- void *a[] = { &t, 0, &status, &flags };
- QMetaObject::metacall(*m_coreObject, QMetaObject::WriteProperty, idx, a);
+ int idx = pd.coreIndex;
+ Q_ASSERT(idx != -1);
- } else {
- ep->referenceScarceResources();
+ QQmlBinding *t = this;
+ int status = -1;
+ void *a[] = { &t, 0, &status, &flags };
+ QMetaObject::metacall(*m_target, QMetaObject::WriteProperty, idx, a);
- bool isUndefined = false;
+ } else {
+ ep->referenceScarceResources();
- QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(context(), f, &isUndefined));
+ bool isUndefined = false;
- bool needsErrorLocationData = false;
- if (!watcher.wasDeleted() && !hasError())
- needsErrorLocationData = !QQmlPropertyPrivate::writeBinding(*m_coreObject, m_core, context(),
- this, result, isUndefined, flags);
+ QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(&isUndefined));
- if (!watcher.wasDeleted()) {
+ bool error = false;
+ if (!watcher.wasDeleted() && isAddedToObject() && !hasError())
+ error = !write(pd, result, isUndefined, flags);
- if (needsErrorLocationData)
- delayedError()->setErrorLocation(f->sourceLocation());
+ if (!watcher.wasDeleted()) {
- if (hasError()) {
- if (!delayedError()->addError(ep)) ep->warning(this->error(context()->engine));
- } else {
- clearError();
- }
+ if (error) {
+ delayedError()->setErrorLocation(f->sourceLocation());
+ delayedError()->setErrorObject(m_target.data());
+ }
+ if (hasError()) {
+ if (!delayedError()->addError(ep)) ep->warning(this->error(context()->engine));
+ } else {
+ clearError();
}
- ep->dereferenceScarceResources();
}
- if (!watcher.wasDeleted())
- setUpdatingFlag(false);
- } else {
- QQmlProperty p = property();
- QQmlAbstractBinding::printBindingLoopError(p);
+ ep->dereferenceScarceResources();
}
+
+ if (!watcher.wasDeleted())
+ setUpdatingFlag(false);
+}
+
+// Returns true if successful, false if an error description was set on expression
+bool QQmlBinding::write(const QQmlPropertyData &core,
+ const QV4::Value &result, bool isUndefined,
+ QQmlPropertyPrivate::WriteFlags flags)
+{
+ Q_ASSERT(m_target.data());
+ Q_ASSERT(core.coreIndex != -1);
+
+ QQmlEngine *engine = context()->engine;
+ QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(engine);
+
+#define QUICK_STORE(cpptype, conversion) \
+ { \
+ cpptype o = (conversion); \
+ int status = -1; \
+ void *argv[] = { &o, 0, &status, &flags }; \
+ QMetaObject::metacall(m_target.data(), QMetaObject::WriteProperty, core.coreIndex, argv); \
+ return true; \
+ } \
+
+
+ if (!isUndefined && !core.isValueTypeVirtual()) {
+ switch (core.propType) {
+ case QMetaType::Int:
+ if (result.isInteger())
+ QUICK_STORE(int, result.integerValue())
+ else if (result.isNumber())
+ QUICK_STORE(int, result.doubleValue())
+ break;
+ case QMetaType::Double:
+ if (result.isNumber())
+ QUICK_STORE(double, result.asDouble())
+ break;
+ case QMetaType::Float:
+ if (result.isNumber())
+ QUICK_STORE(float, result.asDouble())
+ break;
+ case QMetaType::QString:
+ if (result.isString())
+ QUICK_STORE(QString, result.toQStringNoThrow())
+ break;
+ default:
+ if (const QV4::QQmlValueTypeWrapper *vtw = result.as<const QV4::QQmlValueTypeWrapper>()) {
+ if (vtw->d()->valueType->typeId == core.propType) {
+ return vtw->write(m_target.data(), core.coreIndex);
+ }
+ }
+ break;
+ }
+ }
+#undef QUICK_STORE
+
+ int type = core.isValueTypeVirtual() ? core.valueTypePropType : core.propType;
+
+ QQmlJavaScriptExpression::DeleteWatcher watcher(this);
+
+ QVariant value;
+ bool isVarProperty = core.isVarProperty();
+
+ if (isUndefined) {
+ } else if (core.isQList()) {
+ value = QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QObject *> >());
+ } else if (result.isNull() && core.isQObject()) {
+ value = QVariant::fromValue((QObject *)0);
+ } else if (core.propType == qMetaTypeId<QList<QUrl> >()) {
+ value = QQmlPropertyPrivate::resolvedUrlSequence(QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QUrl> >()), context());
+ } else if (!isVarProperty && type != qMetaTypeId<QJSValue>()) {
+ value = QV8Engine::getV4(v8engine)->toVariant(result, type);
+ }
+
+ if (hasError()) {
+ return false;
+ } else if (isVarProperty) {
+ const QV4::FunctionObject *f = result.as<QV4::FunctionObject>();
+ if (f && f->isBinding()) {
+ // we explicitly disallow this case to avoid confusion. Users can still store one
+ // in an array in a var property if they need to, but the common case is user error.
+ delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
+ return false;
+ }
+
+ QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(m_target.data());
+ Q_ASSERT(vmemo);
+ vmemo->setVMEProperty(core.coreIndex, result);
+ } else if (isUndefined && core.isResettable()) {
+ void *args[] = { 0 };
+ QMetaObject::metacall(m_target.data(), QMetaObject::ResetProperty, core.coreIndex, args);
+ } else if (isUndefined && type == qMetaTypeId<QVariant>()) {
+ QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, QVariant(), context(), flags);
+ } else if (type == qMetaTypeId<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."));
+ return false;
+ }
+ QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, QVariant::fromValue(
+ QJSValue(QV8Engine::getV4(v8engine), result.asReturnedValue())),
+ context(), flags);
+ } else if (isUndefined) {
+ QString errorStr = QLatin1String("Unable to assign [undefined] to ");
+ if (!QMetaType::typeName(type))
+ errorStr += QLatin1String("[unknown property type]");
+ else
+ errorStr += QLatin1String(QMetaType::typeName(type));
+ delayedError()->setErrorDescription(errorStr);
+ return false;
+ } else if (const QV4::FunctionObject *f = result.as<QV4::FunctionObject>()) {
+ if (f->isBinding())
+ delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
+ else
+ delayedError()->setErrorDescription(QLatin1String("Unable to assign a function to a property of any type other than var."));
+ return false;
+ } else if (!QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, value, context(), flags)) {
+
+ if (watcher.wasDeleted())
+ return true;
+
+ const char *valueType = 0;
+ const char *propertyType = 0;
+
+ if (value.userType() == QMetaType::QObjectStar) {
+ if (QObject *o = *(QObject *const *)value.constData()) {
+ valueType = o->metaObject()->className();
+
+ QQmlMetaObject propertyMetaObject = QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate::get(engine), type);
+ if (!propertyMetaObject.isNull())
+ propertyType = propertyMetaObject.className();
+ }
+ } else if (value.userType() != QVariant::Invalid) {
+ if (value.userType() == QMetaType::VoidStar)
+ valueType = "null";
+ else
+ valueType = QMetaType::typeName(value.userType());
+ }
+
+ if (!valueType)
+ valueType = "undefined";
+ if (!propertyType)
+ propertyType = QMetaType::typeName(type);
+ if (!propertyType)
+ propertyType = "[unknown property type]";
+
+ delayedError()->setErrorDescription(QLatin1String("Unable to assign ") +
+ QLatin1String(valueType) +
+ QLatin1String(" to ") +
+ QLatin1String(propertyType));
+ return false;
+ }
+
+ return true;
}
QVariant QQmlBinding::evaluate()
{
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
- QV4::Scope scope(ep->v4engine());
ep->referenceScarceResources();
bool isUndefined = false;
- QV4::ScopedValue f(scope, v4function.value());
- QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(context(), f, &isUndefined));
+ QV4::Scope scope(ep->v4engine());
+ QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(&isUndefined));
ep->dereferenceScarceResources();
return scope.engine->toVariant(result, qMetaTypeId<QList<QObject*> >());
}
-QString QQmlBinding::expressionIdentifier(QQmlJavaScriptExpression *e)
+QString QQmlBinding::expressionIdentifier()
{
- QQmlBinding *This = static_cast<QQmlBinding *>(e);
-
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(This->context()->engine);
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
QV4::Scope scope(ep->v4engine());
- QV4::ScopedValue f(scope, This->v4function.value());
- QV4::Function *function = f->asFunctionObject()->function();
+ QV4::ScopedValue f(scope, m_function.value());
+ QV4::Function *function = f->as<QV4::FunctionObject>()->function();
QString url = function->sourceFile();
quint16 lineNumber = function->compiledFunction->location.line;
@@ -254,10 +393,9 @@ QString QQmlBinding::expressionIdentifier(QQmlJavaScriptExpression *e)
return url + QLatin1Char(':') + QString::number(lineNumber) + QLatin1Char(':') + QString::number(columnNumber);
}
-void QQmlBinding::expressionChanged(QQmlJavaScriptExpression *e)
+void QQmlBinding::expressionChanged()
{
- QQmlBinding *This = static_cast<QQmlBinding *>(e);
- This->update();
+ update();
}
void QQmlBinding::refresh()
@@ -265,36 +403,6 @@ void QQmlBinding::refresh()
update();
}
-QString QQmlBinding::expression(const QQmlAbstractBinding *This)
-{
- return static_cast<const QQmlBinding *>(This)->expression();
-}
-
-int QQmlBinding::propertyIndex(const QQmlAbstractBinding *This)
-{
- return static_cast<const QQmlBinding *>(This)->propertyIndex();
-}
-
-QObject *QQmlBinding::object(const QQmlAbstractBinding *This)
-{
- return static_cast<const QQmlBinding *>(This)->object();
-}
-
-void QQmlBinding::setEnabled(QQmlAbstractBinding *This, bool e, QQmlPropertyPrivate::WriteFlags f)
-{
- static_cast<QQmlBinding *>(This)->setEnabled(e, f);
-}
-
-void QQmlBinding::update(QQmlAbstractBinding *This , QQmlPropertyPrivate::WriteFlags f)
-{
- static_cast<QQmlBinding *>(This)->update(f);
-}
-
-void QQmlBinding::retargetBinding(QQmlAbstractBinding *This, QObject *o, int i)
-{
- static_cast<QQmlBinding *>(This)->retargetBinding(o, i);
-}
-
void QQmlBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags)
{
setEnabledFlag(e);
@@ -307,44 +415,92 @@ void QQmlBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags)
QString QQmlBinding::expression() const
{
QV4::Scope scope(QQmlEnginePrivate::get(context()->engine)->v4engine());
- QV4::ScopedValue v(scope, v4function.value());
+ QV4::ScopedValue v(scope, m_function.value());
return v->toQStringNoThrow();
}
-QObject *QQmlBinding::object() const
+void QQmlBinding::setTarget(const QQmlProperty &prop)
{
- if (m_coreObject.hasValue()) return m_coreObject.constValue()->target;
- else return *m_coreObject;
+ setTarget(prop.object(), QQmlPropertyPrivate::get(prop)->core);
}
-int QQmlBinding::propertyIndex() const
+void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core)
{
- if (m_coreObject.hasValue()) return m_coreObject.constValue()->targetProperty;
- else return m_core.encodedIndex();
-}
+ m_target = object;
-void QQmlBinding::retargetBinding(QObject *t, int i)
-{
- m_coreObject.value().target = t;
- m_coreObject.value().targetProperty = i;
-}
+ if (!object) {
+ m_targetIndex = -1;
+ return;
+ }
-void QQmlBinding::setTarget(const QQmlProperty &prop)
-{
- setTarget(prop.object(), QQmlPropertyPrivate::get(prop)->core,
- QQmlPropertyPrivate::get(prop)->context);
-}
+ QQmlPropertyData pd = core;
-void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core, QQmlContextData *ctxt)
-{
- m_coreObject = object;
- m_core = core;
- m_ctxt = ctxt;
+ while (pd.isAlias()) {
+ int coreIndex = pd.coreIndex;
+ int valueTypeIndex = pd.getValueTypeCoreIndex();
+ QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
+
+ int aValueTypeIndex;
+ if (!vme->aliasTarget(coreIndex, &object, &coreIndex, &aValueTypeIndex)) {
+ m_target = 0;
+ m_targetIndex = -1;
+ return;
+ }
+ if (valueTypeIndex == -1)
+ valueTypeIndex = aValueTypeIndex;
+
+ QQmlData *data = QQmlData::get(object, false);
+ if (!data || !data->propertyCache) {
+ m_target = 0;
+ m_targetIndex = -1;
+ return;
+ }
+ QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex);
+ Q_ASSERT(propertyData);
+
+ m_target = object;
+ pd = *propertyData;
+ if (valueTypeIndex != -1) {
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(pd.propType);
+ Q_ASSERT(valueTypeMetaObject);
+ QMetaProperty vtProp = valueTypeMetaObject->property(valueTypeIndex);
+ pd.setFlags(pd.getFlags() | QQmlPropertyData::IsValueTypeVirtual);
+ pd.valueTypeFlags = QQmlPropertyData::flagsForProperty(vtProp);
+ pd.valueTypePropType = vtProp.userType();
+ pd.valueTypeCoreIndex = valueTypeIndex;
+ }
+ }
+ m_targetIndex = pd.encodedIndex();
+
+ QQmlData *data = QQmlData::get(*m_target, true);
+ if (!data->propertyCache) {
+ data->propertyCache = QQmlEnginePrivate::get(context()->engine)->cache(m_target->metaObject());
+ data->propertyCache->addref();
+ }
}
-QQmlProperty QQmlBinding::property() const
+QQmlPropertyData QQmlBinding::getPropertyData() const
{
- return QQmlPropertyPrivate::restore(object(), m_core, *m_ctxt);
+ int coreIndex;
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(m_targetIndex, &coreIndex);
+
+ QQmlData *data = QQmlData::get(*m_target, false);
+ Q_ASSERT(data && data->propertyCache);
+
+ QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex);
+ Q_ASSERT(propertyData);
+
+ QQmlPropertyData d = *propertyData;
+ if (valueTypeIndex != -1) {
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d.propType);
+ Q_ASSERT(valueTypeMetaObject);
+ QMetaProperty vtProp = valueTypeMetaObject->property(valueTypeIndex);
+ d.setFlags(d.getFlags() | QQmlPropertyData::IsValueTypeVirtual);
+ d.valueTypeFlags = QQmlPropertyData::flagsForProperty(vtProp);
+ d.valueTypePropType = vtProp.userType();
+ d.valueTypeCoreIndex = valueTypeIndex;
+ }
+ return d;
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index 1e440b2e86..a435847819 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -57,16 +57,15 @@
#include <private/qpointervaluepair_p.h>
#include <private/qqmlabstractbinding_p.h>
-#include <private/qqmlabstractexpression_p.h>
#include <private/qqmljavascriptexpression_p.h>
QT_BEGIN_NAMESPACE
class QQmlContext;
class Q_QML_PRIVATE_EXPORT QQmlBinding : public QQmlJavaScriptExpression,
- public QQmlAbstractExpression,
public QQmlAbstractBinding
{
+ friend class QQmlAbstractBinding;
public:
QQmlBinding(const QString &, QObject *, QQmlContext *);
QQmlBinding(const QQmlScriptString &, QObject *, QQmlContext *);
@@ -74,84 +73,62 @@ public:
QQmlBinding(const QString &, QObject *, QQmlContextData *,
const QString &url, quint16 lineNumber, quint16 columnNumber);
QQmlBinding(const QV4::Value &, QObject *, QQmlContextData *);
+ ~QQmlBinding();
void setTarget(const QQmlProperty &);
- void setTarget(QObject *, const QQmlPropertyData &, QQmlContextData *);
- QQmlProperty property() const;
+ void setTarget(QObject *, const QQmlPropertyData &);
void setNotifyOnValueChanged(bool);
- // Inherited from QQmlAbstractExpression
+ // Inherited from QQmlJavaScriptExpression
virtual void refresh();
- // "Inherited" from QQmlAbstractBinding
- static QString expression(const QQmlAbstractBinding *);
- static int propertyIndex(const QQmlAbstractBinding *);
- static QObject *object(const QQmlAbstractBinding *);
- static void setEnabled(QQmlAbstractBinding *, bool, QQmlPropertyPrivate::WriteFlags);
- static void update(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags);
- static void retargetBinding(QQmlAbstractBinding *, QObject *, int);
-
- void setEnabled(bool, QQmlPropertyPrivate::WriteFlags flags);
- void update(QQmlPropertyPrivate::WriteFlags flags);
- void update() { update(QQmlPropertyPrivate::DontRemoveBinding); }
-
- QString expression() const;
- QObject *object() const;
- int propertyIndex() const;
- void retargetBinding(QObject *, int);
+ // Inherited from QQmlAbstractBinding
+ virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding);
+ virtual QString expression() const;
+ void update(QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding);
typedef int Identifier;
- static Identifier Invalid;
+ enum {
+ Invalid = -1
+ };
QVariant evaluate();
- static QString expressionIdentifier(QQmlJavaScriptExpression *);
- static void expressionChanged(QQmlJavaScriptExpression *);
-
-protected:
- friend class QQmlAbstractBinding;
- ~QQmlBinding();
+ virtual QString expressionIdentifier();
+ virtual void expressionChanged();
private:
- QV4::PersistentValue v4function;
-
inline bool updatingFlag() const;
inline void setUpdatingFlag(bool);
inline bool enabledFlag() const;
inline void setEnabledFlag(bool);
+ QQmlPropertyData getPropertyData() const;
- struct Retarget {
- QObject *target;
- int targetProperty;
- };
+ bool write(const QQmlPropertyData &core,
+ const QV4::Value &result, bool isUndefined,
+ QQmlPropertyPrivate::WriteFlags flags);
- QPointerValuePair<QObject, Retarget> m_coreObject;
- QQmlPropertyData m_core;
- // We store some flag bits in the following flag pointers.
- // m_ctxt:flag1 - updatingFlag
- // m_ctxt:flag2 - enabledFlag
- QFlagPointer<QQmlContextData> m_ctxt;
};
bool QQmlBinding::updatingFlag() const
{
- return m_ctxt.flag();
+ return m_target.flag();
}
void QQmlBinding::setUpdatingFlag(bool v)
{
- m_ctxt.setFlagValue(v);
+ m_target.setFlagValue(v);
}
bool QQmlBinding::enabledFlag() const
{
- return m_ctxt.flag2();
+ return m_target.flag2();
}
void QQmlBinding::setEnabledFlag(bool v)
{
- m_ctxt.setFlag2Value(v);
+ m_target.setFlag2Value(v);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index 766e657c59..477a517e32 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -43,11 +43,12 @@
#include "qqmlcontext.h"
#include "qqmlglobal_p.h"
#include <private/qqmlprofiler_p.h>
-#include <private/qv4debugservice_p.h>
+#include <private/qqmldebugconnector_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#include <private/qqmlcompiler_p.h>
#include "qqmlinfo.h"
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <QtCore/qstringbuilder.h>
#include <QtCore/qdebug.h>
@@ -55,71 +56,79 @@
QT_BEGIN_NAMESPACE
-static QQmlJavaScriptExpression::VTable QQmlBoundSignalExpression_jsvtable = {
- QQmlBoundSignalExpression::expressionIdentifier,
- QQmlBoundSignalExpression::expressionChanged
-};
-
-QQmlBoundSignalExpression::ExtraData::ExtraData(const QString &handlerName, const QString &parameterString,
- const QString &expression, const QString &fileName,
- quint16 line, quint16 column)
- : m_handlerName(handlerName),
- m_parameterString(parameterString),
- m_expression(expression),
- m_sourceLocation(fileName, line, column)
-{
-}
-
QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
QQmlContextData *ctxt, QObject *scope, const QString &expression,
const QString &fileName, quint16 line, quint16 column,
const QString &handlerName,
const QString &parameterString)
- : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable),
+ : QQmlJavaScriptExpression(),
m_index(index),
- m_target(target),
- m_extra(new ExtraData(handlerName, parameterString, expression, fileName, line, column))
+ m_target(target)
{
- setExpressionFunctionValid(false);
- setInvalidParameterName(false);
-
init(ctxt, scope);
+
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine());
+ QV4::ExecutionEngine *v4 = ep->v4engine();
+
+ QString function;
+
+ // Add some leading whitespace to account for the binding's column offset.
+ // It's 2 off because a, we start counting at 1 and b, the '(' below is not counted.
+ function.fill(QChar(QChar::Space), qMax(column, (quint16)2) - 2);
+ function += QStringLiteral("(function ");
+ function += handlerName;
+ function += QLatin1Char('(');
+
+ if (parameterString.isEmpty()) {
+ QString error;
+ //TODO: look at using the property cache here (as in the compiler)
+ // for further optimization
+ QMetaMethod signal = QMetaObjectPrivate::signal(m_target->metaObject(), m_index);
+ function += QQmlPropertyCache::signalParameterStringForJS(v4, signal.parameterNames(), &error);
+
+ if (!error.isEmpty()) {
+ qmlInfo(scopeObject()) << error;
+ return;
+ }
+ } else
+ function += parameterString;
+
+ function += QStringLiteral(") { ");
+ function += expression;
+ function += QStringLiteral(" })");
+
+ m_function.set(v4, evalFunction(context(), scopeObject(), function, fileName, line));
+
+ if (m_function.isNullOrUndefined())
+ return; // could not evaluate function. Not valid.
+
}
QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, QQmlContextData *ctxt, QObject *scope, const QV4::Value &function)
- : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable),
+ : QQmlJavaScriptExpression(),
m_index(index),
- m_function(function.asObject()->engine(), function),
- m_target(target),
- m_extra(0)
+ m_target(target)
{
- setExpressionFunctionValid(true);
- setInvalidParameterName(false);
-
+ m_function.set(function.as<QV4::Object>()->engine(), function);
init(ctxt, scope);
}
QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, QQmlContextData *ctxt, QObject *scope, QV4::Function *runtimeFunction)
- : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable),
+ : QQmlJavaScriptExpression(),
m_index(index),
- m_target(target),
- m_extra(0)
+ m_target(target)
{
- setExpressionFunctionValid(true);
- setInvalidParameterName(false);
-
// It's important to call init first, because m_index gets remapped in case of cloned signals.
init(ctxt, scope);
QMetaMethod signal = QMetaObjectPrivate::signal(m_target->metaObject(), m_index);
QString error;
QV4::ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(ctxt->engine);
- m_function.set(engine, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, scope, runtimeFunction, signal.parameterNames(), &error));
+ m_function.set(engine, QV4::FunctionObject::createQmlFunction(ctxt, scope, runtimeFunction, signal.parameterNames(), &error));
if (!error.isEmpty()) {
qmlInfo(scopeObject()) << error;
- setInvalidParameterName(true);
- } else
- setInvalidParameterName(false);
+ m_function.clear();
+ }
}
void QQmlBoundSignalExpression::init(QQmlContextData *ctxt, QObject *scope)
@@ -134,34 +143,30 @@ void QQmlBoundSignalExpression::init(QQmlContextData *ctxt, QObject *scope)
QQmlBoundSignalExpression::~QQmlBoundSignalExpression()
{
- delete m_extra.data();
}
-QString QQmlBoundSignalExpression::expressionIdentifier(QQmlJavaScriptExpression *e)
+QString QQmlBoundSignalExpression::expressionIdentifier()
{
- QQmlBoundSignalExpression *This = static_cast<QQmlBoundSignalExpression *>(e);
- QQmlSourceLocation loc = This->sourceLocation();
+ QQmlSourceLocation loc = sourceLocation();
return loc.sourceFile + QLatin1Char(':') + QString::number(loc.line);
}
-void QQmlBoundSignalExpression::expressionChanged(QQmlJavaScriptExpression *)
+void QQmlBoundSignalExpression::expressionChanged()
{
// bound signals do not notify on change.
}
QQmlSourceLocation QQmlBoundSignalExpression::sourceLocation() const
{
- if (expressionFunctionValid()) {
- QV4::Function *f = function();
- Q_ASSERT(f);
+ QV4::Function *f = function();
+ if (f) {
QQmlSourceLocation loc;
loc.sourceFile = f->sourceFile();
loc.line = f->compiledFunction->location.line;
loc.column = f->compiledFunction->location.column;
return loc;
}
- Q_ASSERT(!m_extra.isNull());
- return m_extra->m_sourceLocation;
+ return QQmlSourceLocation();
}
QString QQmlBoundSignalExpression::expression() const
@@ -171,10 +176,8 @@ QString QQmlBoundSignalExpression::expression() const
QV4::Scope scope(QQmlEnginePrivate::get(engine())->v4engine());
QV4::ScopedValue v(scope, m_function.value());
return v->toQStringNoThrow();
- } else {
- Q_ASSERT(!m_extra.isNull());
- return m_extra->m_expression;
}
+ return QString();
}
QV4::Function *QQmlBoundSignalExpression::function() const
@@ -194,108 +197,79 @@ void QQmlBoundSignalExpression::evaluate(void **a)
{
Q_ASSERT (context() && engine());
- if (invalidParameterName())
+ if (!expressionFunctionValid())
return;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine());
QV4::Scope scope(ep->v4engine());
ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
- {
- if (!expressionFunctionValid()) {
- Q_ASSERT(!m_extra.isNull());
- QString expression;
-
- // Add some leading whitespace to account for the binding's column offset.
- // It's 2 off because a, we start counting at 1 and b, the '(' below is not counted.
- expression.fill(QChar(QChar::Space), qMax(m_extra->m_sourceLocation.column, (quint16)2) - 2);
- expression += QStringLiteral("(function ");
- expression += m_extra->m_handlerName;
- expression += QLatin1Char('(');
-
- if (m_extra->m_parameterString.isEmpty()) {
- QString error;
- //TODO: look at using the property cache here (as in the compiler)
- // for further optimization
- QMetaMethod signal = QMetaObjectPrivate::signal(m_target->metaObject(), m_index);
- expression += QQmlPropertyCache::signalParameterStringForJS(scope.engine, signal.parameterNames(), &error);
-
- if (!error.isEmpty()) {
- qmlInfo(scopeObject()) << error;
- setInvalidParameterName(true);
- ep->dereferenceScarceResources();
- return;
- }
- } else
- expression += m_extra->m_parameterString;
-
- expression += QStringLiteral(") { ");
- expression += m_extra->m_expression;
- expression += QStringLiteral(" })");
-
- m_extra->m_expression.clear();
- m_extra->m_handlerName.clear();
- m_extra->m_parameterString.clear();
-
- m_function.set(scope.engine, evalFunction(context(), scopeObject(), expression,
- m_extra->m_sourceLocation.sourceFile, m_extra->m_sourceLocation.line, &m_extra->m_v8qmlscope));
-
- if (m_function.isNullOrUndefined()) {
- ep->dereferenceScarceResources();
- return; // could not evaluate function. Not valid.
- }
-
- setExpressionFunctionValid(true);
- }
- QVarLengthArray<int, 9> dummy;
- //TODO: lookup via signal index rather than method index as an optimization
- int methodIndex = QMetaObjectPrivate::signal(m_target->metaObject(), m_index).methodIndex();
- int *argsTypes = QQmlMetaObject(m_target).methodParameterTypes(methodIndex, dummy, 0);
- int argCount = argsTypes ? *argsTypes : 0;
-
- QV4::ScopedValue f(scope, m_function.value());
- QV4::ScopedCallData callData(scope, argCount);
- for (int ii = 0; ii < argCount; ++ii) {
- int type = argsTypes[ii + 1];
- //### ideally we would use metaTypeToJS, however it currently gives different results
- // for several cases (such as QVariant type and QObject-derived types)
- //args[ii] = engine->metaTypeToJS(type, a[ii + 1]);
- if (type == QMetaType::QVariant) {
- callData->args[ii] = scope.engine->fromVariant(*((QVariant *)a[ii + 1]));
- } else if (type == QMetaType::Int) {
- //### optimization. Can go away if we switch to metaTypeToJS, or be expanded otherwise
- callData->args[ii] = QV4::Primitive::fromInt32(*reinterpret_cast<const int*>(a[ii + 1]));
- } else if (type == qMetaTypeId<QQmlV4Handle>()) {
- callData->args[ii] = *reinterpret_cast<QQmlV4Handle *>(a[ii + 1]);
- } else if (ep->isQObject(type)) {
- if (!*reinterpret_cast<void* const *>(a[ii + 1]))
- callData->args[ii] = QV4::Primitive::nullValue();
- else
- callData->args[ii] = QV4::QObjectWrapper::wrap(ep->v4engine(), *reinterpret_cast<QObject* const *>(a[ii + 1]));
- } else {
- callData->args[ii] = scope.engine->fromVariant(QVariant(type, a[ii + 1]));
- }
+ QVarLengthArray<int, 9> dummy;
+ //TODO: lookup via signal index rather than method index as an optimization
+ int methodIndex = QMetaObjectPrivate::signal(m_target->metaObject(), m_index).methodIndex();
+ int *argsTypes = QQmlMetaObject(m_target).methodParameterTypes(methodIndex, dummy, 0);
+ int argCount = argsTypes ? *argsTypes : 0;
+
+ QV4::ScopedCallData callData(scope, argCount);
+ for (int ii = 0; ii < argCount; ++ii) {
+ int type = argsTypes[ii + 1];
+ //### ideally we would use metaTypeToJS, however it currently gives different results
+ // for several cases (such as QVariant type and QObject-derived types)
+ //args[ii] = engine->metaTypeToJS(type, a[ii + 1]);
+ if (type == QMetaType::QVariant) {
+ callData->args[ii] = scope.engine->fromVariant(*((QVariant *)a[ii + 1]));
+ } else if (type == QMetaType::Int) {
+ //### optimization. Can go away if we switch to metaTypeToJS, or be expanded otherwise
+ callData->args[ii] = QV4::Primitive::fromInt32(*reinterpret_cast<const int*>(a[ii + 1]));
+ } else if (type == qMetaTypeId<QQmlV4Handle>()) {
+ callData->args[ii] = *reinterpret_cast<QQmlV4Handle *>(a[ii + 1]);
+ } else if (ep->isQObject(type)) {
+ if (!*reinterpret_cast<void* const *>(a[ii + 1]))
+ callData->args[ii] = QV4::Primitive::nullValue();
+ else
+ callData->args[ii] = QV4::QObjectWrapper::wrap(ep->v4engine(), *reinterpret_cast<QObject* const *>(a[ii + 1]));
+ } else {
+ callData->args[ii] = scope.engine->fromVariant(QVariant(type, a[ii + 1]));
}
-
- QQmlJavaScriptExpression::evaluate(context(), f, callData, 0);
}
+
+ QQmlJavaScriptExpression::evaluate(callData, 0);
+
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
}
////////////////////////////////////////////////////////////////////////
-QQmlAbstractBoundSignal::QQmlAbstractBoundSignal()
-: m_prevSignal(0), m_nextSignal(0)
+
+/*! \internal
+ \a signal MUST be in the signal index range (see QObjectPrivate::signalIndex()).
+ This is different from QMetaMethod::methodIndex().
+*/
+QQmlBoundSignal::QQmlBoundSignal(QObject *target, int signal, QObject *owner,
+ QQmlEngine *engine)
+ : QQmlNotifierEndpoint(QQmlNotifierEndpoint::QQmlBoundSignal),
+ m_prevSignal(0), m_nextSignal(0),
+ m_expression(0)
{
+ addToObject(owner);
+
+ /*
+ If this is a cloned method, connect to the 'original'. For example,
+ for the signal 'void aSignal(int parameter = 0)', if the method
+ index refers to 'aSignal()', get the index of 'aSignal(int)'.
+ This ensures that 'parameter' will be available from QML.
+ */
+ signal = QQmlPropertyCache::originalClone(target, signal);
+ QQmlNotifierEndpoint::connect(target, signal, engine);
}
-QQmlAbstractBoundSignal::~QQmlAbstractBoundSignal()
+QQmlBoundSignal::~QQmlBoundSignal()
{
removeFromObject();
}
-void QQmlAbstractBoundSignal::addToObject(QObject *obj)
+void QQmlBoundSignal::addToObject(QObject *obj)
{
Q_ASSERT(!m_prevSignal);
Q_ASSERT(obj);
@@ -308,7 +282,7 @@ void QQmlAbstractBoundSignal::addToObject(QObject *obj)
data->signalHandlers = this;
}
-void QQmlAbstractBoundSignal::removeFromObject()
+void QQmlBoundSignal::removeFromObject()
{
if (m_prevSignal) {
*m_prevSignal = m_nextSignal;
@@ -318,40 +292,6 @@ void QQmlAbstractBoundSignal::removeFromObject()
}
}
-/*! \internal
- \a signal MUST be in the signal index range (see QObjectPrivate::signalIndex()).
- This is different from QMetaMethod::methodIndex().
-*/
-QQmlBoundSignal::QQmlBoundSignal(QObject *target, int signal, QObject *owner,
- QQmlEngine *engine)
-: m_expression(0), m_index(signal), m_isEvaluating(false)
-{
- addToObject(owner);
- setCallback(QQmlNotifierEndpoint::QQmlBoundSignal);
-
- /*
- If this is a cloned method, connect to the 'original'. For example,
- for the signal 'void aSignal(int parameter = 0)', if the method
- index refers to 'aSignal()', get the index of 'aSignal(int)'.
- This ensures that 'parameter' will be available from QML.
- */
- m_index = QQmlPropertyCache::originalClone(target, m_index);
- QQmlNotifierEndpoint::connect(target, m_index, engine);
-}
-
-QQmlBoundSignal::~QQmlBoundSignal()
-{
- m_expression = 0;
-}
-
-/*!
- Returns the signal index in the range returned by QObjectPrivate::signalIndex().
- This is different from QMetaMethod::methodIndex().
-*/
-int QQmlBoundSignal::index() const
-{
- return m_index;
-}
/*!
Returns the signal expression.
@@ -362,45 +302,29 @@ QQmlBoundSignalExpression *QQmlBoundSignal::expression() const
}
/*!
- Sets the signal expression to \a e. Returns the current signal expression,
- or null if there is no signal expression.
+ Sets the signal expression to \a e.
- The QQmlBoundSignal instance adds a reference to \a e. The caller
- assumes ownership of the returned QQmlBoundSignalExpression reference.
+ The QQmlBoundSignal instance takes ownership of \a e (and does not add a reference).
*/
-QQmlBoundSignalExpressionPointer QQmlBoundSignal::setExpression(QQmlBoundSignalExpression *e)
+void QQmlBoundSignal::takeExpression(QQmlBoundSignalExpression *e)
{
- QQmlBoundSignalExpressionPointer rv = m_expression;
- m_expression = e;
- if (m_expression) m_expression->setNotifyOnValueChanged(false);
- return rv;
-}
-
-/*!
- Sets the signal expression to \a e. Returns the current signal expression,
- or null if there is no signal expression.
-
- The QQmlBoundSignal instance takes ownership of \a e (and does not add a reference). The caller
- assumes ownership of the returned QQmlBoundSignalExpression reference.
-*/
-QQmlBoundSignalExpressionPointer QQmlBoundSignal::takeExpression(QQmlBoundSignalExpression *e)
-{
- QQmlBoundSignalExpressionPointer rv = m_expression;
m_expression.take(e);
- if (m_expression) m_expression->setNotifyOnValueChanged(false);
- return rv;
+ if (m_expression)
+ m_expression->setNotifyOnValueChanged(false);
}
void QQmlBoundSignal_callback(QQmlNotifierEndpoint *e, void **a)
{
QQmlBoundSignal *s = static_cast<QQmlBoundSignal*>(e);
+
if (!s->m_expression)
return;
- if (QQmlDebugService::isDebuggingEnabled())
- QV4DebugService::instance()->signalEmitted(QString::fromLatin1(QMetaObjectPrivate::signal(s->m_expression->target()->metaObject(), s->m_index).methodSignature()));
-
- s->m_isEvaluating = true;
+ QV4DebugService *service = QQmlDebugConnector::service<QV4DebugService>();
+ if (service)
+ service->signalEmitted(QString::fromLatin1(QMetaObjectPrivate::signal(
+ s->m_expression->target()->metaObject(),
+ s->signalIndex()).methodSignature()));
QQmlEngine *engine;
if (s->m_expression && (engine = s->m_expression->engine())) {
@@ -410,8 +334,6 @@ void QQmlBoundSignal_callback(QQmlNotifierEndpoint *e, void **a)
QQmlEnginePrivate::warning(engine, s->m_expression->error(engine));
}
}
-
- s->m_isEvaluating = false;
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h
index 8d677ea039..3742317484 100644
--- a/src/qml/qml/qqmlboundsignal_p.h
+++ b/src/qml/qml/qqmlboundsignal_p.h
@@ -47,7 +47,6 @@
#include <QtCore/qmetaobject.h>
-#include <private/qqmlabstractexpression_p.h>
#include <private/qqmljavascriptexpression_p.h>
#include <private/qqmlboundsignalexpressionpointer_p.h>
#include <private/qqmlnotifier_p.h>
@@ -58,7 +57,7 @@
QT_BEGIN_NAMESPACE
-class Q_QML_PRIVATE_EXPORT QQmlBoundSignalExpression : public QQmlAbstractExpression, public QQmlJavaScriptExpression, public QQmlRefCount
+class Q_QML_PRIVATE_EXPORT QQmlBoundSignalExpression : public QQmlJavaScriptExpression, public QQmlRefCount
{
public:
QQmlBoundSignalExpression(QObject *target, int index,
@@ -73,9 +72,9 @@ public:
QQmlBoundSignalExpression(QObject *target, int index,
QQmlContextData *ctxt, QObject *scope, QV4::Function *runtimeFunction);
- // "inherited" from QQmlJavaScriptExpression.
- static QString expressionIdentifier(QQmlJavaScriptExpression *);
- static void expressionChanged(QQmlJavaScriptExpression *);
+ // inherited from QQmlJavaScriptExpression.
+ virtual QString expressionIdentifier();
+ virtual void expressionChanged();
// evaluation of a bound signal expression doesn't return any value
void evaluate(void **a);
@@ -92,80 +91,35 @@ private:
void init(QQmlContextData *ctxt, QObject *scope);
- bool expressionFunctionValid() const { return m_extra.flag(); }
- void setExpressionFunctionValid(bool v) { m_extra.setFlagValue(v); }
-
- bool invalidParameterName() const { return m_extra.flag2(); }
- void setInvalidParameterName(bool v) { m_extra.setFlag2Value(v); }
+ bool expressionFunctionValid() const { return !m_function.isNullOrUndefined(); }
int m_index;
- QV4::PersistentValue m_function;
-
QObject *m_target;
-
- // only needed when !expressionFunctionValid()
- struct ExtraData {
- ExtraData(const QString &handlerName, const QString &parameterString,
- const QString &expression, const QString &fileName,
- quint16 line, quint16 column);
- QString m_handlerName;
- QString m_parameterString;
- QString m_expression;
- QQmlSourceLocation m_sourceLocation;
- QV4::PersistentValue m_v8qmlscope;
- };
-
- // We store some flag bits in the following flag pointers.
- // flag - expressionFunctionValid
- // flag2 - invalidParameterName
- QFlagPointer<ExtraData> m_extra;
};
-class Q_QML_PRIVATE_EXPORT QQmlAbstractBoundSignal
+class Q_QML_PRIVATE_EXPORT QQmlBoundSignal : public QQmlNotifierEndpoint
{
public:
- QQmlAbstractBoundSignal();
- virtual ~QQmlAbstractBoundSignal();
-
- virtual int index() const = 0;
- virtual QQmlBoundSignalExpression *expression() const = 0;
- virtual QQmlBoundSignalExpressionPointer setExpression(QQmlBoundSignalExpression *) = 0;
- virtual QQmlBoundSignalExpressionPointer takeExpression(QQmlBoundSignalExpression *) = 0;
- virtual bool isEvaluating() const = 0;
+ QQmlBoundSignal(QObject *target, int signal, QObject *owner, QQmlEngine *engine);
+ ~QQmlBoundSignal();
void removeFromObject();
-protected:
- void addToObject(QObject *owner);
+
+ QQmlBoundSignalExpression *expression() const;
+ void takeExpression(QQmlBoundSignalExpression *);
private:
- friend class QQmlData;
+ friend void QQmlBoundSignal_callback(QQmlNotifierEndpoint *, void **);
friend class QQmlPropertyPrivate;
+ friend class QQmlData;
friend class QQmlEngineDebugService;
- QQmlAbstractBoundSignal **m_prevSignal;
- QQmlAbstractBoundSignal *m_nextSignal;
-};
-class Q_QML_PRIVATE_EXPORT QQmlBoundSignal : public QQmlAbstractBoundSignal,
- public QQmlNotifierEndpoint
-{
-public:
- QQmlBoundSignal(QObject *target, int signal, QObject *owner, QQmlEngine *engine);
- virtual ~QQmlBoundSignal();
-
- int index() const;
-
- QQmlBoundSignalExpression *expression() const;
- QQmlBoundSignalExpressionPointer setExpression(QQmlBoundSignalExpression *);
- QQmlBoundSignalExpressionPointer takeExpression(QQmlBoundSignalExpression *);
+ void addToObject(QObject *owner);
- bool isEvaluating() const { return m_isEvaluating; }
-
-private:
- friend void QQmlBoundSignal_callback(QQmlNotifierEndpoint *, void **);
+ QQmlBoundSignal **m_prevSignal;
+ QQmlBoundSignal *m_nextSignal;
QQmlBoundSignalExpressionPointer m_expression;
- int m_index;
- bool m_isEvaluating;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 35182d6319..22a54d732e 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -42,8 +42,8 @@
#include "qqml.h"
#include "qqmlengine.h"
#include "qqmlbinding_p.h"
-#include "qqmlglobal_p.h"
-#include <private/qqmlenginedebugservice_p.h>
+#include <private/qqmldebugconnector_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#include "qqmlincubator.h"
#include "qqmlincubator_p.h"
#include <private/qqmljavascriptexpression_p.h>
@@ -53,6 +53,7 @@
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
#include <private/qv4scopedvalue_p.h>
+#include <private/qv4objectiterator_p.h>
#include <QStack>
#include <QStringList>
@@ -61,23 +62,6 @@
#include <qqmlinfo.h>
#include "qqmlmemoryprofiler_p.h"
-#define INITIALPROPERTIES_SOURCE \
- "(function(object, values) {"\
- "try {"\
- "for (var property in values) {" \
- "try {"\
- "var properties = property.split(\".\");"\
- "var o = object;"\
- "for (var ii = 0; ii < properties.length - 1; ++ii) {"\
- "o = o[properties[ii]];"\
- "}"\
- "o[properties[properties.length - 1]] = values[property];"\
- "} catch(e) {}"\
- "}"\
- "} catch(e) {}"\
- "})"
-
-
namespace {
QThreadStorage<int> creationDepth;
}
@@ -98,7 +82,6 @@ V4_DEFINE_EXTENSION(QQmlComponentExtension, componentExtension);
\class QQmlComponent
\since 5.0
\inmodule QtQml
- \mainclass
\brief The QQmlComponent class encapsulates a QML component definition
@@ -896,10 +879,11 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
depthIncreased = false;
}
- if (enginePriv->isDebugging && rv) {
+ QQmlEngineDebugService *service = QQmlDebugConnector::service<QQmlEngineDebugService>();
+ if (service && rv) {
if (!context->isInternal)
context->asQQmlContextPrivate()->instances.append(rv);
- QQmlEngineDebugService::instance()->objectCreated(engine, rv);
+ service->objectCreated(engine, rv);
}
return rv;
@@ -1075,11 +1059,10 @@ namespace QV4 {
namespace Heap {
struct QmlIncubatorObject : Object {
- QmlIncubatorObject(QV4::ExecutionEngine *engine, QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous);
+ QmlIncubatorObject(QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous);
QScopedPointer<QQmlComponentIncubator> incubator;
QPointer<QObject> parent;
QV4::Value valuemap;
- QV4::Value qmlGlobal;
QV4::Value statusChanged;
};
@@ -1194,6 +1177,46 @@ static void QQmlComponent_setQmlParent(QObject *me, QObject *parent)
\sa incubateObject()
*/
+
+static void setInitialProperties(QV4::ExecutionEngine *engine, const QV4::Value &o, const QV4::Value &v)
+{
+ QV4::Scope scope(engine);
+ QV4::ScopedObject object(scope);
+ QV4::ScopedObject valueMap(scope, v);
+ QV4::ObjectIterator it(scope, valueMap, QV4::ObjectIterator::EnumerableOnly|QV4::ObjectIterator::WithProtoChain);
+ QV4::ScopedString name(scope);
+ QV4::ScopedValue val(scope);
+ if (engine->hasException)
+ return;
+
+ while (1) {
+ name = it.nextPropertyNameAsString(val);
+ if (!name)
+ break;
+ object = o;
+ const QStringList properties = name->toQString().split(QLatin1Char('.'));
+ for (int i = 0; i < properties.length() - 1; ++i) {
+ name = engine->newString(properties.at(i));
+ object = object->get(name);
+ if (engine->hasException || !object) {
+ break;
+ }
+ }
+ if (engine->hasException || !object) {
+ engine->hasException = false;
+ continue;
+ }
+ name = engine->newString(properties.last());
+ object->put(name, val);
+ if (engine->hasException) {
+ engine->hasException = false;
+ continue;
+ }
+ }
+
+ engine->hasException = false;
+}
+
/*!
\internal
*/
@@ -1216,7 +1239,7 @@ void QQmlComponent::createObject(QQmlV4Function *args)
if (args->length() >= 2) {
QV4::ScopedValue v(scope, (*args)[1]);
- if (!v->asObject() || v->asArrayObject()) {
+ if (!v->as<QV4::Object>() || v->as<QV4::ArrayObject>()) {
qmlInfo(this) << tr("createObject: value is not an object");
args->setReturnValue(QV4::Encode::null());
return;
@@ -1239,16 +1262,8 @@ void QQmlComponent::createObject(QQmlV4Function *args)
QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(v4, rv));
Q_ASSERT(object->isObject());
- if (!valuemap->isUndefined()) {
- QV4::ScopedObject qmlglobal(scope, args->qmlGlobal());
- QV4::ScopedValue f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlglobal));
- Q_ASSERT(f->asFunctionObject());
- QV4::ScopedCallData callData(scope, 2);
- callData->thisObject = v4->globalObject();
- callData->args[0] = object;
- callData->args[1] = valuemap;
- f->asFunctionObject()->call(callData);
- }
+ if (!valuemap->isUndefined())
+ setInitialProperties(v4, object, valuemap);
d->completeCreate();
@@ -1256,10 +1271,7 @@ void QQmlComponent::createObject(QQmlV4Function *args)
QQmlData::get(rv)->explicitIndestructibleSet = false;
QQmlData::get(rv)->indestructible = false;
- if (!rv)
- args->setReturnValue(QV4::Encode::null());
- else
- args->setReturnValue(object->asReturnedValue());
+ args->setReturnValue(object->asReturnedValue());
}
/*!
@@ -1342,7 +1354,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
if (args->length() >= 2) {
QV4::ScopedValue v(scope, (*args)[1]);
if (v->isNull()) {
- } else if (!v->asObject() || v->asArrayObject()) {
+ } else if (!v->as<QV4::Object>() || v->as<QV4::ArrayObject>()) {
qmlInfo(this) << tr("createObject: value is not an object");
args->setReturnValue(QV4::Encode::null());
return;
@@ -1362,14 +1374,12 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
QQmlComponentExtension *e = componentExtension(args->v4engine());
- QV4::Scoped<QV4::QmlIncubatorObject> r(scope, v4->memoryManager->alloc<QV4::QmlIncubatorObject>(args->v4engine(), mode));
+ QV4::Scoped<QV4::QmlIncubatorObject> r(scope, v4->memoryManager->allocObject<QV4::QmlIncubatorObject>(mode));
QV4::ScopedObject p(scope, e->incubationProto.value());
r->setPrototype(p);
- if (!valuemap->isUndefined()) {
+ if (!valuemap->isUndefined())
r->d()->valuemap = valuemap;
- r->d()->qmlGlobal = args->qmlGlobal();
- }
r->d()->parent = parent;
QQmlIncubator *incubator = r->d()->incubator.data();
@@ -1383,25 +1393,17 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
}
// XXX used by QSGLoader
-void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Value &qmlGlobal, const QV4::Value &valuemap, QObject *toCreate)
+void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Value &valuemap, QObject *toCreate)
{
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
QV4::ExecutionEngine *v4engine = QV8Engine::getV4(ep->v8engine());
QV4::Scope scope(v4engine);
QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(v4engine, toCreate));
- Q_ASSERT(object->asObject());
-
- if (!valuemap.isUndefined()) {
- QV4::ScopedObject qmlGlobalObj(scope, qmlGlobal);
- QV4::ScopedFunctionObject f(scope, QV4::Script::evaluate(v4engine,
- QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobalObj));
- QV4::ScopedCallData callData(scope, 2);
- callData->thisObject = v4engine->globalObject();
- callData->args[0] = object;
- callData->args[1] = valuemap;
- f->call(callData);
- }
+ Q_ASSERT(object->as<QV4::Object>());
+
+ if (!valuemap.isUndefined())
+ setInitialProperties(v4engine, object, valuemap);
}
QQmlComponentExtension::QQmlComponentExtension(QV4::ExecutionEngine *v4)
@@ -1475,10 +1477,8 @@ QQmlComponentExtension::~QQmlComponentExtension()
{
}
-QV4::Heap::QmlIncubatorObject::QmlIncubatorObject(ExecutionEngine *engine, QQmlIncubator::IncubationMode m)
- : QV4::Heap::Object(engine)
- , valuemap(QV4::Primitive::undefinedValue())
- , qmlGlobal(QV4::Primitive::undefinedValue())
+QV4::Heap::QmlIncubatorObject::QmlIncubatorObject(QQmlIncubator::IncubationMode m)
+ : valuemap(QV4::Primitive::undefinedValue())
, statusChanged(QV4::Primitive::undefinedValue())
{
incubator.reset(new QQmlComponentIncubator(this, m));
@@ -1491,13 +1491,8 @@ void QV4::QmlIncubatorObject::setInitialState(QObject *o)
if (!d()->valuemap.isUndefined()) {
QV4::ExecutionEngine *v4 = engine();
QV4::Scope scope(v4);
-
- QV4::ScopedFunctionObject f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), d()->qmlGlobal.asObject()));
- QV4::ScopedCallData callData(scope, 2);
- callData->thisObject = v4->globalObject();
- callData->args[0] = QV4::QObjectWrapper::wrap(v4, o);
- callData->args[1] = d()->valuemap;
- f->call(callData);
+ QV4::ScopedObject obj(scope, QV4::QObjectWrapper::wrap(v4, o));
+ setInitialProperties(v4, obj, d()->valuemap);
}
}
@@ -1505,7 +1500,6 @@ void QV4::QmlIncubatorObject::markObjects(QV4::Heap::Base *that, QV4::ExecutionE
{
QmlIncubatorObject::Data *o = static_cast<QmlIncubatorObject::Data *>(that);
o->valuemap.mark(e);
- o->qmlGlobal.mark(e);
o->statusChanged.mark(e);
Object::markObjects(that, e);
}
diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h
index 8c866c585a..121c83db5c 100644
--- a/src/qml/qml/qqmlcomponent.h
+++ b/src/qml/qml/qqmlcomponent.h
@@ -63,8 +63,8 @@ class Q_QML_EXPORT QQmlComponent : public QObject
Q_PROPERTY(QUrl url READ url CONSTANT)
public:
- Q_ENUMS(CompilationMode)
enum CompilationMode { PreferSynchronous, Asynchronous };
+ Q_ENUM(CompilationMode)
QQmlComponent(QObject *parent = 0);
QQmlComponent(QQmlEngine *, QObject *parent=0);
@@ -74,8 +74,8 @@ public:
QQmlComponent(QQmlEngine *, const QUrl &url, CompilationMode mode, QObject *parent = 0);
virtual ~QQmlComponent();
- Q_ENUMS(Status)
enum Status { Null, Ready, Loading, Error };
+ Q_ENUM(Status)
Status status() const;
bool isNull() const;
@@ -125,7 +125,6 @@ private:
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QQmlComponent::Status)
QML_DECLARE_TYPE(QQmlComponent)
QML_DECLARE_TYPEINFO(QQmlComponent, QML_HAS_ATTACHED_PROPERTIES)
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index adc6e173d2..15ec88dd52 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -82,7 +82,7 @@ public:
QObject *beginCreate(QQmlContextData *);
void completeCreate();
- void initializeObjectWithInitialProperties(const QV4::Value &qmlGlobal, const QV4::Value &valuemap, QObject *toCreate);
+ void initializeObjectWithInitialProperties(const QV4::Value &valuemap, QObject *toCreate);
QQmlTypeData *typeData;
virtual void typeDataReady(QQmlTypeData *);
diff --git a/src/qml/qml/qqmlcomponentattached_p.h b/src/qml/qml/qqmlcomponentattached_p.h
index b6ad3dec00..fa103e7fce 100644
--- a/src/qml/qml/qqmlcomponentattached_p.h
+++ b/src/qml/qml/qqmlcomponentattached_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLCOMPONENTATTACHED_P_H
#define QQMLCOMPONENTATTACHED_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQml/qqml.h>
#include <private/qtqmlglobal_p.h>
#include <QtCore/QObject>
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index fb51bad3a7..b056731e96 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -57,7 +57,6 @@ QQmlContextPrivate::QQmlContextPrivate()
/*!
\class QQmlContext
\brief The QQmlContext class defines a context within a QML engine.
- \mainclass
\inmodule QtQml
Contexts allow data to be exposed to the QML components instantiated by the
@@ -585,9 +584,9 @@ void QQmlContextData::clearContext()
{
emitDestruction();
- QQmlAbstractExpression *expression = expressions;
+ QQmlJavaScriptExpression *expression = expressions;
while (expression) {
- QQmlAbstractExpression *nextExpression = expression->m_nextExpression;
+ QQmlJavaScriptExpression *nextExpression = expression->m_nextExpression;
expression->m_prevExpression = 0;
expression->m_nextExpression = 0;
@@ -652,9 +651,9 @@ void QQmlContextData::setParent(QQmlContextData *p, bool parentTakesOwnership)
}
}
-void QQmlContextData::refreshExpressionsRecursive(QQmlAbstractExpression *expression)
+void QQmlContextData::refreshExpressionsRecursive(QQmlJavaScriptExpression *expression)
{
- QQmlAbstractExpression::DeleteWatcher w(expression);
+ QQmlJavaScriptExpression::DeleteWatcher w(expression);
if (expression->m_nextExpression)
refreshExpressionsRecursive(expression->m_nextExpression);
@@ -808,7 +807,7 @@ QV4::IdentifierHash<int> &QQmlContextData::propertyNames() const
{
if (propertyNameCache.isEmpty()) {
propertyNameCache = QV4::IdentifierHash<int>(QV8Engine::getV4(engine->handle()));
- for (QHash<int, int>::ConstIterator it = objectIndexToId.begin(), end = objectIndexToId.end();
+ for (QHash<int, int>::ConstIterator it = objectIndexToId.cbegin(), end = objectIndexToId.cend();
it != end; ++it) {
const QV4::CompiledData::Object *obj = typeCompilationUnit->data->objectAt(it.key());
const QString name = typeCompilationUnit->data->stringAt(obj->idIndex);
diff --git a/src/qml/qml/qqmlcontext.h b/src/qml/qml/qqmlcontext.h
index c714846147..e69a2f8f69 100644
--- a/src/qml/qml/qqmlcontext.h
+++ b/src/qml/qml/qqmlcontext.h
@@ -72,6 +72,7 @@ public:
void setContextProperty(const QString &, QObject *);
void setContextProperty(const QString &, const QVariant &);
+ // ### Qt 6: no need for a mutable object, this should become a const QObject pointer
QString nameForObject(QObject *) const;
QUrl resolvedUrl(const QUrl &);
diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h
index f5fd7d0a5c..95254d4baa 100644
--- a/src/qml/qml/qqmlcontext_p.h
+++ b/src/qml/qml/qqmlcontext_p.h
@@ -69,7 +69,7 @@ class QQmlExpression;
class QQmlEngine;
class QQmlExpression;
class QQmlExpressionPrivate;
-class QQmlAbstractExpression;
+class QQmlJavaScriptExpression;
class QQmlContextData;
class QQmlContextPrivate : public QObjectPrivate
@@ -171,7 +171,7 @@ public:
QQmlContextData **prevChild;
// Expressions that use this context
- QQmlAbstractExpression *expressions;
+ QQmlJavaScriptExpression *expressions;
// Doubly-linked list of objects that are owned by this context
QQmlData *contextObjects;
@@ -212,7 +212,7 @@ public:
private:
void refreshExpressionsRecursive(bool isGlobal);
- void refreshExpressionsRecursive(QQmlAbstractExpression *);
+ void refreshExpressionsRecursive(QQmlJavaScriptExpression *);
~QQmlContextData() {}
};
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index 5844eab54f..0d84c3bb64 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -38,13 +38,14 @@
#include <private/qqmlcontext_p.h>
#include <private/qv4engine_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4objectproto_p.h>
#include <private/qv4mm_p.h>
#include <private/qv4function_p.h>
#include <private/qv4compileddata_p.h>
#include <private/qqmltypewrapper_p.h>
#include <private/qqmllistwrapper_p.h>
+#include <private/qqmljavascriptexpression_p.h>
#include <private/qjsvalue_p.h>
QT_BEGIN_NAMESPACE
@@ -53,14 +54,12 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlContextWrapper);
-Heap::QmlContextWrapper::QmlContextWrapper(QV4::ExecutionEngine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext)
- : Heap::Object(engine)
- , readOnly(true)
+Heap::QmlContextWrapper::QmlContextWrapper(QQmlContextData *context, QObject *scopeObject, bool ownsContext)
+ : readOnly(true)
, ownsContext(ownsContext)
, isNullWrapper(false)
, context(context)
, scopeObject(scopeObject)
- , idObjectsWrapper(Q_NULLPTR)
{
}
@@ -74,7 +73,7 @@ ReturnedValue QmlContextWrapper::qmlScope(ExecutionEngine *v4, QQmlContextData *
{
Scope valueScope(v4);
- Scoped<QmlContextWrapper> w(valueScope, v4->memoryManager->alloc<QmlContextWrapper>(v4, ctxt, scope));
+ Scoped<QmlContextWrapper> w(valueScope, v4->memoryManager->allocObject<QmlContextWrapper>(ctxt, scope));
return w.asReturnedValue();
}
@@ -88,67 +87,26 @@ ReturnedValue QmlContextWrapper::urlScope(ExecutionEngine *v4, const QUrl &url)
context->isInternal = true;
context->isJSContext = true;
- Scoped<QmlContextWrapper> w(scope, v4->memoryManager->alloc<QmlContextWrapper>(v4, context, (QObject*)0, true));
+ Scoped<QmlContextWrapper> w(scope, v4->memoryManager->allocObject<QmlContextWrapper>(context, (QObject*)0, true));
w->d()->isNullWrapper = true;
return w.asReturnedValue();
}
-QQmlContextData *QmlContextWrapper::callingContext(ExecutionEngine *v4)
-{
- Scope scope(v4);
- QV4::Scoped<QmlContextWrapper> c(scope, v4->qmlContextObject());
-
- return !!c ? c->getContext() : 0;
-}
-
-QQmlContextData *QmlContextWrapper::getContext(const Value &value)
-{
- if (!value.isObject())
- return 0;
-
- QV4::ExecutionEngine *v4 = value.asObject()->engine();
- Scope scope(v4);
- QV4::Scoped<QmlContextWrapper> c(scope, value);
-
- return c ? c->getContext() : 0;
-}
-
-void QmlContextWrapper::takeContextOwnership(const Value &qmlglobal)
-{
- Q_ASSERT(qmlglobal.isObject());
-
- QV4::ExecutionEngine *v4 = qmlglobal.asObject()->engine();
- Scope scope(v4);
- QV4::Scoped<QmlContextWrapper> c(scope, qmlglobal);
- Q_ASSERT(c);
- c->d()->ownsContext = true;
-}
-
-
-ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue QmlContextWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<QmlContextWrapper>());
- QmlContextWrapper *resource = static_cast<QmlContextWrapper *>(m);
+ const QmlContextWrapper *resource = static_cast<const QmlContextWrapper *>(m);
QV4::ExecutionEngine *v4 = resource->engine();
QV4::Scope scope(v4);
- // In V8 the JS global object would come _before_ the QML global object,
- // so simulate that here.
- bool hasProp;
- QV4::ScopedValue result(scope, v4->globalObject()->get(name, &hasProp));
- if (hasProp) {
- if (hasProperty)
- *hasProperty = hasProp;
- return result->asReturnedValue();
- }
-
if (resource->d()->isNullWrapper)
return Object::get(m, name, hasProperty);
- if (QV4::QmlContextWrapper::callingContext(v4) != resource->d()->context)
+ if (v4->callingQmlContext() != resource->d()->context)
return Object::get(m, name, hasProperty);
- result = Object::get(m, name, &hasProp);
+ bool hasProp;
+ QV4::ScopedValue result(scope, Object::get(m, name, &hasProp));
if (hasProp) {
if (hasProperty)
*hasProperty = hasProp;
@@ -209,7 +167,8 @@ ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty
if (propertyIdx < context->idValueCount) {
- ep->captureProperty(&context->idValues[propertyIdx].bindings);
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureProperty(&context->idValues[propertyIdx].bindings);
if (hasProperty)
*hasProperty = true;
return QV4::QObjectWrapper::wrap(v4, context->idValues[propertyIdx]);
@@ -217,8 +176,8 @@ ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty
QQmlContextPrivate *cp = context->asQQmlContextPrivate();
- ep->captureProperty(context->asQQmlContext(), -1,
- propertyIdx + cp->notifyIndex);
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureProperty(context->asQQmlContext(), -1, propertyIdx + cp->notifyIndex);
const QVariant &value = cp->propertyValues.at(propertyIdx);
if (hasProperty)
@@ -278,10 +237,9 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value)
return;
QV4::Scoped<QmlContextWrapper> wrapper(scope, resource);
- PropertyAttributes attrs;
- Property *pd = wrapper->__getOwnProperty__(name, &attrs);
- if (pd) {
- wrapper->putValue(pd, attrs, value);
+ uint member = wrapper->internalClass()->find(name);
+ if (member < UINT_MAX) {
+ wrapper->putValue(member, value);
return;
}
@@ -289,7 +247,7 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value)
if (wrapper && wrapper->d()->readOnly) {
QString error = QLatin1String("Invalid write to global property \"") + name->toQString() +
QLatin1Char('"');
- ScopedString e(scope, v4->currentContext()->engine->newString(error));
+ ScopedString e(scope, v4->newString(error));
v4->throwError(e);
return;
}
@@ -342,127 +300,4 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value)
Object::put(m, name, value);
}
-void QmlContextWrapper::markObjects(Heap::Base *m, ExecutionEngine *engine)
-{
- QmlContextWrapper::Data *This = static_cast<QmlContextWrapper::Data *>(m);
- if (This->idObjectsWrapper)
- This->idObjectsWrapper->mark(engine);
- Object::markObjects(m, engine);
-}
-
-void QmlContextWrapper::registerQmlDependencies(ExecutionEngine *engine, const CompiledData::Function *compiledFunction)
-{
- // Let the caller check and avoid the function call :)
- Q_ASSERT(compiledFunction->hasQmlDependencies());
-
- QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
- if (!ep)
- return;
- QQmlEnginePrivate::PropertyCapture *capture = ep->propertyCapture;
- if (!capture)
- return;
-
- QV4::Scope scope(engine);
- QV4::Scoped<QmlContextWrapper> contextWrapper(scope, engine->qmlContextObject());
- QQmlContextData *qmlContext = contextWrapper->getContext();
-
- const quint32 *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable();
- const int idObjectDependencyCount = compiledFunction->nDependingIdObjects;
- for (int i = 0; i < idObjectDependencyCount; ++i, ++idObjectDependency) {
- Q_ASSERT(int(*idObjectDependency) < qmlContext->idValueCount);
- capture->captureProperty(&qmlContext->idValues[*idObjectDependency].bindings);
- }
-
- Q_ASSERT(qmlContext->contextObject);
- const quint32 *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable();
- const int contextPropertyDependencyCount = compiledFunction->nDependingContextProperties;
- for (int i = 0; i < contextPropertyDependencyCount; ++i) {
- const int propertyIndex = *contextPropertyDependency++;
- const int notifyIndex = *contextPropertyDependency++;
- capture->captureProperty(qmlContext->contextObject, propertyIndex, notifyIndex);
- }
-
- QObject *scopeObject = contextWrapper->getScopeObject();
- const quint32 *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable();
- const int scopePropertyDependencyCount = compiledFunction->nDependingScopeProperties;
- for (int i = 0; i < scopePropertyDependencyCount; ++i) {
- const int propertyIndex = *scopePropertyDependency++;
- const int notifyIndex = *scopePropertyDependency++;
- capture->captureProperty(scopeObject, propertyIndex, notifyIndex);
- }
-
-}
-
-ReturnedValue QmlContextWrapper::idObjectsArray()
-{
- if (!d()->idObjectsWrapper) {
- ExecutionEngine *v4 = engine();
- d()->idObjectsWrapper = v4->memoryManager->alloc<QQmlIdObjectsArray>(v4, this);
- }
- return d()->idObjectsWrapper->asReturnedValue();
-}
-
-ReturnedValue QmlContextWrapper::qmlSingletonWrapper(ExecutionEngine *v4, String *name)
-{
- if (!d()->context->imports)
- return Encode::undefined();
- // Search for attached properties, enums and imported scripts
- QQmlTypeNameCache::Result r = d()->context->imports->query(name);
-
- Q_ASSERT(r.isValid());
- Q_ASSERT(r.type);
- Q_ASSERT(r.type->isSingleton());
- Q_ASSERT(v4);
-
- QQmlEngine *e = v4->qmlEngine();
- QQmlType::SingletonInstanceInfo *siinfo = r.type->singletonInstanceInfo();
- siinfo->init(e);
-
- if (QObject *qobjectSingleton = siinfo->qobjectApi(e))
- return QV4::QObjectWrapper::wrap(engine(), qobjectSingleton);
- return QJSValuePrivate::convertedToValue(engine(), siinfo->scriptApi(e));
-}
-
-DEFINE_OBJECT_VTABLE(QQmlIdObjectsArray);
-
-Heap::QQmlIdObjectsArray::QQmlIdObjectsArray(ExecutionEngine *engine, QV4::QmlContextWrapper *contextWrapper)
- : Heap::Object(engine)
- , contextWrapper(contextWrapper->d())
-{
-}
-
-ReturnedValue QQmlIdObjectsArray::getIndexed(Managed *m, uint index, bool *hasProperty)
-{
- Scope scope(static_cast<QV4::QQmlIdObjectsArray*>(m)->engine());
- Scoped<QQmlIdObjectsArray> This(scope, static_cast<QV4::QQmlIdObjectsArray*>(m));
- Scoped<QmlContextWrapper> contextWrapper(scope, This->d()->contextWrapper);
- QQmlContextData *context = contextWrapper->getContext();
- if (!context) {
- if (hasProperty)
- *hasProperty = false;
- return Encode::undefined();
- }
- if (index >= (uint)context->idValueCount) {
- if (hasProperty)
- *hasProperty = false;
- return Encode::undefined();
- }
-
- if (hasProperty)
- *hasProperty = true;
-
- QQmlEnginePrivate *ep = scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : 0;
- if (ep)
- ep->captureProperty(&context->idValues[index].bindings);
-
- return QObjectWrapper::wrap(This->engine(), context->idValues[index].data());
-}
-
-void QQmlIdObjectsArray::markObjects(Heap::Base *that, ExecutionEngine *engine)
-{
- QQmlIdObjectsArray::Data *This = static_cast<QQmlIdObjectsArray::Data *>(that);
- This->contextWrapper->mark(engine);
- Object::markObjects(that, engine);
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcontextwrapper_p.h b/src/qml/qml/qqmlcontextwrapper_p.h
index 52d8677103..9dd71b708f 100644
--- a/src/qml/qml/qqmlcontextwrapper_p.h
+++ b/src/qml/qml/qqmlcontextwrapper_p.h
@@ -48,7 +48,7 @@
#include <QtCore/qglobal.h>
#include <private/qtqmlglobal_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
#include <private/qqmlcontext_p.h>
#include <private/qv4functionobject_p.h>
@@ -65,10 +65,8 @@ struct QmlContextWrapper;
namespace Heap {
-struct QQmlIdObjectsArray;
-
struct QmlContextWrapper : Object {
- QmlContextWrapper(ExecutionEngine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext = false);
+ QmlContextWrapper(QQmlContextData *context, QObject *scopeObject, bool ownsContext = false);
~QmlContextWrapper();
bool readOnly;
bool ownsContext;
@@ -76,12 +74,6 @@ struct QmlContextWrapper : Object {
QQmlGuardedContextData context;
QPointer<QObject> scopeObject;
- QQmlIdObjectsArray *idObjectsWrapper;
-};
-
-struct QQmlIdObjectsArray : Object {
- QQmlIdObjectsArray(QV4::ExecutionEngine *engine, QV4::QmlContextWrapper *contextWrapper);
- QmlContextWrapper *contextWrapper;
};
}
@@ -94,33 +86,17 @@ struct Q_QML_EXPORT QmlContextWrapper : Object
static ReturnedValue qmlScope(ExecutionEngine *e, QQmlContextData *ctxt, QObject *scope);
static ReturnedValue urlScope(ExecutionEngine *v4, const QUrl &);
- static QQmlContextData *callingContext(ExecutionEngine *v4);
- static void takeContextOwnership(const Value &qmlglobal);
+ void takeContextOwnership() {
+ d()->ownsContext = true;
+ }
inline QObject *getScopeObject() const { return d()->scopeObject; }
inline QQmlContextData *getContext() const { return d()->context; }
- static QQmlContextData *getContext(const Value &value);
void setReadOnly(bool b) { d()->readOnly = b; }
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
- static void markObjects(Heap::Base *m, ExecutionEngine *engine);
-
- static void registerQmlDependencies(ExecutionEngine *context, const CompiledData::Function *compiledFunction);
-
- ReturnedValue idObjectsArray();
- ReturnedValue qmlSingletonWrapper(ExecutionEngine *e, String *name);
-
-};
-
-struct QQmlIdObjectsArray : public Object
-{
- V4_OBJECT2(QQmlIdObjectsArray, Object)
-
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
- static void markObjects(Heap::Base *that, ExecutionEngine *engine);
-
};
}
diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp
index ebca9d2718..517f8d42ed 100644
--- a/src/qml/qml/qqmlcustomparser.cpp
+++ b/src/qml/qml/qqmlcustomparser.cpp
@@ -34,6 +34,7 @@
#include "qqmlcustomparser_p.h"
#include "qqmlcompiler_p.h"
+#include <private/qqmltypecompiler_p.h>
#include <QtCore/qdebug.h>
@@ -140,7 +141,7 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
type = result.type;
}
- return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
+ return type ? type->enumValue(engine, QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
}
const QMetaObject *mo = StaticQtMetaObject::get();
@@ -159,34 +160,8 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
*/
const QMetaObject *QQmlCustomParser::resolveType(const QString& name) const
{
- return compiler->resolveType(name);
-}
-
-int QQmlCustomParserCompilerBackend::evaluateEnum(const QString &scope, const QByteArray &enumValue, bool *ok) const
-{
- Q_ASSERT_X(ok, "QQmlCompiler::evaluateEnum", "ok must not be a null pointer");
- *ok = false;
-
- if (scope != QLatin1String("Qt")) {
- QQmlType *type = 0;
- imports().resolveType(scope, &type, 0, 0, 0);
- return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
- }
-
- const QMetaObject *mo = StaticQtMetaObject::get();
- int i = mo->enumeratorCount();
- while (i--) {
- int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok);
- if (*ok)
- return v;
- }
- return -1;
-}
-
-const QMetaObject *QQmlCustomParserCompilerBackend::resolveType(const QString &name) const
-{
QQmlType *qmltype = 0;
- if (!imports().resolveType(name, &qmltype, 0, 0, 0))
+ if (!validator->imports().resolveType(name, &qmltype, 0, 0, 0))
return 0;
if (!qmltype)
return 0;
diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h
index 88282b1bbc..8bdc73fab1 100644
--- a/src/qml/qml/qqmlcustomparser_p.h
+++ b/src/qml/qml/qqmlcustomparser_p.h
@@ -55,15 +55,8 @@
QT_BEGIN_NAMESPACE
class QQmlCompiledData;
-
-struct QQmlCustomParserCompilerBackend
-{
- virtual ~QQmlCustomParserCompilerBackend() {}
- virtual const QQmlImports &imports() const = 0;
-
- int evaluateEnum(const QString &scope, const QByteArray& enumValue, bool *ok) const;
- const QMetaObject *resolveType(const QString& name) const;
-};
+class QQmlPropertyValidator;
+class QQmlEnginePrivate;
class Q_QML_PRIVATE_EXPORT QQmlCustomParser
{
@@ -75,8 +68,8 @@ public:
};
Q_DECLARE_FLAGS(Flags, Flag)
- QQmlCustomParser() : compiler(0), m_flags(NoFlag) {}
- QQmlCustomParser(Flags f) : compiler(0), m_flags(f) {}
+ QQmlCustomParser() : engine(0), validator(0), m_flags(NoFlag) {}
+ QQmlCustomParser(Flags f) : engine(0), validator(0), m_flags(f) {}
virtual ~QQmlCustomParser() {}
void clearErrors();
@@ -100,7 +93,8 @@ protected:
private:
QList<QQmlError> exceptions;
- const QQmlCustomParserCompilerBackend *compiler;
+ QQmlEnginePrivate *engine;
+ const QQmlPropertyValidator *validator;
Flags m_flags;
QBiPointer<const QQmlImports, QQmlTypeNameCache> imports;
friend class QQmlPropertyValidator;
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index 04c42b638d..ef05dd1fd7 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -48,8 +48,9 @@
#include <private/qtqmlglobal_p.h>
#include <private/qobject_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4persistent_p.h>
+#include <qjsengine.h>
QT_BEGIN_NAMESPACE
@@ -58,7 +59,7 @@ class QQmlEngine;
class QQmlGuardImpl;
class QQmlCompiledData;
class QQmlAbstractBinding;
-class QQmlAbstractBoundSignal;
+class QQmlBoundSignal;
class QQmlContext;
class QQmlPropertyCache;
class QQmlContextData;
@@ -72,15 +73,7 @@ class QQmlNotifierEndpoint;
class Q_QML_PRIVATE_EXPORT QQmlData : public QAbstractDeclarativeData
{
public:
- QQmlData()
- : ownedByQml1(false), ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false),
- hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false),
- hasVMEMetaObject(false), parentFrozen(false), bindingBitsSize(0), bindingBits(0), notifyList(0), context(0), outerContext(0),
- bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0),
- lineNumber(0), columnNumber(0), jsEngineId(0), compiledData(0), deferredData(0),
- propertyCache(0), guards(0), extendedData(0) {
- init();
- }
+ QQmlData();
static inline void init() {
static bool initialized = false;
@@ -119,9 +112,10 @@ public:
* v8 GC will check this flag, only deletes the objects when rootObjectInCreation is false.
*/
quint32 rootObjectInCreation:1;
+ quint32 hasInterceptorMetaObject:1;
quint32 hasVMEMetaObject:1;
quint32 parentFrozen:1;
- quint32 dummy:22;
+ quint32 dummy:21;
// When bindingBitsSize < 32, we store the binding bit flags inside
// bindingBitsValue. When we need more than 32 bits, we allocated
@@ -158,7 +152,7 @@ public:
QQmlContextData *outerContext;
QQmlAbstractBinding *bindings;
- QQmlAbstractBoundSignal *signalHandlers;
+ QQmlBoundSignal *signalHandlers;
// Linked list for QQmlContext::contextObjects
QQmlData *nextContextObject;
diff --git a/src/qml/qml/qqmldirparser.cpp b/src/qml/qml/qqmldirparser.cpp
index 7f6310d58e..57b50733ea 100644
--- a/src/qml/qml/qqmldirparser.cpp
+++ b/src/qml/qml/qqmldirparser.cpp
@@ -146,7 +146,7 @@ bool QQmlDirParser::parse(const QString &source)
if (invalidLine) {
reportError(lineNumber, 0,
- QString::fromLatin1("invalid qmldir directive contains too many tokens"));
+ QStringLiteral("invalid qmldir directive contains too many tokens"));
continue;
} else if (sectionCount == 0) {
continue; // no sections, no party.
@@ -154,17 +154,17 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("module")) {
if (sectionCount != 2) {
reportError(lineNumber, 0,
- QString::fromLatin1("module identifier directive requires one argument, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("module identifier directive requires one argument, but %1 were provided").arg(sectionCount - 1));
continue;
}
if (!_typeNamespace.isEmpty()) {
reportError(lineNumber, 0,
- QString::fromLatin1("only one module identifier directive may be defined in a qmldir file"));
+ QStringLiteral("only one module identifier directive may be defined in a qmldir file"));
continue;
}
if (!firstLine) {
reportError(lineNumber, 0,
- QString::fromLatin1("module identifier directive must be the first directive in a qmldir file"));
+ QStringLiteral("module identifier directive must be the first directive in a qmldir file"));
continue;
}
@@ -173,7 +173,7 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("plugin")) {
if (sectionCount < 2 || sectionCount > 3) {
reportError(lineNumber, 0,
- QString::fromLatin1("plugin directive requires one or two arguments, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("plugin directive requires one or two arguments, but %1 were provided").arg(sectionCount - 1));
continue;
}
@@ -185,7 +185,7 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("internal")) {
if (sectionCount != 3) {
reportError(lineNumber, 0,
- QString::fromLatin1("internal types require 2 arguments, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("internal types require 2 arguments, but %1 were provided").arg(sectionCount - 1));
continue;
}
Component entry(sections[1], sections[2], -1, -1);
@@ -194,7 +194,7 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("singleton")) {
if (sectionCount < 3 || sectionCount > 4) {
reportError(lineNumber, 0,
- QString::fromLatin1("singleton types require 2 or 3 arguments, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("singleton types require 2 or 3 arguments, but %1 were provided").arg(sectionCount - 1));
continue;
} else if (sectionCount == 3) {
// handle qmldir directory listing case where singleton is defined in the following pattern:
@@ -218,7 +218,7 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("typeinfo")) {
if (sectionCount != 2) {
reportError(lineNumber, 0,
- QString::fromLatin1("typeinfo requires 1 argument, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("typeinfo requires 1 argument, but %1 were provided").arg(sectionCount - 1));
continue;
}
#ifdef QT_CREATOR
@@ -228,13 +228,13 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sections[0] == QLatin1String("designersupported")) {
if (sectionCount != 1)
- reportError(lineNumber, 0, QString::fromLatin1("designersupported does not expect any argument"));
+ reportError(lineNumber, 0, QStringLiteral("designersupported does not expect any argument"));
else
_designerSupported = true;
} else if (sections[0] == QLatin1String("depends")) {
if (sectionCount != 3) {
reportError(lineNumber, 0,
- QString::fromLatin1("depends requires 2 arguments, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("depends requires 2 arguments, but %1 were provided").arg(sectionCount - 1));
continue;
}
@@ -268,7 +268,7 @@ bool QQmlDirParser::parse(const QString &source)
}
} else {
reportError(lineNumber, 0,
- QString::fromLatin1("a component declaration requires two or three arguments, but %1 were provided").arg(sectionCount));
+ QStringLiteral("a component declaration requires two or three arguments, but %1 were provided").arg(sectionCount));
}
firstLine = false;
@@ -304,7 +304,9 @@ QList<QQmlError> QQmlDirParser::errors(const QString &uri) const
{
QUrl url(uri);
QList<QQmlError> errors;
- for (int i = 0; i < _errors.size(); ++i) {
+ const int numErrors = _errors.size();
+ errors.reserve(numErrors);
+ for (int i = 0; i < numErrors; ++i) {
const QQmlJS::DiagnosticMessage &msg = _errors.at(i);
QQmlError e;
QString description = msg.message;
@@ -362,14 +364,14 @@ bool QQmlDirParser::designerSupported() const
QDebug &operator<< (QDebug &debug, const QQmlDirParser::Component &component)
{
- const QString output = QString::fromLatin1("{%1 %2.%3}").
+ const QString output = QStringLiteral("{%1 %2.%3}").
arg(component.typeName).arg(component.majorVersion).arg(component.minorVersion);
return debug << qPrintable(output);
}
QDebug &operator<< (QDebug &debug, const QQmlDirParser::Script &script)
{
- const QString output = QString::fromLatin1("{%1 %2.%3}").
+ const QString output = QStringLiteral("{%1 %2.%3}").
arg(script.nameSpace).arg(script.majorVersion).arg(script.minorVersion);
return debug << qPrintable(output);
}
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 06a61c3307..109cfac0c3 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -42,7 +42,6 @@
#include "qqmlexpression.h"
#include "qqmlcomponent.h"
#include "qqmlvme_p.h"
-#include <private/qqmlenginedebugservice_p.h>
#include "qqmlstringconverters_p.h"
#include "qqmlxmlhttprequest_p.h"
#include "qqmlscriptstring.h"
@@ -54,11 +53,7 @@
#include "qqmllist_p.h"
#include "qqmltypenamecache_p.h"
#include "qqmlnotifier_p.h"
-#include <private/qqmldebugserver_p.h>
-#include <private/qqmlprofilerservice_p.h>
-#include <private/qv4debugservice_p.h>
-#include <private/qdebugmessageservice_p.h>
-#include <private/qqmlenginecontrolservice_p.h>
+#include <private/qqmldebugconnector_p.h>
#include "qqmlincubator.h"
#include "qqmlabstracturlinterceptor.h"
#include <private/qqmlboundsignal_p.h>
@@ -225,7 +220,6 @@ void QQmlEnginePrivate::activateDesignerMode()
/*!
\class QQmlImageProviderBase
\brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
- \mainclass
\inmodule QtQml
Image providers must be registered with the QML engine. The only information the QML
@@ -247,6 +241,10 @@ void QQmlEnginePrivate::activateDesignerMode()
The QQuickImageProvider::requestPixmap() method will be called for all image requests.
\value Texture The Image Provider provides QSGTextureProvider based images.
The QQuickImageProvider::requestTexture() method will be called for all image requests.
+ \value ImageResponse The Image provider provides QQuickTextureFactory based images.
+ Should only be used in QQuickAsyncImageProvider or its subclasses.
+ The QQuickAsyncImageProvider::requestImageResponse() method will be called for all image requests.
+ Since Qt 5.6
\omitvalue Invalid
*/
@@ -594,7 +592,7 @@ the same object as is returned from the Qt.include() call.
// Qt.include() is implemented in qv4include.cpp
QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
-: propertyCapture(0), rootContext(0), isDebugging(false),
+: propertyCapture(0), rootContext(0),
profiler(0), outputWarningsToMsgLog(true),
cleanup(0), erroredBindings(0), inProgressCreations(0),
workerScriptEngine(0),
@@ -607,8 +605,8 @@ QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
QQmlEnginePrivate::~QQmlEnginePrivate()
{
- typedef QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator TypePropertyCacheIt;
- typedef QHash<int, QQmlCompiledData *>::Iterator CompositeTypesIt;
+ typedef QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::const_iterator TypePropertyCacheIt;
+ typedef QHash<int, QQmlCompiledData *>::const_iterator CompositeTypesIt;
if (inProgressCreations)
qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
@@ -627,9 +625,9 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
if (incubationController) incubationController->d = 0;
incubationController = 0;
- for (TypePropertyCacheIt iter = typePropertyCache.begin(), end = typePropertyCache.end(); iter != end; ++iter)
+ for (TypePropertyCacheIt iter = typePropertyCache.cbegin(), end = typePropertyCache.cend(); iter != end; ++iter)
(*iter)->release();
- for (CompositeTypesIt iter = m_compositeTypes.begin(), end = m_compositeTypes.end(); iter != end; ++iter) {
+ for (CompositeTypesIt iter = m_compositeTypes.cbegin(), end = m_compositeTypes.cend(); iter != end; ++iter) {
iter.value()->isRegisteredWithEngine = false;
// since unregisterInternalCompositeType() will not be called in this
@@ -666,6 +664,17 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
}
}
+QQmlData::QQmlData()
+ : ownedByQml1(false), ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false),
+ hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false),
+ hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false), bindingBitsSize(0), bindingBits(0), notifyList(0), context(0), outerContext(0),
+ bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0),
+ lineNumber(0), columnNumber(0), jsEngineId(0), compiledData(0), deferredData(0),
+ propertyCache(0), guards(0), extendedData(0)
+{
+ init();
+}
+
void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
{
QQmlData *ddata = static_cast<QQmlData *>(d);
@@ -799,7 +808,7 @@ void QQmlData::markAsDeleted(QObject *o)
QQmlData::setQueuedForDeletion(o);
QObjectPrivate *p = QObjectPrivate::get(o);
- for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
+ for (QList<QObject *>::const_iterator it = p->children.constBegin(), end = p->children.constEnd(); it != end; ++it) {
QQmlData::markAsDeleted(*it);
}
}
@@ -824,14 +833,12 @@ void QQmlData::flushPendingBindingImpl(int coreIndex)
// Find the binding
QQmlAbstractBinding *b = bindings;
- while (b && *b->m_mePtr && b->propertyIndex() != coreIndex)
+ while (b && b->targetPropertyIndex() != coreIndex)
b = b->nextBinding();
- if (b && b->propertyIndex() == coreIndex) {
- b->clear();
+ if (b && b->targetPropertyIndex() == coreIndex)
b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
QQmlPropertyPrivate::DontRemoveBinding);
- }
}
bool QQmlEnginePrivate::baseModulesUninitialized = true;
@@ -861,15 +868,9 @@ void QQmlEnginePrivate::init()
rootContext = new QQmlContext(q,true);
- if (QCoreApplication::instance()->thread() == q->thread() &&
- QQmlEngineDebugService::isDebuggingEnabled()) {
- isDebugging = true;
- QQmlEngineDebugService::instance();
- QV4DebugService::instance();
- QQmlProfilerService::instance();
- QDebugMessageService::instance();
- QQmlEngineControlService::instance();
- QQmlDebugServer::instance()->addEngine(q);
+ if (QCoreApplication::instance()->thread() == q->thread() && QQmlDebugConnector::instance()) {
+ QQmlDebugConnector::instance()->open();
+ QQmlDebugConnector::instance()->addEngine(q);
}
}
@@ -886,7 +887,6 @@ QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
\since 5.0
\inmodule QtQml
\brief The QQmlEngine class provides an environment for instantiating QML components.
- \mainclass
Each QML component is instantiated in a QQmlContext.
QQmlContext's are essential for passing data to QML
@@ -947,8 +947,9 @@ QQmlEngine::QQmlEngine(QQmlEnginePrivate &dd, QObject *parent)
QQmlEngine::~QQmlEngine()
{
Q_D(QQmlEngine);
- if (d->isDebugging)
- QQmlDebugServer::instance()->removeEngine(this);
+ QQmlDebugConnector *server = QQmlDebugConnector::instance();
+ if (server)
+ server->removeEngine(this);
d->typeLoader.invalidate();
@@ -1237,7 +1238,7 @@ bool QQmlEngine::outputWarningsToStandardError() const
If \a enabled is true, any warning messages generated by QML will be
output to stderr and emitted by the warnings() signal. If \a enabled
- is false, on the warnings() signal will be emitted. This allows
+ is false, only the warnings() signal will be emitted. This allows
applications to handle warning output themselves.
The default value is true.
@@ -1433,7 +1434,8 @@ QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool cre
if (rv || !create)
return rv;
- QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
+ QQmlEnginePrivate *engine = QQmlEnginePrivate::get(data->context);
+ QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(engine, id);
if (!pf)
return 0;
@@ -1448,8 +1450,10 @@ QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool cre
QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
const QMetaObject *attachedMetaObject, bool create)
{
- if (*idCache == -1)
- *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
+ if (*idCache == -1) {
+ QQmlEngine *engine = object ? qmlEngine(object) : 0;
+ *idCache = QQmlMetaType::attachedPropertiesFuncId(engine ? QQmlEnginePrivate::get(engine) : 0, attachedMetaObject);
+ }
if (*idCache == -1 || !object)
return 0;
@@ -1492,51 +1496,6 @@ Q_QML_EXPORT QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *o
#endif // QT_DEPRECATED_SINCE(5, 1)
-QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
-{
-#ifndef QQML_NO_DEBUG_PROTOCOL
- if (!QQmlEnginePrivate::qml_debugging_enabled
- && printWarning) {
- qDebug("QML debugging is enabled. Only use this in a safe environment.");
- }
- QQmlEnginePrivate::qml_debugging_enabled = true;
-#else
- Q_UNUSED(printWarning);
-#endif
-}
-
-/*!
- * \enum QQmlDebuggingEnabler::StartMode
- *
- * Defines the debug server's start behavior. You can interrupt QML engines starting while a debug
- * client is connecting, in order to set breakpoints in or profile startup code.
- *
- * \value DoNotWaitForClient Run any QML engines as usual while the debug services are connecting.
- * \value WaitForClient If a QML engine starts while the debug services are connecting,
- * interrupt it until they are done.
- */
-
-/*!
- * Enables debugging for QML engines created after calling this function. The debug server will
- * listen on \a port at \a hostName and block the QML engine until it receives a connection if
- * \a mode is \c WaitForClient. If \a mode is not specified it won't block and if \a hostName is not
- * specified it will listen on all available interfaces. You can only start one debug server at a
- * time. A debug server may have already been started if the -qmljsdebugger= command line argument
- * was given. This method returns \c true if a new debug server was successfully started, or
- * \c false otherwise.
- */
-bool QQmlDebuggingEnabler::startTcpDebugServer(int port, StartMode mode, const QString &hostName)
-{
-#ifndef QQML_NO_DEBUG_PROTOCOL
- return QQmlDebugServer::enable(port, port, mode == WaitForClient, hostName);
-#else
- Q_UNUSED(port);
- Q_UNUSED(block);
- Q_UNUSED(hostName);
- return false;
-#endif
-}
-
class QQmlDataExtended {
public:
QQmlDataExtended();
@@ -1678,12 +1637,11 @@ void QQmlData::destroyed(QObject *object)
QQmlAbstractBinding *binding = bindings;
while (binding) {
- QQmlAbstractBinding *next = binding->nextBinding();
binding->setAddedToObject(false);
- binding->setNextBinding(0);
- binding->destroy();
- binding = next;
+ binding = binding->nextBinding();
}
+ if (bindings && !bindings->ref.deref())
+ delete bindings;
if (compiledData) {
compiledData->release();
@@ -1696,9 +1654,9 @@ void QQmlData::destroyed(QObject *object)
deferredData = 0;
}
- QQmlAbstractBoundSignal *signalHandler = signalHandlers;
+ QQmlBoundSignal *signalHandler = signalHandlers;
while (signalHandler) {
- if (signalHandler->isEvaluating()) {
+ if (signalHandler->isNotifying()) {
// The object is being deleted during signal handler evaluation.
// This will cause a crash due to invalid memory access when the
// evaluation has completed.
@@ -1710,7 +1668,7 @@ void QQmlData::destroyed(QObject *object)
if (location.sourceFile.isEmpty())
location.sourceFile = QStringLiteral("<Unknown File>");
locationString.append(location.sourceFile);
- locationString.append(QString::fromLatin1(":%0: ").arg(location.line));
+ locationString.append(QStringLiteral(":%0: ").arg(location.line));
QString source = expr->expression();
if (source.size() > 100) {
source.truncate(96);
@@ -1727,7 +1685,7 @@ void QQmlData::destroyed(QObject *object)
"%s", object, qPrintable(locationString));
}
- QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
+ QQmlBoundSignal *next = signalHandler->m_nextSignal;
signalHandler->m_prevSignal = 0;
signalHandler->m_nextSignal = 0;
delete signalHandler;
@@ -2140,8 +2098,7 @@ QString QQmlEngine::offlineStoragePath() const
return d->offlineStoragePath;
}
-QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
- QQmlError &error)
+QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion)
{
QList<QQmlType *> types;
@@ -2203,10 +2160,10 @@ QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersi
// Properties override:
// * other elements of the same name
+#if 0
bool overloadError = false;
QString overloadName;
-#if 0
for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
!overloadError && iter != raw->stringCache.end();
++iter) {
@@ -2223,7 +2180,6 @@ QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersi
overloadError = true;
}
}
-#endif
if (overloadError) {
if (hasCopied) raw->release();
@@ -2231,6 +2187,7 @@ QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersi
error.setDescription(QLatin1String("Type ") + type->qmlTypeName() + QLatin1Char(' ') + QString::number(type->majorVersion()) + QLatin1Char('.') + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\". This is an error in the type's implementation."));
return 0;
}
+#endif
if (!hasCopied) raw->addref();
typePropertyCache.insert(qMakePair(type, minorVersion), raw);
@@ -2281,8 +2238,8 @@ bool QQmlEnginePrivate::isList(int t) const
int QQmlEnginePrivate::listType(int t) const
{
Locker locker(this);
- QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
- if (iter != m_qmlLists.end())
+ QHash<int, int>::ConstIterator iter = m_qmlLists.constFind(t);
+ if (iter != m_qmlLists.cend())
return *iter;
else
return QQmlMetaType::listType(t);
@@ -2291,8 +2248,8 @@ int QQmlEnginePrivate::listType(int t) const
QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
{
Locker locker(this);
- QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
- if (iter != m_compositeTypes.end()) {
+ QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.constFind(t);
+ if (iter != m_compositeTypes.cend()) {
return QQmlMetaObject((*iter)->rootPropertyCache);
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
@@ -2303,8 +2260,8 @@ QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
{
Locker locker(this);
- QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
- if (iter != m_compositeTypes.end()) {
+ QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.constFind(t);
+ if (iter != m_compositeTypes.cend()) {
return QQmlMetaObject((*iter)->rootPropertyCache);
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
@@ -2315,8 +2272,8 @@ QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
{
Locker locker(this);
- QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
- if (iter != m_compositeTypes.end()) {
+ QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constFind(t);
+ if (iter != m_compositeTypes.cend()) {
return (*iter)->rootPropertyCache;
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
@@ -2328,8 +2285,8 @@ QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
{
Locker locker(this);
- QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
- if (iter != m_compositeTypes.end()) {
+ QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constFind(t);
+ if (iter != m_compositeTypes.cend()) {
return (*iter)->rootPropertyCache;
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
@@ -2482,6 +2439,8 @@ bool QQml_isFileCaseCorrect(const QString &fileName, int lengthIn /* = -1 */)
Returns the QQmlEngine associated with \a object, if any. This is equivalent to
QQmlEngine::contextForObject(object)->engine(), but more efficient.
+ \note Add \c{#include <QtQml>} to use this function.
+
\sa {QQmlEngine::contextForObject()}{contextForObject()}, qmlContext()
*/
@@ -2492,6 +2451,8 @@ bool QQml_isFileCaseCorrect(const QString &fileName, int lengthIn /* = -1 */)
Returns the QQmlContext associated with \a object, if any. This is equivalent to
QQmlEngine::contextForObject(object).
+ \note Add \c{#include <QtQml>} to use this function.
+
\sa {QQmlEngine::contextForObject()}{contextForObject()}, qmlEngine()
*/
diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h
index df673c1fd5..61a884279d 100644
--- a/src/qml/qml/qqmlengine.h
+++ b/src/qml/qml/qqmlengine.h
@@ -52,7 +52,9 @@ public:
Image,
Pixmap,
Texture,
- Invalid
+ Invalid,
+ ImageResponse
+ // ### Qt6: reorder these, and give Invalid a fixed large value
};
enum Flag {
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index f1fbad3cf8..26ee3bd655 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -85,7 +85,6 @@ class QQmlImportDatabase;
class QNetworkReply;
class QNetworkAccessManager;
class QQmlNetworkAccessManagerFactory;
-class QQmlAbstractBinding;
class QQmlTypeNameCache;
class QQmlComponentAttached;
class QQmlCleanup;
@@ -95,6 +94,7 @@ class QQmlObjectCreator;
class QDir;
class QQmlIncubator;
class QQmlProfiler;
+class QQmlPropertyCapture;
// This needs to be declared here so that the pool for it can live in QQmlEnginePrivate.
// The inline method definitions are in qqmljavascriptexpression_p.h
@@ -123,21 +123,11 @@ public:
// is just qmlClearTypeRegistrations (which can't be called while an engine exists)
static bool baseModulesUninitialized;
- class PropertyCapture {
- public:
- inline virtual ~PropertyCapture() {}
- virtual void captureProperty(QQmlNotifier *) = 0;
- virtual void captureProperty(QObject *, int, int) = 0;
- };
-
- PropertyCapture *propertyCapture;
- inline void captureProperty(QQmlNotifier *);
- inline void captureProperty(QObject *, int, int);
+ QQmlPropertyCapture *propertyCapture;
QRecyclePool<QQmlJavaScriptExpressionGuard> jsExpressionGuardPool;
QQmlContext *rootContext;
- bool isDebugging;
QQmlProfiler *profiler;
void enableProfiler();
@@ -208,7 +198,7 @@ public:
inline static void deleteInEngineThread(QQmlEngine *, T *);
// These methods may be called from the loader thread
- inline QQmlPropertyCache *cache(QQmlType *, int, QQmlError &error);
+ inline QQmlPropertyCache *cache(QQmlType *, int);
using QJSEnginePrivate::cache;
// These methods may be called from the loader thread
@@ -262,7 +252,7 @@ public:
private:
// Must be called locked
- QQmlPropertyCache *createCache(QQmlType *, int, QQmlError &error);
+ QQmlPropertyCache *createCache(QQmlType *, int);
// These members must be protected by a QQmlEnginePrivate::Locker as they are required by
// the threaded loader. Only access them through their respective accessor methods.
@@ -346,7 +336,7 @@ Returns a QQmlPropertyCache for \a type with \a minorVersion.
The returned cache is not referenced, so if it is to be stored, call addref().
*/
-QQmlPropertyCache *QQmlEnginePrivate::cache(QQmlType *type, int minorVersion, QQmlError &error)
+QQmlPropertyCache *QQmlEnginePrivate::cache(QQmlType *type, int minorVersion)
{
Q_ASSERT(type);
@@ -355,7 +345,7 @@ QQmlPropertyCache *QQmlEnginePrivate::cache(QQmlType *type, int minorVersion, QQ
Locker locker(this);
QQmlPropertyCache *rv = typePropertyCache.value(qMakePair(type, minorVersion));
- if (!rv) rv = createCache(type, minorVersion, error);
+ if (!rv) rv = createCache(type, minorVersion);
return rv;
}
@@ -414,18 +404,6 @@ QQmlEnginePrivate *QQmlEnginePrivate::get(QV4::ExecutionEngine *e)
return get(qmlEngine);
}
-void QQmlEnginePrivate::captureProperty(QQmlNotifier *n)
-{
- if (propertyCapture)
- propertyCapture->captureProperty(n);
-}
-
-void QQmlEnginePrivate::captureProperty(QObject *o, int c, int n)
-{
- if (propertyCapture)
- propertyCapture->captureProperty(o, c, n);
-}
-
void QQmlEnginePrivate::setDebugChangesCache(const QHash<QUrl, QByteArray> &changes)
{
Locker locker(this);
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index 35e0bc8c64..e9700712e9 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -45,13 +45,8 @@
QT_BEGIN_NAMESPACE
-static QQmlJavaScriptExpression::VTable QQmlExpressionPrivate_jsvtable = {
- QQmlExpressionPrivate::expressionIdentifier,
- QQmlExpressionPrivate::expressionChanged
-};
-
QQmlExpressionPrivate::QQmlExpressionPrivate()
-: QQmlJavaScriptExpression(&QQmlExpressionPrivate_jsvtable),
+: QQmlJavaScriptExpression(),
expressionFunctionValid(true),
line(0), column(0)
{
@@ -65,7 +60,7 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, QOb
{
expression = expr;
- QQmlAbstractExpression::setContext(ctxt);
+ QQmlJavaScriptExpression::setContext(ctxt);
setScopeObject(me);
expressionFunctionValid = false;
}
@@ -74,9 +69,9 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, QV4::Function *runtimeFu
{
expressionFunctionValid = true;
QV4::ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(ctxt->engine);
- function.set(engine, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, me, runtimeFunction));
+ m_function.set(engine, QV4::FunctionObject::createQmlFunction(ctxt, me, runtimeFunction));
- QQmlAbstractExpression::setContext(ctxt);
+ QQmlJavaScriptExpression::setContext(ctxt);
setScopeObject(me);
}
@@ -246,18 +241,12 @@ void QQmlExpression::setExpression(const QString &expression)
// Must be called with a valid handle scope
QV4::ReturnedValue QQmlExpressionPrivate::v4value(bool *isUndefined)
{
- Q_Q(QQmlExpression);
-
- QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(q->engine())->v4engine();
-
if (!expressionFunctionValid) {
- function.set(v4, qmlBinding(context(), scopeObject(), expression, url, line, &qmlscope));
+ createQmlBinding(context(), scopeObject(), expression, url, line);
expressionFunctionValid = true;
}
- QV4::Scope scope(v4);
- QV4::ScopedValue f(scope, function.value());
- return evaluate(context(), f, isUndefined);
+ return evaluate(isUndefined);
}
QVariant QQmlExpressionPrivate::value(bool *isUndefined)
@@ -432,22 +421,15 @@ QQmlError QQmlExpression::error() const
calling QQmlExpression::evaluate()) before this signal will be emitted.
*/
-void QQmlExpressionPrivate::expressionChanged(QQmlJavaScriptExpression *e)
-{
- QQmlExpressionPrivate *This = static_cast<QQmlExpressionPrivate *>(e);
- This->expressionChanged();
-}
-
void QQmlExpressionPrivate::expressionChanged()
{
Q_Q(QQmlExpression);
emit q->valueChanged();
}
-QString QQmlExpressionPrivate::expressionIdentifier(QQmlJavaScriptExpression *e)
+QString QQmlExpressionPrivate::expressionIdentifier()
{
- QQmlExpressionPrivate *This = static_cast<QQmlExpressionPrivate *>(e);
- return QLatin1Char('"') + This->expression + QLatin1Char('"');
+ return QLatin1Char('"') + expression + QLatin1Char('"');
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlexpression_p.h b/src/qml/qml/qqmlexpression_p.h
index d8da387878..2303539194 100644
--- a/src/qml/qml/qqmlexpression_p.h
+++ b/src/qml/qml/qqmlexpression_p.h
@@ -52,7 +52,6 @@
#include <private/qflagpointer_p.h>
#include <private/qdeletewatcher_p.h>
#include <private/qpointervaluepair_p.h>
-#include <private/qqmlabstractexpression_p.h>
#include <private/qqmljavascriptexpression_p.h>
QT_BEGIN_NAMESPACE
@@ -60,8 +59,7 @@ QT_BEGIN_NAMESPACE
class QQmlExpression;
class QString;
class QQmlExpressionPrivate : public QObjectPrivate,
- public QQmlJavaScriptExpression,
- public QQmlAbstractExpression
+ public QQmlJavaScriptExpression
{
Q_DECLARE_PUBLIC(QQmlExpression)
public:
@@ -82,16 +80,12 @@ public:
bool expressionFunctionValid:1;
- // "Inherited" from QQmlJavaScriptExpression
- static QString expressionIdentifier(QQmlJavaScriptExpression *);
- static void expressionChanged(QQmlJavaScriptExpression *);
+ // Inherited from QQmlJavaScriptExpression
+ virtual QString expressionIdentifier();
virtual void expressionChanged();
QString expression;
- QV4::PersistentValue qmlscope;
- QV4::PersistentValue function;
-
QString url; // This is a QString for a reason. QUrls are slooooooow...
quint16 line;
quint16 column;
diff --git a/src/qml/qml/qqmlfileselector.cpp b/src/qml/qml/qqmlfileselector.cpp
index 8597e8a5c7..ab880b7069 100644
--- a/src/qml/qml/qqmlfileselector.cpp
+++ b/src/qml/qml/qqmlfileselector.cpp
@@ -123,6 +123,12 @@ QQmlFileSelectorPrivate::QQmlFileSelectorPrivate()
myInstance.reset(new QQmlFileSelectorInterceptor(this));
}
+QQmlFileSelectorPrivate::~QQmlFileSelectorPrivate()
+{
+ if (ownSelector)
+ delete selector;
+}
+
/*!
Sets the QFileSelector instance for use by the QQmlFileSelector to \a selector.
QQmlFileSelector does not take ownership of the new QFileSelector. To reset QQmlFileSelector
diff --git a/src/qml/qml/qqmlfileselector_p.h b/src/qml/qml/qqmlfileselector_p.h
index 58248bf1c1..46ea027bc1 100644
--- a/src/qml/qml/qqmlfileselector_p.h
+++ b/src/qml/qml/qqmlfileselector_p.h
@@ -60,6 +60,8 @@ class Q_QML_PRIVATE_EXPORT QQmlFileSelectorPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QQmlFileSelector)
public:
QQmlFileSelectorPrivate();
+ ~QQmlFileSelectorPrivate();
+
QFileSelector* selector;
QPointer<QQmlEngine> engine;
bool ownSelector;
diff --git a/src/qml/qml/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp
index d904242f93..aa2b4b6aee 100644
--- a/src/qml/qml/qqmlglobal.cpp
+++ b/src/qml/qml/qqmlglobal.cpp
@@ -62,40 +62,11 @@ const QMetaObject *QQmlValueTypeProvider::metaObjectForMetaType(int type)
return 0;
}
-bool QQmlValueTypeProvider::initValueType(int type, void *data, size_t n)
+bool QQmlValueTypeProvider::initValueType(int type, QVariant& dst)
{
- Q_ASSERT(data);
-
- QQmlValueTypeProvider *p = this;
- do {
- if (p->init(type, data, n))
- return true;
- } while ((p = p->next));
-
- return false;
-}
-
-bool QQmlValueTypeProvider::destroyValueType(int type, void *data, size_t n)
-{
- Q_ASSERT(data);
-
QQmlValueTypeProvider *p = this;
do {
- if (p->destroy(type, data, n))
- return true;
- } while ((p = p->next));
-
- return false;
-}
-
-bool QQmlValueTypeProvider::copyValueType(int type, const void *src, void *dst, size_t n)
-{
- Q_ASSERT(src);
- Q_ASSERT(dst);
-
- QQmlValueTypeProvider *p = this;
- do {
- if (p->copy(type, src, dst, n))
+ if (p->init(type, dst))
return true;
} while ((p = p->next));
@@ -188,14 +159,13 @@ QVariant QQmlValueTypeProvider::createVariantFromJsObject(int type, QQmlV4Handle
return QVariant();
}
-bool QQmlValueTypeProvider::equalValueType(int type, const void *lhs, const void *rhs, size_t rhsSize)
+bool QQmlValueTypeProvider::equalValueType(int type, const void *lhs, const QVariant& rhs)
{
Q_ASSERT(lhs);
- Q_ASSERT(rhs);
QQmlValueTypeProvider *p = this;
do {
- if (p->equal(type, lhs, rhs, rhsSize))
+ if (p->equal(type, lhs, rhs))
return true;
} while ((p = p->next));
@@ -216,28 +186,26 @@ bool QQmlValueTypeProvider::storeValueType(int type, const void *src, void *dst,
return false;
}
-bool QQmlValueTypeProvider::readValueType(int srcType, const void *src, size_t srcSize, int dstType, void *dst)
+bool QQmlValueTypeProvider::readValueType(const QVariant& src, void *dst, int dstType)
{
- Q_ASSERT(src);
Q_ASSERT(dst);
QQmlValueTypeProvider *p = this;
do {
- if (p->read(srcType, src, srcSize, dstType, dst))
+ if (p->read(src, dst, dstType))
return true;
} while ((p = p->next));
return false;
}
-bool QQmlValueTypeProvider::writeValueType(int type, const void *src, void *dst, size_t n)
+bool QQmlValueTypeProvider::writeValueType(int type, const void *src, QVariant& dst)
{
Q_ASSERT(src);
- Q_ASSERT(dst);
QQmlValueTypeProvider *p = this;
do {
- if (p->write(type, src, dst, n))
+ if (p->write(type, src, dst))
return true;
} while ((p = p->next));
@@ -245,19 +213,17 @@ bool QQmlValueTypeProvider::writeValueType(int type, const void *src, void *dst,
}
const QMetaObject *QQmlValueTypeProvider::getMetaObjectForMetaType(int) { return 0; }
-bool QQmlValueTypeProvider::init(int, void *, size_t) { return false; }
-bool QQmlValueTypeProvider::destroy(int, void *, size_t) { return false; }
-bool QQmlValueTypeProvider::copy(int, const void *, void *, size_t) { return false; }
+bool QQmlValueTypeProvider::init(int, QVariant&) { return false; }
bool QQmlValueTypeProvider::create(int, int, const void *[], QVariant *) { return false; }
bool QQmlValueTypeProvider::createFromString(int, const QString &, void *, size_t) { return false; }
bool QQmlValueTypeProvider::createStringFrom(int, const void *, QString *) { return false; }
bool QQmlValueTypeProvider::variantFromString(const QString &, QVariant *) { return false; }
bool QQmlValueTypeProvider::variantFromString(int, const QString &, QVariant *) { return false; }
bool QQmlValueTypeProvider::variantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, QVariant *) { return false; }
-bool QQmlValueTypeProvider::equal(int, const void *, const void *, size_t) { return false; }
+bool QQmlValueTypeProvider::equal(int, const void *, const QVariant&) { return false; }
bool QQmlValueTypeProvider::store(int, const void *, void *, size_t) { return false; }
-bool QQmlValueTypeProvider::read(int, const void *, size_t, int, void *) { return false; }
-bool QQmlValueTypeProvider::write(int, const void *, void *, size_t) { return false; }
+bool QQmlValueTypeProvider::read(const QVariant&, void *, int) { return false; }
+bool QQmlValueTypeProvider::write(int, const void *, QVariant&) { return false; }
Q_GLOBAL_STATIC(QQmlValueTypeProvider, nullValueTypeProvider)
static QQmlValueTypeProvider *valueTypeProvider = 0;
@@ -359,7 +325,7 @@ QObject *QQmlGuiProvider::inputMethod()
{
// We don't have any input method code by default
QObject *o = new QObject();
- o->setObjectName(QString::fromLatin1("No inputMethod available"));
+ o->setObjectName(QStringLiteral("No inputMethod available"));
QQmlEngine::setObjectOwnership(o, QQmlEngine::JavaScriptOwnership);
return o;
}
@@ -368,7 +334,7 @@ QObject *QQmlGuiProvider::inputMethod()
QObject *QQmlGuiProvider::styleHints()
{
QObject *o = new QObject();
- o->setObjectName(QString::fromLatin1("No styleHints available"));
+ o->setObjectName(QStringLiteral("No styleHints available"));
QQmlEngine::setObjectOwnership(o, QQmlEngine::JavaScriptOwnership);
return o;
}
diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h
index 7856d85376..23cfc24e7a 100644
--- a/src/qml/qml/qqmlglobal_p.h
+++ b/src/qml/qml/qqmlglobal_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLGLOBAL_H
#define QQMLGLOBAL_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qtqmlglobal_p.h>
#include <QtCore/QObject>
#include <private/qqmlpropertycache_p.h>
@@ -48,10 +59,12 @@ QT_BEGIN_NAMESPACE
{ \
static enum { Yes, No, Unknown } status = Unknown; \
if (status == Unknown) { \
- QByteArray v = qgetenv(#var); \
- bool value = !v.isEmpty() && v != "0" && v != "false"; \
- if (value) status = Yes; \
- else status = No; \
+ status = No; \
+ if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty(#var))) { \
+ const QByteArray v = qgetenv(#var); \
+ if (v != "0" && v != "false") \
+ status = Yes; \
+ } \
} \
return status == Yes; \
}
@@ -224,9 +237,7 @@ public:
const QMetaObject *metaObjectForMetaType(int);
- bool initValueType(int, void *, size_t);
- bool destroyValueType(int, void *, size_t);
- bool copyValueType(int, const void *, void *, size_t);
+ bool initValueType(int, QVariant&);
QVariant createValueType(int, int, const void *[]);
bool createValueFromString(int, const QString &, void *, size_t);
@@ -236,16 +247,14 @@ public:
QVariant createVariantFromString(int, const QString &, bool *);
QVariant createVariantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, bool*);
- bool equalValueType(int, const void *, const void *, size_t);
+ bool equalValueType(int, const void *, const QVariant&);
bool storeValueType(int, const void *, void *, size_t);
- bool readValueType(int, const void *, size_t, int, void *);
- bool writeValueType(int, const void *, void *, size_t);
+ bool readValueType(const QVariant&, void *, int);
+ bool writeValueType(int, const void *, QVariant&);
private:
virtual const QMetaObject *getMetaObjectForMetaType(int);
- virtual bool init(int, void *, size_t);
- virtual bool destroy(int, void *, size_t);
- virtual bool copy(int, const void *, void *, size_t);
+ virtual bool init(int, QVariant&);
virtual bool create(int, int, const void *[], QVariant *);
virtual bool createFromString(int, const QString &, void *, size_t);
@@ -255,10 +264,10 @@ private:
virtual bool variantFromString(int, const QString &, QVariant *);
virtual bool variantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, QVariant *);
- virtual bool equal(int, const void *, const void *, size_t);
+ virtual bool equal(int, const void *, const QVariant&);
virtual bool store(int, const void *, void *, size_t);
- virtual bool read(int, const void *, size_t, int, void *);
- virtual bool write(int, const void *, void *, size_t);
+ virtual bool read(const QVariant&, void *, int);
+ virtual bool write(int, const void *, QVariant&);
friend Q_QML_PRIVATE_EXPORT void QQml_addValueTypeProvider(QQmlValueTypeProvider *);
friend Q_QML_PRIVATE_EXPORT void QQml_removeValueTypeProvider(QQmlValueTypeProvider *);
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index ff48a10d95..d538199520 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -125,7 +125,9 @@ bool isPathAbsolute(const QString &path)
}
// If the type does not already exist as a file import, add the type and return the new type
-QQmlType *getTypeForUrl(const QString &urlString, const QHashedStringRef& typeName, bool isCompositeSingleton, QList<QQmlError> *errors)
+QQmlType *getTypeForUrl(const QString &urlString, const QHashedStringRef& typeName,
+ bool isCompositeSingleton, QList<QQmlError> *errors,
+ int majorVersion=-1, int minorVersion=-1)
{
QUrl url(urlString);
QQmlType *ret = QQmlMetaType::qmlType(url);
@@ -140,8 +142,8 @@ QQmlType *getTypeForUrl(const QString &urlString, const QHashedStringRef& typeNa
QQmlPrivate::RegisterCompositeSingletonType reg = {
url,
"", //Empty URI indicates loaded via file imports
- -1,
- -1,
+ majorVersion,
+ minorVersion,
buf.constData()
};
ret = QQmlMetaType::qmlTypeFromIndex(QQmlPrivate::qmlregister(QQmlPrivate::CompositeSingletonRegistration, &reg));
@@ -149,8 +151,8 @@ QQmlType *getTypeForUrl(const QString &urlString, const QHashedStringRef& typeNa
QQmlPrivate::RegisterCompositeType reg = {
url,
"", //Empty URI indicates loaded via file imports
- -1,
- -1,
+ majorVersion,
+ minorVersion,
buf.constData()
};
ret = QQmlMetaType::qmlTypeFromIndex(QQmlPrivate::qmlregister(QQmlPrivate::CompositeRegistration, &reg));
@@ -169,6 +171,7 @@ QQmlType *getTypeForUrl(const QString &urlString, const QHashedStringRef& typeNa
} // namespace
+#ifndef QT_NO_LIBRARY
struct RegisteredPlugin {
QString uri;
QPluginLoader* loader;
@@ -193,6 +196,7 @@ void qmlClearEnginePlugins()
}
typedef QPair<QStaticPlugin, QJsonArray> StaticPluginPair;
+#endif
class QQmlImportNamespace
{
@@ -292,9 +296,10 @@ public:
const QString &uri, const QString &url,
int vmaj, int vmin, QV4::CompiledData::Import::ImportType type,
QList<QQmlError> *errors, bool lowPrecedence = false);
-
+#ifndef QT_NO_LIBRARY
bool populatePluginPairVector(QVector<StaticPluginPair> &result, const QString &uri,
const QString &qmldirPath, QList<QQmlError> *errors);
+#endif
};
/*!
@@ -382,7 +387,7 @@ void QQmlImports::populateCache(QQmlTypeNameCache *cache) const
// We need to exclude the entry for the current baseUrl. This can happen for example
// when handling qmldir files on the remote dir case and the current type is marked as
// singleton.
-bool excludeBaseUrl(const QString &importUrl, const QString &fileName, const QString baseUrl)
+bool excludeBaseUrl(const QString &importUrl, const QString &fileName, const QString &baseUrl)
{
if (importUrl.isEmpty())
return false;
@@ -398,7 +403,7 @@ bool excludeBaseUrl(const QString &importUrl, const QString &fileName, const QSt
return true;
}
-void findCompositeSingletons(const QQmlImportNamespace &set, QList<QQmlImports::CompositeSingletonReference> &resultList, QUrl baseUrl)
+void findCompositeSingletons(const QQmlImportNamespace &set, QList<QQmlImports::CompositeSingletonReference> &resultList, const QUrl &baseUrl)
{
typedef QQmlDirComponents::const_iterator ConstIterator;
@@ -413,6 +418,8 @@ void findCompositeSingletons(const QQmlImportNamespace &set, QList<QQmlImports::
QQmlImports::CompositeSingletonReference ref;
ref.typeName = cit->typeName;
ref.prefix = set.prefix;
+ ref.majorVersion = cit->majorVersion;
+ ref.minorVersion = cit->minorVersion;
resultList.append(ref);
}
}
@@ -653,7 +660,10 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader,
}
if (candidate != end) {
- QQmlType *returnType = getTypeForUrl(componentUrl, type, isCompositeSingleton, 0);
+ int major = vmajor ? *vmajor : -1;
+ int minor = vminor ? *vminor : -1;
+ QQmlType *returnType = getTypeForUrl(componentUrl, type, isCompositeSingleton, 0,
+ major, minor);
if (type_return)
*type_return = returnType;
return returnType != 0;
@@ -826,6 +836,7 @@ QQmlImportNamespace *QQmlImportsPrivate::findQualifiedNamespace(const QHashedStr
}
+#ifndef QT_NO_LIBRARY
/*!
Get all static plugins that are QML plugins and has a meta data URI that begins with \a uri.
Note that if e.g uri == "a", and different plugins have meta data "a", "a.2.1", "a.b.c", all
@@ -869,6 +880,7 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &res
}
return true;
}
+#endif
/*!
Import an extension defined by a qmldir file.
@@ -995,6 +1007,13 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
}
#else
+ Q_UNUSED(qmldirFilePath);
+ Q_UNUSED(uri);
+ Q_UNUSED(vmaj);
+ Q_UNUSED(vmin);
+ Q_UNUSED(database);
+ Q_UNUSED(qmldir);
+ Q_UNUSED(errors);
return false;
#endif // QT_NO_LIBRARY
return true;
@@ -1550,8 +1569,8 @@ QQmlImportDatabase::QQmlImportDatabase(QQmlEngine *e)
addImportPath(installImportsPath);
// env import paths
- QByteArray envImportPath = qgetenv("QML2_IMPORT_PATH");
- if (!envImportPath.isEmpty()) {
+ if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QML2_IMPORT_PATH"))) {
+ const QByteArray envImportPath = qgetenv("QML2_IMPORT_PATH");
#if defined(Q_OS_WIN)
QLatin1Char pathSep(';');
#else
@@ -1639,8 +1658,6 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader,
\header \li Platform \li Valid suffixes
\row \li Windows \li \c .dll
\row \li Unix/Linux \li \c .so
- \row \li AIX \li \c .a
- \row \li HP-UX \li \c .sl, \c .so (HP-UXi)
\row \li OS X \li \c .dylib, \c .bundle, \c .so
\endtable
@@ -1657,9 +1674,7 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader,
<< QLatin1String("d.dll") // try a qmake-style debug build first
# endif
<< QLatin1String(".dll"));
-#else
-
-# if defined(Q_OS_DARWIN)
+#elif defined(Q_OS_DARWIN)
return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName,
QStringList()
@@ -1673,31 +1688,8 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader,
<< QLatin1String(".so")
<< QLatin1String(".bundle"),
QLatin1String("lib"));
-# else // Generic Unix
- QStringList validSuffixList;
-
-# if defined(Q_OS_HPUX)
-/*
- See "HP-UX Linker and Libraries User's Guide", section "Link-time Differences between PA-RISC and IPF":
- "In PA-RISC (PA-32 and PA-64) shared libraries are suffixed with .sl. In IPF (32-bit and 64-bit),
- the shared libraries are suffixed with .so. For compatibility, the IPF linker also supports the .sl suffix."
- */
- validSuffixList << QLatin1String(".sl");
-# if defined __ia64
- validSuffixList << QLatin1String(".so");
-# endif
-# elif defined(Q_OS_AIX)
- validSuffixList << QLatin1String(".a") << QLatin1String(".so");
-# elif defined(Q_OS_UNIX)
- validSuffixList << QLatin1String(".so");
-# endif
-
- // Examples of valid library names:
- // libfoo.so
-
- return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName, validSuffixList, QLatin1String("lib"));
-# endif
-
+# else // Unix
+ return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName, QStringList() << QLatin1String(".so"), QLatin1String("lib"));
#endif
}
@@ -1931,6 +1923,12 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba
return true;
#else
+ Q_UNUSED(instance);
+ Q_UNUSED(basePath);
+ Q_UNUSED(uri);
+ Q_UNUSED(typeNamespace);
+ Q_UNUSED(vmaj);
+ Q_UNUSED(errors);
return false;
#endif
}
@@ -2011,6 +2009,11 @@ bool QQmlImportDatabase::importDynamicPlugin(const QString &filePath, const QStr
return true;
#else
+ Q_UNUSED(filePath);
+ Q_UNUSED(uri);
+ Q_UNUSED(typeNamespace);
+ Q_UNUSED(vmaj);
+ Q_UNUSED(errors);
return false;
#endif
}
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index bda87f29b1..951b9752f3 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -118,6 +118,8 @@ public:
{
QString typeName;
QString prefix;
+ int majorVersion;
+ int minorVersion;
};
QList<CompositeSingletonReference> resolvedCompositeSingletons() const;
diff --git a/src/qml/qml/qqmlinfo.cpp b/src/qml/qml/qqmlinfo.cpp
index b9f96a724c..7a801032d3 100644
--- a/src/qml/qml/qqmlinfo.cpp
+++ b/src/qml/qml/qqmlinfo.cpp
@@ -109,34 +109,8 @@ QQmlInfo::~QQmlInfo()
if (object) {
engine = qmlEngine(d->object);
- QString typeName;
- QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
- if (type) {
- typeName = type->qmlTypeName();
- int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
- if (lastSlash != -1)
- typeName = typeName.mid(lastSlash+1);
- } else {
- typeName = QString::fromUtf8(object->metaObject()->className());
- int marker = typeName.indexOf(QLatin1String("_QMLTYPE_"));
- if (marker != -1)
- typeName = typeName.left(marker);
-
- marker = typeName.indexOf(QLatin1String("_QML_"));
- if (marker != -1) {
- typeName = typeName.left(marker);
- typeName += QLatin1Char('*');
- type = QQmlMetaType::qmlType(QMetaType::type(typeName.toLatin1()));
- if (type) {
- typeName = type->qmlTypeName();
- int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
- if (lastSlash != -1)
- typeName = typeName.mid(lastSlash+1);
- }
- }
- }
- d->buffer.prepend(QLatin1String("QML ") + typeName + QLatin1String(": "));
+ d->buffer.prepend(QLatin1String("QML ") + QQmlMetaType::prettyTypeName(object) + QLatin1String(": "));
QQmlData *ddata = QQmlData::get(object, false);
if (ddata && ddata->outerContext) {
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 02bd1c4b83..5938ebf5d7 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -35,7 +35,7 @@
#include <private/qqmlexpression_p.h>
#include <private/qqmlcontextwrapper_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
#include <private/qv4errorobject_p.h>
@@ -83,13 +83,22 @@ void QQmlDelayedError::catchJavaScriptException(QV4::ExecutionEngine *engine)
}
-QQmlJavaScriptExpression::QQmlJavaScriptExpression(VTable *v)
-: m_vtable(v)
+QQmlJavaScriptExpression::QQmlJavaScriptExpression()
+ : m_error(0),
+ m_context(0),
+ m_prevExpression(0),
+ m_nextExpression(0)
{
}
QQmlJavaScriptExpression::~QQmlJavaScriptExpression()
{
+ if (m_prevExpression) {
+ *m_prevExpression = m_nextExpression;
+ if (m_nextExpression)
+ m_nextExpression->m_prevExpression = m_prevExpression;
+ }
+
clearGuards();
if (m_scopeObject.isT2()) // notify DeleteWatcher of our deletion.
m_scopeObject.asT2()->_s = 0;
@@ -106,40 +115,62 @@ void QQmlJavaScriptExpression::resetNotifyOnValueChanged()
clearGuards();
}
-QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
- const QV4::Value &function, bool *isUndefined)
+void QQmlJavaScriptExpression::setContext(QQmlContextData *context)
{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(context->engine);
+ if (m_prevExpression) {
+ *m_prevExpression = m_nextExpression;
+ if (m_nextExpression)
+ m_nextExpression->m_prevExpression = m_prevExpression;
+ m_prevExpression = 0;
+ m_nextExpression = 0;
+ }
+
+ m_context = context;
+
+ if (context) {
+ m_nextExpression = context->expressions;
+ if (m_nextExpression)
+ m_nextExpression->m_prevExpression = &m_nextExpression;
+ m_prevExpression = &context->expressions;
+ context->expressions = this;
+ }
+}
+
+void QQmlJavaScriptExpression::refresh()
+{
+}
+
+QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(bool *isUndefined)
+{
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_context->engine);
QV4::Scope scope(v4);
QV4::ScopedCallData callData(scope);
- return evaluate(context, function, callData, isUndefined);
+ return evaluate(callData, isUndefined);
}
-QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
- const QV4::Value &function,
- QV4::CallData *callData,
- bool *isUndefined)
+QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, bool *isUndefined)
{
- Q_ASSERT(context && context->engine);
+ Q_ASSERT(m_context && m_context->engine);
- if (function.isUndefined()) {
+ QV4::Value *f = m_function.valueRef();
+ if (!f || f->isUndefined()) {
if (isUndefined)
*isUndefined = true;
return QV4::Encode::undefined();
}
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(m_context->engine);
// All code that follows must check with watcher before it accesses data members
// incase we have been deleted.
DeleteWatcher watcher(this);
Q_ASSERT(notifyOnValueChanged() || activeGuards.isEmpty());
- GuardCapture capture(context->engine, this, &watcher);
+ QQmlPropertyCapture capture(m_context->engine, this, &watcher);
- QQmlEnginePrivate::PropertyCapture *lastPropertyCapture = ep->propertyCapture;
- ep->propertyCapture = notifyOnValueChanged()?&capture:0;
+ QQmlPropertyCapture *lastPropertyCapture = ep->propertyCapture;
+ ep->propertyCapture = notifyOnValueChanged() ? &capture : 0;
if (notifyOnValueChanged())
@@ -148,14 +179,14 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine());
QV4::Scope scope(v4);
QV4::ScopedValue result(scope, QV4::Primitive::undefinedValue());
- callData->thisObject = v4->globalObject();
+ callData->thisObject = v4->globalObject;
if (scopeObject()) {
QV4::ScopedValue value(scope, QV4::QObjectWrapper::wrap(v4, scopeObject()));
if (value->isObject())
callData->thisObject = value;
}
- result = function.asFunctionObject()->call(callData);
+ result = f->as<QV4::FunctionObject>()->call(callData);
if (scope.hasException()) {
if (watcher.wasDeleted())
scope.engine->catchException(); // ignore exception
@@ -178,7 +209,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
capture.errorString = 0;
}
- while (Guard *g = capture.guards.takeFirst())
+ while (QQmlJavaScriptExpressionGuard *g = capture.guards.takeFirst())
g->Delete();
ep->propertyCapture = lastPropertyCapture;
@@ -186,7 +217,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
return result->asReturnedValue();
}
-void QQmlJavaScriptExpression::GuardCapture::captureProperty(QQmlNotifier *n)
+void QQmlPropertyCapture::captureProperty(QQmlNotifier *n)
{
if (watcher->wasDeleted())
return;
@@ -196,13 +227,13 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QQmlNotifier *n)
while (!guards.isEmpty() && !guards.first()->isConnected(n))
guards.takeFirst()->Delete();
- Guard *g = 0;
+ QQmlJavaScriptExpressionGuard *g = 0;
if (!guards.isEmpty()) {
g = guards.takeFirst();
g->cancelNotify();
Q_ASSERT(g->isConnected(n));
} else {
- g = Guard::New(expression, engine);
+ g = QQmlJavaScriptExpressionGuard::New(expression, engine);
g->connect(n);
}
@@ -213,7 +244,7 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QQmlNotifier *n)
\a n is in the signal index range (see QObjectPrivate::signalIndex()).
*/
-void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c, int n)
+void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n)
{
if (watcher->wasDeleted())
return;
@@ -223,7 +254,7 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c,
if (!errorString) {
errorString = new QStringList;
QString preamble = QLatin1String("QQmlExpression: Expression ") +
- expression->m_vtable->expressionIdentifier(expression) +
+ expression->expressionIdentifier() +
QLatin1String(" depends on non-NOTIFYable properties:");
errorString->append(preamble);
}
@@ -242,13 +273,13 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c,
while (!guards.isEmpty() && !guards.first()->isConnected(o, n))
guards.takeFirst()->Delete();
- Guard *g = 0;
+ QQmlJavaScriptExpressionGuard *g = 0;
if (!guards.isEmpty()) {
g = guards.takeFirst();
g->cancelNotify();
Q_ASSERT(g->isConnected(o, n));
} else {
- g = Guard::New(expression, engine);
+ g = QQmlJavaScriptExpressionGuard::New(expression, engine);
g->connect(o, n, engine);
}
@@ -256,33 +287,77 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c,
}
}
-void QQmlJavaScriptExpression::clearError()
+void QQmlPropertyCapture::registerQmlDependencies(QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction)
{
- if (m_vtable.hasValue()) {
- m_vtable.value().clearError();
- m_vtable.value().removeError();
+ // Let the caller check and avoid the function call :)
+ Q_ASSERT(compiledFunction->hasQmlDependencies());
+
+ QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
+ if (!ep)
+ return;
+ QQmlPropertyCapture *capture = ep->propertyCapture;
+ if (!capture)
+ return;
+
+ QV4::Scope scope(engine);
+ QV4::Scoped<QV4::QmlContext> context(scope, engine->qmlContext());
+ QQmlContextData *qmlContext = context->qmlContext();
+
+ const quint32 *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable();
+ const int idObjectDependencyCount = compiledFunction->nDependingIdObjects;
+ for (int i = 0; i < idObjectDependencyCount; ++i, ++idObjectDependency) {
+ Q_ASSERT(int(*idObjectDependency) < qmlContext->idValueCount);
+ capture->captureProperty(&qmlContext->idValues[*idObjectDependency].bindings);
+ }
+
+ Q_ASSERT(qmlContext->contextObject);
+ const quint32 *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable();
+ const int contextPropertyDependencyCount = compiledFunction->nDependingContextProperties;
+ for (int i = 0; i < contextPropertyDependencyCount; ++i) {
+ const int propertyIndex = *contextPropertyDependency++;
+ const int notifyIndex = *contextPropertyDependency++;
+ capture->captureProperty(qmlContext->contextObject, propertyIndex, notifyIndex);
+ }
+
+ QObject *scopeObject = context->qmlScope();
+ const quint32 *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable();
+ const int scopePropertyDependencyCount = compiledFunction->nDependingScopeProperties;
+ for (int i = 0; i < scopePropertyDependencyCount; ++i) {
+ const int propertyIndex = *scopePropertyDependency++;
+ const int notifyIndex = *scopePropertyDependency++;
+ capture->captureProperty(scopeObject, propertyIndex, notifyIndex);
}
+
+}
+
+
+void QQmlJavaScriptExpression::clearError()
+{
+ if (m_error)
+ delete m_error;
+ m_error = 0;
}
QQmlError QQmlJavaScriptExpression::error(QQmlEngine *engine) const
{
Q_UNUSED(engine);
- if (m_vtable.hasValue())
- return m_vtable.constValue()->error();
+ if (m_error)
+ return m_error->error();
else
return QQmlError();
}
QQmlDelayedError *QQmlJavaScriptExpression::delayedError()
{
- return &m_vtable.value();
+ if (!m_error)
+ m_error = new QQmlDelayedError;
+ return m_error;
}
QV4::ReturnedValue
QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObject,
- const QString &code, const QString &filename, quint16 line,
- QV4::PersistentValue *qmlscope)
+ const QString &code, const QString &filename, quint16 line)
{
QQmlEngine *engine = ctxt->engine;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
@@ -290,8 +365,8 @@ QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObje
QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine());
QV4::Scope scope(v4);
- QV4::ScopedObject qmlScopeObject(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, scopeObject));
- QV4::Script script(v4, qmlScopeObject, code, filename, line);
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, v4->rootContext()->newQmlContext(ctxt, scopeObject));
+ QV4::Script script(v4, qmlContext, code, filename, line);
QV4::ScopedValue result(scope);
script.parse();
if (!v4->hasException)
@@ -308,14 +383,11 @@ QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObje
ep->warning(error);
return QV4::Encode::undefined();
}
- if (qmlscope)
- qmlscope->set(v4, qmlScopeObject);
return result->asReturnedValue();
}
-QV4::ReturnedValue QQmlJavaScriptExpression::qmlBinding(QQmlContextData *ctxt, QObject *qmlScope,
- const QString &code, const QString &filename, quint16 line,
- QV4::PersistentValue *qmlscope)
+void QQmlJavaScriptExpression::createQmlBinding(QQmlContextData *ctxt, QObject *qmlScope,
+ const QString &code, const QString &filename, quint16 line)
{
QQmlEngine *engine = ctxt->engine;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
@@ -323,8 +395,8 @@ QV4::ReturnedValue QQmlJavaScriptExpression::qmlBinding(QQmlContextData *ctxt, Q
QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine());
QV4::Scope scope(v4);
- QV4::ScopedObject qmlScopeObject(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, qmlScope));
- QV4::Script script(v4, qmlScopeObject, code, filename, line);
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, v4->rootContext()->newQmlContext(ctxt, qmlScope));
+ QV4::Script script(v4, qmlContext, code, filename, line);
QV4::ScopedValue result(scope);
script.parse();
if (!v4->hasException)
@@ -339,17 +411,15 @@ QV4::ReturnedValue QQmlJavaScriptExpression::qmlBinding(QQmlContextData *ctxt, Q
error.setUrl(QUrl::fromLocalFile(filename));
error.setObject(qmlScope);
ep->warning(error);
- return QV4::Encode::undefined();
+ result = QV4::Encode::undefined();
}
- if (qmlscope)
- qmlscope->set(v4, qmlScopeObject);
- return result->asReturnedValue();
+ m_function.set(v4, result);
}
void QQmlJavaScriptExpression::clearGuards()
{
- while (Guard *g = activeGuards.takeFirst())
+ while (QQmlJavaScriptExpressionGuard *g = activeGuards.takeFirst())
g->Delete();
}
@@ -358,7 +428,7 @@ void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *e, void **)
QQmlJavaScriptExpression *expression =
static_cast<QQmlJavaScriptExpressionGuard *>(e)->expression;
- expression->m_vtable->expressionChanged(expression);
+ expression->expressionChanged();
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index 989d5a0b0d..f0a3741588 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -89,23 +89,17 @@ private:
QQmlDelayedError **prevError;
};
-class QQmlJavaScriptExpression
+class Q_QML_PRIVATE_EXPORT QQmlJavaScriptExpression
{
public:
- // Although this looks crazy, we implement our own "vtable" here, rather than relying on
- // C++ virtuals, to save memory. By doing it ourselves, we can overload the storage
- // location that is use for the vtable to also store the rarely used delayed error.
- // If we use C++ virtuals, we can't do this and it consts us an extra sizeof(void *) in
- // memory for every expression.
- struct VTable {
- QString (*expressionIdentifier)(QQmlJavaScriptExpression *);
- void (*expressionChanged)(QQmlJavaScriptExpression *);
- };
+ QQmlJavaScriptExpression();
+ virtual ~QQmlJavaScriptExpression();
- QQmlJavaScriptExpression(VTable *vtable);
+ virtual QString expressionIdentifier() = 0;
+ virtual void expressionChanged() = 0;
- QV4::ReturnedValue evaluate(QQmlContextData *, const QV4::Value &function, bool *isUndefined);
- QV4::ReturnedValue evaluate(QQmlContextData *, const QV4::Value &function, QV4::CallData *callData, bool *isUndefined);
+ QV4::ReturnedValue evaluate(bool *isUndefined);
+ QV4::ReturnedValue evaluate(QV4::CallData *callData, bool *isUndefined);
inline bool notifyOnValueChanged() const;
@@ -115,6 +109,13 @@ public:
inline QObject *scopeObject() const;
inline void setScopeObject(QObject *v);
+ bool isValid() const { return context() != 0; }
+
+ QQmlContextData *context() const { return m_context; }
+ void setContext(QQmlContextData *context);
+
+ virtual void refresh();
+
class DeleteWatcher {
public:
inline DeleteWatcher(QQmlJavaScriptExpression *);
@@ -136,46 +137,52 @@ public:
static QV4::ReturnedValue evalFunction(QQmlContextData *ctxt, QObject *scope,
const QString &code, const QString &filename,
- quint16 line,
- QV4::PersistentValue *qmlscope = 0);
- // doesn't require rewriting the expression
- static QV4::ReturnedValue qmlBinding(QQmlContextData *ctxt, QObject *scope,
- const QString &code,
- const QString &filename, quint16 line,
- QV4::PersistentValue *qmlscope = 0);
+ quint16 line);
protected:
- ~QQmlJavaScriptExpression();
+ void createQmlBinding(QQmlContextData *ctxt, QObject *scope, const QString &code, const QString &filename, quint16 line);
private:
- typedef QQmlJavaScriptExpressionGuard Guard;
+ friend class QQmlContextData;
+ friend class QQmlPropertyCapture;
friend void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *, void **);
- struct GuardCapture : public QQmlEnginePrivate::PropertyCapture {
- GuardCapture(QQmlEngine *engine, QQmlJavaScriptExpression *e, DeleteWatcher *w)
- : engine(engine), expression(e), watcher(w), errorString(0) { }
-
- ~GuardCapture() {
- Q_ASSERT(guards.isEmpty());
- Q_ASSERT(errorString == 0);
- }
-
- virtual void captureProperty(QQmlNotifier *);
- virtual void captureProperty(QObject *, int, int);
-
- QQmlEngine *engine;
- QQmlJavaScriptExpression *expression;
- DeleteWatcher *watcher;
- QFieldList<Guard, &Guard::next> guards;
- QStringList *errorString;
- };
-
- QPointerValuePair<VTable, QQmlDelayedError> m_vtable;
+ QQmlDelayedError *m_error;
// We store some flag bits in the following flag pointers.
// activeGuards:flag1 - notifyOnValueChanged
// activeGuards:flag2 - useSharedContext
QBiPointer<QObject, DeleteWatcher> m_scopeObject;
- QForwardFieldList<Guard, &Guard::next> activeGuards;
+ QForwardFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> activeGuards;
+
+ QQmlContextData *m_context;
+ QQmlJavaScriptExpression **m_prevExpression;
+ QQmlJavaScriptExpression *m_nextExpression;
+
+protected:
+ QV4::PersistentValue m_function;
+};
+
+class QQmlPropertyCapture
+{
+public:
+ QQmlPropertyCapture(QQmlEngine *engine, QQmlJavaScriptExpression *e, QQmlJavaScriptExpression::DeleteWatcher *w)
+ : engine(engine), expression(e), watcher(w), errorString(0) { }
+
+ ~QQmlPropertyCapture() {
+ Q_ASSERT(guards.isEmpty());
+ Q_ASSERT(errorString == 0);
+ }
+
+ void captureProperty(QQmlNotifier *);
+ void captureProperty(QObject *, int, int);
+
+ static void registerQmlDependencies(QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction);
+
+ QQmlEngine *engine;
+ QQmlJavaScriptExpression *expression;
+ QQmlJavaScriptExpression::DeleteWatcher *watcher;
+ QFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> guards;
+ QStringList *errorString;
};
QQmlJavaScriptExpression::DeleteWatcher::DeleteWatcher(QQmlJavaScriptExpression *e)
@@ -222,18 +229,18 @@ void QQmlJavaScriptExpression::setScopeObject(QObject *v)
bool QQmlJavaScriptExpression::hasError() const
{
- return m_vtable.hasValue() && m_vtable.constValue()->isValid();
+ return m_error && m_error->isValid();
}
bool QQmlJavaScriptExpression::hasDelayedError() const
{
- return m_vtable.hasValue();
+ return m_error;
}
QQmlJavaScriptExpressionGuard::QQmlJavaScriptExpressionGuard(QQmlJavaScriptExpression *e)
-: expression(e), next(0)
+ : QQmlNotifierEndpoint(QQmlNotifierEndpoint::QQmlJavaScriptExpressionGuard),
+ expression(e), next(0)
{
- setCallback(QQmlNotifierEndpoint::QQmlJavaScriptExpressionGuard);
}
QQmlJavaScriptExpressionGuard *
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index bcb1e72f0b..942f4f79e7 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -45,10 +45,9 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlListWrapper);
-Heap::QmlListWrapper::QmlListWrapper(ExecutionEngine *engine)
- : Heap::Object(engine)
+Heap::QmlListWrapper::QmlListWrapper()
{
- QV4::Scope scope(engine);
+ QV4::Scope scope(internalClass->engine);
QV4::ScopedObject o(scope, this);
o->setArrayType(Heap::ArrayData::Custom);
}
@@ -64,7 +63,7 @@ ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, QObject *object, i
Scope scope(engine);
- Scoped<QmlListWrapper> r(scope, engine->memoryManager->alloc<QmlListWrapper>(engine));
+ Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocObject<QmlListWrapper>());
r->d()->object = object;
r->d()->propertyType = propType;
void *args[] = { &r->d()->property, 0 };
@@ -76,7 +75,7 @@ ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, const QQmlListProp
{
Scope scope(engine);
- Scoped<QmlListWrapper> r(scope, engine->memoryManager->alloc<QmlListWrapper>(engine));
+ Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocObject<QmlListWrapper>());
r->d()->object = prop.object;
r->d()->property = prop;
r->d()->propertyType = propType;
@@ -92,13 +91,13 @@ QVariant QmlListWrapper::toVariant() const
}
-ReturnedValue QmlListWrapper::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue QmlListWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<QmlListWrapper>());
- QmlListWrapper *w = static_cast<QmlListWrapper *>(m);
+ const QmlListWrapper *w = static_cast<const QmlListWrapper *>(m);
QV4::ExecutionEngine *v4 = w->engine();
- if (name->equals(v4->id_length) && !w->d()->object.isNull()) {
+ if (name->equals(v4->id_length()) && !w->d()->object.isNull()) {
quint32 count = w->d()->property.count ? w->d()->property.count(&w->d()->property) : 0;
return Primitive::fromUInt32(count).asReturnedValue();
}
@@ -110,12 +109,12 @@ ReturnedValue QmlListWrapper::get(Managed *m, String *name, bool *hasProperty)
return Object::get(m, name, hasProperty);
}
-ReturnedValue QmlListWrapper::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue QmlListWrapper::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
Q_UNUSED(hasProperty);
Q_ASSERT(m->as<QmlListWrapper>());
- QmlListWrapper *w = static_cast<QmlListWrapper *>(m);
+ const QmlListWrapper *w = static_cast<const QmlListWrapper *>(m);
QV4::ExecutionEngine *v4 = w->engine();
quint32 count = w->d()->property.count ? w->d()->property.count(&w->d()->property) : 0;
@@ -138,9 +137,9 @@ void QmlListWrapper::put(Managed *m, String *name, const Value &value)
Q_UNUSED(value);
}
-void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
+void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{
- *name = (Heap::String *)0;
+ name->setM(0);
*index = UINT_MAX;
Q_ASSERT(m->as<QmlListWrapper>());
QmlListWrapper *w = static_cast<QmlListWrapper *>(m);
diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h
index 3590bcb1c9..6df3d83b2e 100644
--- a/src/qml/qml/qqmllistwrapper_p.h
+++ b/src/qml/qml/qqmllistwrapper_p.h
@@ -50,7 +50,7 @@
#include <QtQml/qqmllist.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
@@ -62,7 +62,7 @@ namespace QV4 {
namespace Heap {
struct QmlListWrapper : Object {
- QmlListWrapper(ExecutionEngine *engine);
+ QmlListWrapper();
~QmlListWrapper();
QPointer<QObject> object;
QQmlListProperty<QObject> property;
@@ -81,10 +81,10 @@ struct Q_QML_EXPORT QmlListWrapper : Object
QVariant toVariant() const;
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
- static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
};
}
diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp
index 62b5b76ede..af7b394a1b 100644
--- a/src/qml/qml/qqmllocale.cpp
+++ b/src/qml/qml/qqmllocale.cpp
@@ -65,13 +65,13 @@ static bool isLocaleObject(const QV4::Value &val)
void QQmlDateExtension::registerExtension(QV4::ExecutionEngine *engine)
{
- engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
- engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleTimeString"), method_toLocaleTimeString);
- engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleDateString"), method_toLocaleDateString);
- engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString);
- engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleTimeString"), method_fromLocaleTimeString);
- engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleDateString"), method_fromLocaleDateString);
- engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("timeZoneUpdated"), method_timeZoneUpdated);
+ engine->datePrototype()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
+ engine->datePrototype()->defineDefaultProperty(QStringLiteral("toLocaleTimeString"), method_toLocaleTimeString);
+ engine->datePrototype()->defineDefaultProperty(QStringLiteral("toLocaleDateString"), method_toLocaleDateString);
+ engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString);
+ engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleTimeString"), method_fromLocaleTimeString);
+ engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleDateString"), method_fromLocaleDateString);
+ engine->dateCtor()->defineDefaultProperty(QStringLiteral("timeZoneUpdated"), method_timeZoneUpdated);
}
QV4::ReturnedValue QQmlDateExtension::method_toLocaleString(QV4::CallContext *ctx)
@@ -81,7 +81,7 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleString(QV4::CallContext *ct
QV4::Scope scope(ctx);
- QV4::DateObject *date = ctx->thisObject().asDateObject();
+ QV4::DateObject *date = ctx->thisObject().as<DateObject>();
if (!date)
return QV4::DatePrototype::method_toLocaleString(ctx);
@@ -125,7 +125,7 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleTimeString(QV4::CallContext
QV4::Scope scope(ctx);
- QV4::DateObject *date = ctx->thisObject().asDateObject();
+ QV4::DateObject *date = ctx->thisObject().as<DateObject>();
if (!date)
return QV4::DatePrototype::method_toLocaleTimeString(ctx);
@@ -170,7 +170,7 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleDateString(QV4::CallContext
QV4::Scope scope(ctx);
- QV4::DateObject *dateObj = ctx->thisObject().asDateObject();
+ QV4::DateObject *dateObj = ctx->thisObject().as<DateObject>();
if (!dateObj)
return QV4::DatePrototype::method_toLocaleDateString(ctx);
@@ -347,9 +347,9 @@ QV4::ReturnedValue QQmlDateExtension::method_timeZoneUpdated(QV4::CallContext *c
void QQmlNumberExtension::registerExtension(QV4::ExecutionEngine *engine)
{
- engine->numberPrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
- engine->numberPrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleCurrencyString"), method_toLocaleCurrencyString);
- engine->numberCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString);
+ engine->numberPrototype()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
+ engine->numberPrototype()->defineDefaultProperty(QStringLiteral("toLocaleCurrencyString"), method_toLocaleCurrencyString);
+ engine->numberCtor()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString);
}
QV4::ReturnedValue QQmlNumberExtension::method_toLocaleString(QV4::CallContext *ctx)
@@ -806,7 +806,7 @@ QV4::ReturnedValue QQmlLocale::wrap(ExecutionEngine *v4, const QLocale &locale)
{
QV4::Scope scope(v4);
QV4LocaleDataDeletable *d = localeV4Data(scope.engine);
- QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->alloc<QQmlLocaleData>(v4));
+ QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->allocObject<QQmlLocaleData>());
wrapper->d()->locale = locale;
QV4::ScopedObject p(scope, d->prototype.value());
wrapper->setPrototype(p);
@@ -815,15 +815,15 @@ QV4::ReturnedValue QQmlLocale::wrap(ExecutionEngine *v4, const QLocale &locale)
void QQmlLocale::registerStringLocaleCompare(QV4::ExecutionEngine *engine)
{
- engine->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare);
+ engine->stringPrototype()->defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare);
}
QV4::ReturnedValue QQmlLocale::method_localeCompare(QV4::CallContext *ctx)
{
- if (ctx->argc() != 1 || (!ctx->args()[0].isString() && !ctx->args()[0].asStringObject()))
+ if (ctx->argc() != 1 || (!ctx->args()[0].isString() && !ctx->args()[0].as<StringObject>()))
return QV4::StringPrototype::method_localeCompare(ctx);
- if (!ctx->thisObject().isString() && !ctx->thisObject().asStringObject())
+ if (!ctx->thisObject().isString() && !ctx->thisObject().as<StringObject>())
return QV4::StringPrototype::method_localeCompare(ctx);
QString thisString = ctx->thisObject().toQStringNoThrow();
diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h
index d4436482cf..aa6b2e8681 100644
--- a/src/qml/qml/qqmllocale_p.h
+++ b/src/qml/qml/qqmllocale_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLLOCALE_H
#define QQMLLOCALE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include <QtCore/qlocale.h>
@@ -71,13 +82,9 @@ private:
};
-class Q_AUTOTEST_EXPORT QQmlLocale
+class Q_QML_PRIVATE_EXPORT QQmlLocale
{
Q_GADGET
- Q_ENUMS(MeasurementSystem)
- Q_ENUMS(FormatType)
- Q_ENUMS(CurrencySymbolFormat)
- Q_ENUMS(DayOfWeek)
public:
~QQmlLocale();
@@ -88,16 +95,19 @@ public:
ImperialUSSystem = QLocale::ImperialUSSystem,
ImperialUKSystem = QLocale::ImperialUKSystem
};
+ Q_ENUM(MeasurementSystem)
enum FormatType {
LongFormat = QLocale::LongFormat,
ShortFormat = QLocale::ShortFormat,
NarrowFormat = QLocale::NarrowFormat
};
+ Q_ENUM(FormatType)
enum CurrencySymbolFormat {
CurrencyIsoCode = QLocale::CurrencyIsoCode,
CurrencySymbol = QLocale::CurrencySymbol,
CurrencyDisplayName = QLocale::CurrencyDisplayName
};
+ Q_ENUM(CurrencySymbolFormat)
// Qt defines Sunday as 7, but JS Date assigns Sunday 0
enum DayOfWeek {
Sunday = 0,
@@ -108,6 +118,7 @@ public:
Friday = Qt::Friday,
Saturday = Qt::Saturday
};
+ Q_ENUM(DayOfWeek)
static QV4::ReturnedValue locale(QV4::ExecutionEngine *engine, const QString &localeName);
static QV4::ReturnedValue wrap(QV4::ExecutionEngine *engine, const QLocale &locale);
@@ -125,7 +136,7 @@ namespace QV4 {
namespace Heap {
struct QQmlLocaleData : Object {
- inline QQmlLocaleData(ExecutionEngine *engine);
+ inline QQmlLocaleData() {}
QLocale locale;
};
@@ -137,7 +148,7 @@ struct QQmlLocaleData : public QV4::Object
V4_NEEDS_DESTROY
static QLocale *getThisLocale(QV4::CallContext *ctx) {
- QV4::Object *o = ctx->thisObject().asObject();
+ QV4::Object *o = ctx->thisObject().as<Object>();
QQmlLocaleData *thisObject = o ? o->as<QQmlLocaleData>() : 0;
if (!thisObject) {
ctx->engine()->throwTypeError();
@@ -175,11 +186,6 @@ struct QQmlLocaleData : public QV4::Object
static QV4::ReturnedValue method_get_pmText(QV4::CallContext *ctx);
};
-Heap::QQmlLocaleData::QQmlLocaleData(ExecutionEngine *engine)
- : Heap::Object(engine)
-{
-}
-
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlmemoryprofiler.cpp b/src/qml/qml/qqmlmemoryprofiler.cpp
index cdd60e2dec..531666340b 100644
--- a/src/qml/qml/qqmlmemoryprofiler.cpp
+++ b/src/qml/qml/qqmlmemoryprofiler.cpp
@@ -63,11 +63,13 @@ static qmlmemprofile_pop_location *memprofile_pop_location;
static qmlmemprofile_save *memprofile_save;
static qmlmemprofile_is_enabled *memprofile_is_enabled;
+#ifndef QT_NO_LIBRARY
extern QFunctionPointer qt_linux_find_symbol_sys(const char *symbol);
+#endif
static bool openLibrary()
{
-#ifdef Q_OS_LINUX
+#if defined(Q_OS_LINUX) && !defined(QT_NO_LIBRARY)
if (state == Unloaded) {
memprofile_stats = (qmlmemprofile_stats *) qt_linux_find_symbol_sys("qmlmemprofile_stats");
memprofile_clear = (qmlmemprofile_clear *) qt_linux_find_symbol_sys("qmlmemprofile_clear");
diff --git a/src/qml/qml/qqmlmemoryprofiler_p.h b/src/qml/qml/qqmlmemoryprofiler_p.h
index 98977f9db5..77008bd448 100644
--- a/src/qml/qml/qqmlmemoryprofiler_p.h
+++ b/src/qml/qml/qqmlmemoryprofiler_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLMEMORYPROFILER_H
#define QQMLMEMORYPROFILER_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qtqmlglobal_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index cb8c2bd3b5..1a27a487bd 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -38,6 +38,7 @@
#include <private/qqmlcustomparser_p.h>
#include <private/qhashedstring_p.h>
#include <private/qqmlimport_p.h>
+#include <private/qqmlcompiler_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qstringlist.h>
@@ -217,12 +218,10 @@ public:
void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e)
{
QV4::ExecutionEngine *v4 = QV8Engine::getV4(e->handle());
+ v4->pushGlobalContext();
if (scriptCallback && scriptApi(e).isUndefined()) {
- v4->pushGlobalContext();
setScriptApi(e, scriptCallback(e, e));
- v4->popContext();
} else if (qobjectCallback && !qobjectApi(e)) {
- v4->pushGlobalContext();
QObject *o = qobjectCallback(e, e);
setQObjectApi(e, o);
if (!o) {
@@ -230,14 +229,12 @@ void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e)
}
// if this object can use a property cache, create it now
QQmlData::ensurePropertyCache(e, o);
- v4->popContext();
} else if (!url.isEmpty() && !qobjectApi(e)) {
- v4->pushGlobalContext();
QQmlComponent component(e, url, QQmlComponent::PreferSynchronous);
QObject *o = component.create();
setQObjectApi(e, o);
- v4->popContext();
}
+ v4->popContext();
}
void QQmlType::SingletonInstanceInfo::destroy(QQmlEngine *e)
@@ -245,7 +242,12 @@ void QQmlType::SingletonInstanceInfo::destroy(QQmlEngine *e)
// cleans up the engine-specific singleton instances if they exist.
scriptApis.remove(e);
QObject *o = qobjectApis.take(e);
- delete o;
+ if (o) {
+ QQmlData *ddata = QQmlData::get(o, false);
+ if (ddata && ddata->indestructible)
+ return;
+ delete o;
+ }
}
void QQmlType::SingletonInstanceInfo::setQObjectApi(QQmlEngine *e, QObject *o)
@@ -258,7 +260,7 @@ QObject *QQmlType::SingletonInstanceInfo::qobjectApi(QQmlEngine *e) const
return qobjectApis.value(e);
}
-void QQmlType::SingletonInstanceInfo::setScriptApi(QQmlEngine *e, QJSValue v)
+void QQmlType::SingletonInstanceInfo::setScriptApi(QQmlEngine *e, const QJSValue &v)
{
scriptApis.insert(e, v);
}
@@ -477,6 +479,29 @@ QQmlType *QQmlType::superType() const
return d->superType;
}
+QQmlType *QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
+{
+ Q_ASSERT(isComposite());
+ if (!engine)
+ return 0;
+ QQmlTypeData *td = engine->typeLoader.getType(sourceUrl());
+ if (!td || !td->isComplete())
+ return 0;
+ QQmlCompiledData *cd = td->compiledData();
+ const QMetaObject *mo = cd->rootPropertyCache->firstCppMetaObject();
+ return QQmlMetaType::qmlType(mo);
+}
+
+int QQmlType::resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const
+{
+ Q_ASSERT(isComposite());
+ *ok = false;
+ QQmlType *type = resolveCompositeBaseType(engine);
+ if (!type)
+ return -1;
+ return type->enumValue(engine, name, ok);
+}
+
static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd)
{
@@ -842,18 +867,26 @@ int QQmlType::metaObjectRevision() const
return d->revision;
}
-QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction() const
+QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction(QQmlEnginePrivate *engine) const
{
- if (d->regType != CppType)
- return 0;
- return d->extraData.cd->attachedPropertiesFunc;
+ if (d->regType == CppType)
+ return d->extraData.cd->attachedPropertiesFunc;
+
+ QQmlType *base = 0;
+ if (d->regType == CompositeType)
+ base = resolveCompositeBaseType(engine);
+ return base ? base->attachedPropertiesFunction(engine) : 0;
}
-const QMetaObject *QQmlType::attachedPropertiesType() const
+const QMetaObject *QQmlType::attachedPropertiesType(QQmlEnginePrivate *engine) const
{
- if (d->regType != CppType)
- return 0;
- return d->extraData.cd->attachedPropertiesType;
+ if (d->regType == CppType)
+ return d->extraData.cd->attachedPropertiesType;
+
+ QQmlType *base = 0;
+ if (d->regType == CompositeType)
+ base = resolveCompositeBaseType(engine);
+ return base ? base->attachedPropertiesType(engine) : 0;
}
/*
@@ -861,11 +894,15 @@ This is the id passed to qmlAttachedPropertiesById(). This is different from th
for the case that a single class is registered under two or more names (eg. Item in
Qt 4.7 and QtQuick 1.0).
*/
-int QQmlType::attachedPropertiesId() const
+int QQmlType::attachedPropertiesId(QQmlEnginePrivate *engine) const
{
- if (d->regType != CppType)
- return 0;
- return d->extraData.cd->attachedPropertiesId;
+ if (d->regType == CppType)
+ return d->extraData.cd->attachedPropertiesId;
+
+ QQmlType *base = 0;
+ if (d->regType == CompositeType)
+ base = resolveCompositeBaseType(engine);
+ return base ? base->attachedPropertiesId(engine) : 0;
}
int QQmlType::parserStatusCast() const
@@ -911,9 +948,11 @@ QUrl QQmlType::sourceUrl() const
return QUrl();
}
-int QQmlType::enumValue(const QHashedStringRef &name, bool *ok) const
+int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name, bool *ok) const
{
Q_ASSERT(ok);
+ if (isComposite())
+ return resolveCompositeEnumValue(engine, name.toString(), ok);
*ok = true;
d->initEnums();
@@ -926,9 +965,11 @@ int QQmlType::enumValue(const QHashedStringRef &name, bool *ok) const
return -1;
}
-int QQmlType::enumValue(const QHashedCStringRef &name, bool *ok) const
+int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name, bool *ok) const
{
Q_ASSERT(ok);
+ if (isComposite())
+ return resolveCompositeEnumValue(engine, name.toUtf16(), ok);
*ok = true;
d->initEnums();
@@ -941,9 +982,11 @@ int QQmlType::enumValue(const QHashedCStringRef &name, bool *ok) const
return -1;
}
-int QQmlType::enumValue(const QV4::String *name, bool *ok) const
+int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const
{
Q_ASSERT(ok);
+ if (isComposite())
+ return resolveCompositeEnumValue(engine, name->toQString(), ok);
*ok = true;
d->initEnums();
@@ -1110,7 +1153,9 @@ void qmlClearTypeRegistrations() // Declared in qqml.h
data->uriToModule.clear();
QQmlEnginePrivate::baseModulesUninitialized = true; //So the engine re-registers its types
+#ifndef QT_NO_LIBRARY
qmlClearEnginePlugins();
+#endif
}
int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent)
@@ -1440,8 +1485,8 @@ bool QQmlMetaType::isAnyModule(const QString &uri)
QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
- for (QQmlMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin();
- iter != data->uriToModule.end(); ++iter) {
+ for (QQmlMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.cbegin();
+ iter != data->uriToModule.cend(); ++iter) {
if ((*iter)->module() == uri)
return true;
}
@@ -1538,25 +1583,25 @@ int QQmlMetaType::listType(int id)
return 0;
}
-int QQmlMetaType::attachedPropertiesFuncId(const QMetaObject *mo)
+int QQmlMetaType::attachedPropertiesFuncId(QQmlEnginePrivate *engine, const QMetaObject *mo)
{
QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QQmlType *type = data->metaObjectToType.value(mo);
- if (type && type->attachedPropertiesFunction())
- return type->attachedPropertiesId();
+ if (type && type->attachedPropertiesFunction(engine))
+ return type->attachedPropertiesId(engine);
else
return -1;
}
-QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFuncById(int id)
+QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFuncById(QQmlEnginePrivate *engine, int id)
{
if (id < 0)
return 0;
QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
- return data->types.at(id)->attachedPropertiesFunction();
+ return data->types.at(id)->attachedPropertiesFunction(engine);
}
QMetaProperty QQmlMetaType::defaultProperty(const QMetaObject *metaObject)
@@ -1718,7 +1763,7 @@ QQmlType *QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStrin
QQmlMetaTypeData *data = metaTypeData();
QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.constFind(name);
- while (it != data->nameToType.end() && it.key() == name) {
+ while (it != data->nameToType.cend() && it.key() == name) {
// XXX version_major<0 just a kludge for QQmlPropertyPrivate::initProperty
if (version_major < 0 || module.isEmpty() || (*it)->availableInVersion(module, version_major,version_minor))
return (*it);
@@ -1752,7 +1797,7 @@ QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStri
QQmlMetaTypeData *data = metaTypeData();
QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.constFind(metaObject);
- while (it != data->metaObjectToType.end() && it.key() == metaObject) {
+ while (it != data->metaObjectToType.cend() && it.key() == metaObject) {
QQmlType *t = *it;
if (version_major < 0 || module.isEmpty() || t->availableInVersion(module, version_major,version_minor))
return t;
@@ -1823,8 +1868,9 @@ QList<QString> QQmlMetaType::qmlTypeNames()
QQmlMetaTypeData *data = metaTypeData();
QList<QString> names;
- QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.begin();
- while (it != data->nameToType.end()) {
+ names.reserve(data->nameToType.count());
+ QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.cbegin();
+ while (it != data->nameToType.cend()) {
names += (*it)->qmlTypeName();
++it;
}
@@ -1885,4 +1931,43 @@ const QQmlPrivate::CachedQmlUnit *QQmlMetaType::findCachedCompilationUnit(const
return 0;
}
+/*!
+ Returns the pretty QML type name (e.g. 'Item' instead of 'QtQuickItem') for the given object.
+ */
+QString QQmlMetaType::prettyTypeName(const QObject *object)
+{
+ QString typeName;
+
+ if (!object)
+ return typeName;
+
+ const QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
+ if (type) {
+ typeName = type->qmlTypeName();
+ const int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
+ if (lastSlash != -1)
+ typeName = typeName.mid(lastSlash + 1);
+ } else {
+ typeName = QString::fromUtf8(object->metaObject()->className());
+ int marker = typeName.indexOf(QLatin1String("_QMLTYPE_"));
+ if (marker != -1)
+ typeName = typeName.left(marker);
+
+ marker = typeName.indexOf(QLatin1String("_QML_"));
+ if (marker != -1) {
+ typeName = typeName.left(marker);
+ typeName += QLatin1Char('*');
+ type = QQmlMetaType::qmlType(QMetaType::type(typeName.toLatin1()));
+ if (type) {
+ typeName = type->qmlTypeName();
+ const int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
+ if (lastSlash != -1)
+ typeName = typeName.mid(lastSlash + 1);
+ }
+ }
+ }
+
+ return typeName;
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index e5ac20d314..c120941a03 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -57,6 +57,7 @@ QT_BEGIN_NAMESPACE
class QQmlType;
class QQmlEngine;
+class QQmlEnginePrivate;
class QQmlCustomParser;
class QQmlTypePrivate;
class QQmlTypeModule;
@@ -91,8 +92,8 @@ public:
static QObject *toQObject(const QVariant &, bool *ok = 0);
static int listType(int);
- static int attachedPropertiesFuncId(const QMetaObject *);
- static QQmlAttachedPropertiesFunc attachedPropertiesFuncById(int);
+ static int attachedPropertiesFuncId(QQmlEnginePrivate *engine, const QMetaObject *);
+ static QQmlAttachedPropertiesFunc attachedPropertiesFuncById(QQmlEnginePrivate *, int);
enum TypeCategory { Unknown, Object, List };
static TypeCategory typeCategory(int);
@@ -122,6 +123,8 @@ public:
static QStringList typeRegistrationFailures();
static QMutex *typeRegistrationLock();
+
+ static QString prettyTypeName(const QObject *object);
};
struct QQmlMetaTypeData;
@@ -166,9 +169,9 @@ public:
int metaObjectRevision() const;
bool containsRevisionedAttributes() const;
- QQmlAttachedPropertiesFunc attachedPropertiesFunction() const;
- const QMetaObject *attachedPropertiesType() const;
- int attachedPropertiesId() const;
+ QQmlAttachedPropertiesFunc attachedPropertiesFunction(QQmlEnginePrivate *engine) const;
+ const QMetaObject *attachedPropertiesType(QQmlEnginePrivate *engine) const;
+ int attachedPropertiesId(QQmlEnginePrivate *engine) const;
int parserStatusCast() const;
const char *interfaceIId() const;
@@ -191,7 +194,7 @@ public:
void setQObjectApi(QQmlEngine *, QObject *);
QObject *qobjectApi(QQmlEngine *) const;
- void setScriptApi(QQmlEngine *, QJSValue);
+ void setScriptApi(QQmlEngine *, const QJSValue &);
QJSValue scriptApi(QQmlEngine *) const;
void init(QQmlEngine *);
@@ -204,11 +207,13 @@ public:
QUrl sourceUrl() const;
- int enumValue(const QHashedStringRef &, bool *ok) const;
- int enumValue(const QHashedCStringRef &, bool *ok) const;
- int enumValue(const QV4::String *, bool *ok) const;
+ int enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &, bool *ok) const;
+ int enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &, bool *ok) const;
+ int enumValue(QQmlEnginePrivate *engine, const QV4::String *, bool *ok) const;
private:
QQmlType *superType() const;
+ QQmlType *resolveCompositeBaseType(QQmlEnginePrivate *engine) const;
+ int resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const;
friend class QQmlTypePrivate;
friend struct QQmlMetaTypeData;
diff --git a/src/qml/qml/qqmlnotifier_p.h b/src/qml/qml/qqmlnotifier_p.h
index 2742bfc84b..ac0aab892f 100644
--- a/src/qml/qml/qqmlnotifier_p.h
+++ b/src/qml/qml/qqmlnotifier_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLNOTIFIER_P_H
#define QQMLNOTIFIER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qqmldata_p.h"
#include <QtCore/qmetaobject.h>
#include <private/qmetaobject_p.h>
@@ -63,9 +74,6 @@ class QQmlNotifierEndpoint
QQmlNotifierEndpoint *next;
QQmlNotifierEndpoint **prev;
public:
- inline QQmlNotifierEndpoint();
- inline ~QQmlNotifierEndpoint();
-
// QQmlNotifierEndpoint can only invoke one of a set of pre-defined callbacks.
// To add another callback, extend this enum and add the callback to the top
// of qqmlnotifier.cpp. Four bits are reserved for the callback, so there can
@@ -77,7 +85,8 @@ public:
QQmlVMEMetaObjectEndpoint = 3
};
- inline void setCallback(Callback c) { callback = c; }
+ inline QQmlNotifierEndpoint(Callback callback);
+ inline ~QQmlNotifierEndpoint();
inline bool isConnected();
inline bool isConnected(QObject *source, int sourceSignal);
@@ -90,6 +99,8 @@ public:
inline bool isNotifying() const;
inline void cancelNotify();
+ inline int signalIndex() const { return sourceSignal; }
+
private:
friend class QQmlData;
friend class QQmlNotifier;
@@ -135,8 +146,8 @@ void QQmlNotifier::notify()
if (endpoints) emitNotify(endpoints, args);
}
-QQmlNotifierEndpoint::QQmlNotifierEndpoint()
-: next(0), prev(0), senderPtr(0), callback(None), sourceSignal(-1)
+QQmlNotifierEndpoint::QQmlNotifierEndpoint(Callback callback)
+: next(0), prev(0), senderPtr(0), callback(callback), sourceSignal(-1)
{
}
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 3c2f3690b9..21e6d5f6de 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -62,14 +62,6 @@ struct ActiveOCRestorer
};
}
-static void removeBindingOnProperty(QObject *o, int index)
-{
- int coreIndex;
- int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex);
- QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(o, coreIndex, valueTypeIndex, 0);
- if (binding) binding->destroy();
-}
-
QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlContextData *creationContext, void *activeVMEDataForRootContext)
: phase(Startup)
, compiledData(compiledData)
@@ -128,7 +120,7 @@ void QQmlObjectCreator::init(QQmlContextData *providedParentContext)
_ddata = 0;
_propertyCache = 0;
_vmeMetaObject = 0;
- _qmlBindingWrapper = 0;
+ _qmlContext = 0;
}
QQmlObjectCreator::~QQmlObjectCreator()
@@ -137,11 +129,6 @@ QQmlObjectCreator::~QQmlObjectCreator()
{
QQmlObjectCreatorRecursionWatcher watcher(this);
}
- for (int i = 0; i < sharedState->allCreatedBindings.count(); ++i) {
- QQmlAbstractBinding *b = sharedState->allCreatedBindings.at(i);
- if (b)
- b->m_mePtr = 0;
- }
for (int i = 0; i < sharedState->allParserStatusCallbacks.count(); ++i) {
QQmlParserStatus *ps = sharedState->allParserStatusCallbacks.at(i);
if (ps)
@@ -198,9 +185,10 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
if (subComponentIndex == -1 && compiledData->scripts.count()) {
QV4::ScopedObject scripts(scope, v4->newArrayObject(compiledData->scripts.count()));
context->importedScripts.set(v4, scripts);
+ QV4::ScopedValue v(scope);
for (int i = 0; i < compiledData->scripts.count(); ++i) {
QQmlScriptData *s = compiledData->scripts.at(i);
- scripts->putIndexed(i, *s->scriptValueForContext(context).valueRef());
+ scripts->putIndexed(i, (v = s->scriptValueForContext(context)));
}
} else if (sharedState->creationContext) {
context->importedScripts = sharedState->creationContext->importedScripts;
@@ -249,9 +237,9 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
Q_ASSERT(!sharedState->allJavaScriptObjects);
sharedState->allJavaScriptObjects = valueScope.alloc(compiledData->totalObjectCount);
- QV4::Value *qmlBindingWrapper = valueScope.alloc(1);
+ QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc(1));
- qSwap(_qmlBindingWrapper, qmlBindingWrapper);
+ qSwap(_qmlContext, qmlContext);
qSwap(_propertyCache, cache);
qSwap(_qobject, instance);
@@ -280,7 +268,7 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
qSwap(_qobject, instance);
qSwap(_propertyCache, cache);
- qSwap(_qmlBindingWrapper, qmlBindingWrapper);
+ qSwap(_qmlContext, qmlContext);
qSwap(_scopeObject, scopeObject);
phase = ObjectsCreated;
@@ -660,15 +648,12 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
// ### this is best done through type-compile-time binding skip lists.
if (_valueTypeProperty) {
- QQmlAbstractBinding *binding =
- QQmlPropertyPrivate::binding(_bindingTarget, _valueTypeProperty->coreIndex, -1);
+ QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(_bindingTarget, _valueTypeProperty->coreIndex);
- if (binding && binding->bindingType() != QQmlAbstractBinding::ValueTypeProxy) {
- QQmlPropertyPrivate::setBinding(_bindingTarget, _valueTypeProperty->coreIndex, -1, 0);
- binding->destroy();
+ if (binding && !binding->isValueTypeProxy()) {
+ QQmlPropertyPrivate::removeBinding(_bindingTarget, _valueTypeProperty->coreIndex);
} else if (binding) {
- QQmlValueTypeProxyBinding *proxy =
- static_cast<QQmlValueTypeProxyBinding *>(binding);
+ QQmlValueTypeProxyBinding *proxy = static_cast<QQmlValueTypeProxyBinding *>(binding);
if (qmlTypeForObject(_bindingTarget)) {
quint32 bindingSkipList = 0;
@@ -721,7 +706,12 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
QQmlCompiledData::TypeReference *tr = resolvedTypes.value(binding->propertyNameIndex);
Q_ASSERT(tr);
QQmlType *attachedType = tr->type;
- const int id = attachedType->attachedPropertiesId();
+ if (!attachedType) {
+ QQmlTypeNameCache::Result res = context->imports->query(stringAt(binding->propertyNameIndex));
+ if (res.isValid())
+ attachedType = res.type;
+ }
+ const int id = attachedType->attachedPropertiesId(QQmlEnginePrivate::get(engine));
QObject *qmlObject = qmlAttachedPropertiesObjectById(id, _qobject);
if (!populateInstance(binding->value.objectIndex, qmlObject, qmlObject, /*value type property*/0))
return false;
@@ -731,7 +721,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
// ### resolve this at compile time
if (property && property->propType == qMetaTypeId<QQmlScriptString>()) {
QQmlScriptString ss(binding->valueAsScriptString(qmlUnit), context->asQQmlContext(), _scopeObject);
- ss.d.data()->bindingId = binding->type == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : QQmlBinding::Invalid;
+ ss.d.data()->bindingId = binding->type == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : (quint32)QQmlBinding::Invalid;
ss.d.data()->lineNumber = binding->location.line;
ss.d.data()->columnNumber = binding->location.column;
ss.d.data()->isStringLiteral = binding->type == QV4::CompiledData::Binding::Type_String;
@@ -800,7 +790,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
if (_ddata->hasBindingBit(property->coreIndex) && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
&& !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment)
&& !_valueTypeProperty)
- removeBindingOnProperty(_bindingTarget, property->coreIndex);
+ QQmlPropertyPrivate::removeBinding(_bindingTarget, property->coreIndex);
if (binding->type == QV4::CompiledData::Binding::Type_Script) {
QV4::Function *runtimeFunction = compiledData->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
@@ -828,18 +818,12 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
if (_valueTypeProperty)
targetCorePropertyData = QQmlPropertyPrivate::saveValueType(*_valueTypeProperty, _qobject->metaObject(), property->coreIndex, engine);
- sharedState->allCreatedBindings.push(qmlBinding);
- qmlBinding->m_mePtr = &sharedState->allCreatedBindings.top();
+ sharedState->allCreatedBindings.push(QQmlAbstractBinding::Ptr(qmlBinding));
- qmlBinding->setTarget(_bindingTarget, targetCorePropertyData, context);
+ qmlBinding->setTarget(_bindingTarget, targetCorePropertyData);
if (targetCorePropertyData.isAlias()) {
- QQmlAbstractBinding *old =
- QQmlPropertyPrivate::setBindingNoEnable(_bindingTarget,
- targetCorePropertyData.coreIndex,
- targetCorePropertyData.getValueTypeCoreIndex(),
- qmlBinding);
- if (old) { old->destroy(); }
+ QQmlPropertyPrivate::setBinding(qmlBinding, QQmlPropertyPrivate::DontEnable);
} else {
qmlBinding->addToObject();
@@ -875,11 +859,24 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
QQmlPropertyValueInterceptor *vi = reinterpret_cast<QQmlPropertyValueInterceptor *>(reinterpret_cast<char *>(createdSubObject) + valueInterceptorCast);
QObject *target = createdSubObject->parent();
+ if (targetCorePropertyData.isAlias()) {
+ int propIndex;
+ QQmlPropertyPrivate::findAliasTarget(target, targetCorePropertyData.coreIndex, &target, &propIndex);
+ QQmlData *data = QQmlData::get(target);
+ if (!data || !data->propertyCache) {
+ qWarning() << "can't resolve property alias for 'on' assignment";
+ return false;
+ }
+ targetCorePropertyData = *data->propertyCache->property(propIndex);
+ }
+
QQmlProperty prop =
QQmlPropertyPrivate::restore(target, targetCorePropertyData, context);
+
vi->setTarget(prop);
- QQmlVMEMetaObject *mo = QQmlVMEMetaObject::get(target);
- Q_ASSERT(mo);
+ QQmlInterceptorMetaObject *mo = QQmlInterceptorMetaObject::get(target);
+ if (!mo)
+ mo = new QQmlInterceptorMetaObject(target, QQmlData::get(target)->propertyCache);
mo->registerInterceptor(prop.index(), QQmlPropertyPrivate::valueTypeCoreIndex(prop), vi);
return true;
}
@@ -1007,15 +1004,12 @@ void QQmlObjectCreator::registerObjectWithContextById(int objectIndex, QObject *
context->setIdProperty(idEntry.value(), instance);
}
-QV4::Heap::ExecutionContext *QQmlObjectCreator::currentQmlContext()
+QV4::Heap::QmlContext *QQmlObjectCreator::currentQmlContext()
{
- if (!_qmlBindingWrapper->objectValue()) {
- QV4::Scope valueScope(v4);
- QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(v4, context, _scopeObject));
- QV4::ScopedContext global(valueScope, v4->rootContext());
- *_qmlBindingWrapper = v4->memoryManager->alloc<QV4::QmlBindingWrapper>(global, qmlScope);
- }
- return static_cast<QV4::QmlBindingWrapper*>(_qmlBindingWrapper->objectValue())->context();
+ if (!_qmlContext->objectValue())
+ _qmlContext->setM(v4->rootContext()->newQmlContext(context, _scopeObject));
+
+ return _qmlContext->d();
}
QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject)
@@ -1124,8 +1118,9 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
QBitArray bindingsToSkip;
if (customParser) {
- QHash<int, QBitArray>::ConstIterator customParserBindings = compiledData->customParserBindings.find(index);
+ QHash<int, QBitArray>::ConstIterator customParserBindings = compiledData->customParserBindings.constFind(index);
if (customParserBindings != compiledData->customParserBindings.constEnd()) {
+ customParser->engine = QQmlEnginePrivate::get(engine);
customParser->imports = compiledData->importCache;
QList<const QV4::CompiledData::Binding *> bindings;
@@ -1135,6 +1130,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
bindings << obj->bindingTable() + i;
customParser->applyBindings(instance, compiledData, bindings);
+ customParser->engine = 0;
customParser->imports = (QQmlTypeNameCache*)0;
bindingsToSkip = *customParserBindings;
}
@@ -1162,13 +1158,13 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
++sharedState->allJavaScriptObjects;
QV4::Scope valueScope(v4);
- QV4::Value *qmlBindingWrapper = valueScope.alloc(1);
+ QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc(1));
- qSwap(_qmlBindingWrapper, qmlBindingWrapper);
+ qSwap(_qmlContext, qmlContext);
bool result = populateInstance(index, instance, /*binding target*/instance, /*value type property*/0, bindingsToSkip);
- qSwap(_qmlBindingWrapper, qmlBindingWrapper);
+ qSwap(_qmlContext, qmlContext);
qSwap(_scopeObject, scopeObject);
return result ? instance : 0;
@@ -1183,13 +1179,14 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine));
while (!sharedState->allCreatedBindings.isEmpty()) {
- QQmlAbstractBinding *b = sharedState->allCreatedBindings.pop();
- if (!b)
+ QQmlAbstractBinding::Ptr b = sharedState->allCreatedBindings.pop();
+ Q_ASSERT(b);
+ // skip, if b is not added to an object
+ if (!b->isAddedToObject())
continue;
- b->m_mePtr = 0;
- QQmlData *data = QQmlData::get(b->object());
+ QQmlData *data = QQmlData::get(b->targetObject());
Q_ASSERT(data);
- data->clearPendingBindingBit(b->propertyIndex());
+ data->clearPendingBindingBit(b->targetPropertyIndex());
b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
QQmlPropertyPrivate::DontRemoveBinding);
@@ -1299,7 +1296,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
QBitArray bindingSkipList = bindingsToSkip;
{
- QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.find(_compiledObjectIndex);
+ QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.constFind(_compiledObjectIndex);
if (deferredBindings != compiledData->deferredBindingsPerObject.constEnd()) {
if (bindingSkipList.isEmpty())
bindingSkipList.resize(deferredBindings->count());
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 60fefe494f..620ae75f53 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -33,6 +33,17 @@
#ifndef QQMLOBJECTCREATOR_P_H
#define QQMLOBJECTCREATOR_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qqmlimport_p.h>
#include <private/qqmltypenamecache_p.h>
#include <private/qv4compileddata_p.h>
@@ -55,7 +66,7 @@ struct QQmlObjectCreatorSharedState : public QSharedData
{
QQmlContextData *rootContext;
QQmlContextData *creationContext;
- QFiniteStack<QQmlAbstractBinding*> allCreatedBindings;
+ QFiniteStack<QQmlAbstractBinding::Ptr> allCreatedBindings;
QFiniteStack<QQmlParserStatus*> allParserStatusCallbacks;
QFiniteStack<QPointer<QObject> > allCreatedObjects;
QV4::Value *allJavaScriptObjects; // pointer to vector on JS stack to reference JS wrappers during creation phase.
@@ -107,7 +118,7 @@ private:
void registerObjectWithContextById(int objectIndex, QObject *instance) const;
- QV4::Heap::ExecutionContext *currentQmlContext();
+ QV4::Heap::QmlContext *currentQmlContext();
enum Phase {
Startup,
@@ -143,7 +154,7 @@ private:
QQmlRefPointer<QQmlPropertyCache> _propertyCache;
QQmlVMEMetaObject *_vmeMetaObject;
QQmlListProperty<void> _currentList;
- QV4::Value *_qmlBindingWrapper;
+ QV4::QmlContext *_qmlContext;
friend struct QQmlObjectCreatorRecursionWatcher;
};
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp
index fc24b15fd2..9188ba6174 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -35,6 +35,7 @@
#include <private/qqmlpropertycache_p.h>
#include <private/qqmldata_p.h>
#include <private/qmetaobjectbuilder_p.h>
+#include <private/qv8engine_p.h>
#include <qqmlengine.h>
#include <qdebug.h>
@@ -106,6 +107,28 @@ QMetaObject *QQmlOpenMetaObjectType::metaObject() const
return d->mem;
}
+void QQmlOpenMetaObjectType::createProperties(const QVector<QByteArray> &names)
+{
+ for (int i = 0; i < names.count(); ++i) {
+ const QByteArray &name = names.at(i);
+ const int id = d->mob.propertyCount();
+ d->mob.addSignal("__" + QByteArray::number(id) + "()");
+ QMetaPropertyBuilder build = d->mob.addProperty(name, "QVariant", id);
+ propertyCreated(id, build);
+ d->names.insert(name, id);
+ }
+ free(d->mem);
+ d->mem = d->mob.toMetaObject();
+ QSet<QQmlOpenMetaObject*>::iterator it = d->referers.begin();
+ while (it != d->referers.end()) {
+ QQmlOpenMetaObject *omo = *it;
+ *static_cast<QMetaObject *>(omo) = *d->mem;
+ if (d->cache)
+ d->cache->update(omo);
+ ++it;
+ }
+}
+
int QQmlOpenMetaObjectType::createProperty(const QByteArray &name)
{
int id = d->mob.propertyCount();
@@ -230,8 +253,18 @@ QQmlOpenMetaObjectType *QQmlOpenMetaObject::type() const
return d->type;
}
-int QQmlOpenMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
+void QQmlOpenMetaObject::emitPropertyNotification(const QByteArray &propertyName)
{
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(propertyName);
+ if (iter == d->type->d->names.constEnd())
+ return;
+ activate(d->object, *iter + d->type->d->signalOffset, 0);
+}
+
+int QQmlOpenMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void **a)
+{
+ Q_ASSERT(d->object == o);
+
if (( c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty)
&& id >= d->type->d->propertyOffset) {
int propId = id - d->type->d->propertyOffset;
@@ -245,15 +278,15 @@ int QQmlOpenMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
prop.first = propertyWriteValue(propId, *reinterpret_cast<QVariant *>(a[0]));
prop.second = true;
propertyWritten(propId);
- activate(d->object, d->type->d->signalOffset + propId, 0);
+ activate(o, d->type->d->signalOffset + propId, 0);
}
}
return -1;
} else {
if (d->parent)
- return d->parent->metaCall(c, id, a);
+ return d->parent->metaCall(o, c, id, a);
else
- return d->object->qt_metacall(c, id, a);
+ return o->qt_metacall(c, id, a);
}
}
@@ -277,8 +310,8 @@ void QQmlOpenMetaObject::setValue(int id, const QVariant &value)
QVariant QQmlOpenMetaObject::value(const QByteArray &name) const
{
- QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
- if (iter == d->type->d->names.end())
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(name);
+ if (iter == d->type->d->names.cend())
return QVariant();
return d->getData(*iter);
@@ -286,8 +319,8 @@ QVariant QQmlOpenMetaObject::value(const QByteArray &name) const
QVariant &QQmlOpenMetaObject::operator[](const QByteArray &name)
{
- QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
- Q_ASSERT(iter != d->type->d->names.end());
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(name);
+ Q_ASSERT(iter != d->type->d->names.cend());
return d->getData(*iter);
}
@@ -299,10 +332,10 @@ QVariant &QQmlOpenMetaObject::operator[](int id)
bool QQmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val)
{
- QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(name);
int id = -1;
- if (iter == d->type->d->names.end()) {
+ if (iter == d->type->d->names.cend()) {
id = createProperty(name.constData(), "") - d->type->d->propertyOffset;
} else {
id = *iter;
@@ -337,7 +370,7 @@ void QQmlOpenMetaObject::setCached(bool c)
QQmlData *qmldata = QQmlData::get(d->object, true);
if (d->cacheProperties) {
if (!d->type->d->cache)
- d->type->d->cache = new QQmlPropertyCache(d->type->d->engine, this);
+ d->type->d->cache = new QQmlPropertyCache(QV8Engine::getV4(d->type->d->engine), this);
qmldata->propertyCache = d->type->d->cache;
d->type->d->cache->addref();
} else {
diff --git a/src/qml/qml/qqmlopenmetaobject_p.h b/src/qml/qml/qqmlopenmetaobject_p.h
index 6a29d08d4e..9728220b5a 100644
--- a/src/qml/qml/qqmlopenmetaobject_p.h
+++ b/src/qml/qml/qqmlopenmetaobject_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLOPENMETAOBJECT_H
#define QQMLOPENMETAOBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/QMetaObject>
#include <QtCore/QObject>
@@ -54,6 +65,7 @@ public:
QQmlOpenMetaObjectType(const QMetaObject *base, QQmlEngine *engine);
~QQmlOpenMetaObjectType();
+ void createProperties(const QVector<QByteArray> &names);
int createProperty(const QByteArray &name);
int propertyOffset() const;
@@ -101,8 +113,10 @@ public:
QQmlOpenMetaObjectType *type() const;
+ void emitPropertyNotification(const QByteArray &propertyName);
+
protected:
- virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+ virtual int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a);
virtual int createProperty(const char *, const char *);
virtual void propertyRead(int);
diff --git a/src/qml/qml/qqmlplatform_p.h b/src/qml/qml/qqmlplatform_p.h
index 363341c89e..c1a481a439 100644
--- a/src/qml/qml/qqmlplatform_p.h
+++ b/src/qml/qml/qqmlplatform_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLPLATFORM_P_H
#define QQMLPLATFORM_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/QObject>
#include <qqml.h>
#include <private/qtqmlglobal_p.h>
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 800f650075..1b78ada698 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -50,11 +50,13 @@
#include "qqmlvaluetypeproxybinding_p.h"
#include <private/qjsvalue_p.h>
#include <private/qv4functionobject_p.h>
+#include <private/qv4runtime_p.h>
#include <QStringList>
#include <private/qmetaobject_p.h>
#include <private/qqmlvaluetypewrapper_p.h>
#include <QtCore/qdebug.h>
+#include <cmath>
Q_DECLARE_METATYPE(QList<int>)
Q_DECLARE_METATYPE(QList<qreal>)
@@ -246,10 +248,11 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
QQmlTypeNameCache::Result r = typeNameCache->query(pathName);
if (r.isValid()) {
if (r.type) {
- QQmlAttachedPropertiesFunc func = r.type->attachedPropertiesFunction();
+ QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
+ QQmlAttachedPropertiesFunc func = r.type->attachedPropertiesFunction(enginePrivate);
if (!func) return; // Not an attachable type
- currentObject = qmlAttachedPropertiesObjectById(r.type->attachedPropertiesId(), currentObject);
+ currentObject = qmlAttachedPropertiesObjectById(r.type->attachedPropertiesId(enginePrivate), currentObject);
if (!currentObject) return; // Something is broken with the attachable type
} else if (r.importNamespace) {
if ((ii + 1) == path.count()) return; // No type following the namespace
@@ -257,10 +260,11 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
++ii; r = typeNameCache->query(path.at(ii), r.importNamespace);
if (!r.type) return; // Invalid type in namespace
- QQmlAttachedPropertiesFunc func = r.type->attachedPropertiesFunction();
+ QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
+ QQmlAttachedPropertiesFunc func = r.type->attachedPropertiesFunction(enginePrivate);
if (!func) return; // Not an attachable type
- currentObject = qmlAttachedPropertiesObjectById(r.type->attachedPropertiesId(), currentObject);
+ currentObject = qmlAttachedPropertiesObjectById(r.type->attachedPropertiesId(enginePrivate), currentObject);
if (!currentObject) return; // Something is broken with the attachable type
} else if (r.scriptIndex != -1) {
@@ -699,8 +703,7 @@ QQmlPropertyPrivate::binding(const QQmlProperty &that)
if (!that.d || !that.isProperty() || !that.d->object)
return 0;
- return binding(that.d->object, that.d->core.coreIndex,
- that.d->core.getValueTypeCoreIndex());
+ return binding(that.d->object, that.d->core.encodedIndex());
}
/*!
@@ -716,65 +719,96 @@ QQmlPropertyPrivate::binding(const QQmlProperty &that)
\a flags is passed through to the binding and is used for the initial update (when
the binding sets the initial value, it will use these flags for the write).
*/
-QQmlAbstractBinding *
-QQmlPropertyPrivate::setBinding(const QQmlProperty &that,
- QQmlAbstractBinding *newBinding,
- WriteFlags flags)
+void
+QQmlPropertyPrivate::setBinding(const QQmlProperty &that, QQmlAbstractBinding *newBinding)
{
+ if (!newBinding) {
+ removeBinding(that);
+ return;
+ }
+
if (!that.d || !that.isProperty() || !that.d->object) {
- if (newBinding)
- newBinding->destroy();
- return 0;
+ if (!newBinding->ref)
+ delete newBinding;
+ return;
}
+ setBinding(newBinding);
+}
+
+static void removeOldBinding(QObject *object, int index, QQmlPropertyPrivate::BindingFlags flags = QQmlPropertyPrivate::None)
+{
+ int coreIndex;
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex);
- if (newBinding) {
- // In the case that the new binding is provided, we must target the property it
- // is associated with. If we don't do this, retargetBinding() can fail.
- QObject *object = newBinding->object();
- int pi = newBinding->propertyIndex();
+ QQmlData *data = QQmlData::get(object, false);
- int core;
- int vt = QQmlPropertyData::decodeValueTypePropertyIndex(pi, &core);
+ if (!data || !data->hasBindingBit(coreIndex))
+ return;
- return setBinding(object, core, vt, newBinding, flags);
- } else {
- return setBinding(that.d->object, that.d->core.coreIndex,
- that.d->core.getValueTypeCoreIndex(),
- newBinding, flags);
- }
+ QQmlAbstractBinding::Ptr oldBinding;
+ oldBinding = data->bindings;
+
+ while (oldBinding && oldBinding->targetPropertyIndex() != coreIndex)
+ oldBinding = oldBinding->nextBinding();
+
+ if (!oldBinding)
+ return;
+
+ if (valueTypeIndex != -1 && oldBinding->isValueTypeProxy())
+ oldBinding = static_cast<QQmlValueTypeProxyBinding *>(oldBinding.data())->binding(index);
+
+ if (!oldBinding)
+ return;
+
+ if (!(flags & QQmlPropertyPrivate::DontEnable))
+ oldBinding->setEnabled(false, 0);
+ oldBinding->removeFromObject();
+}
+
+void QQmlPropertyPrivate::removeBinding(QQmlAbstractBinding *b)
+{
+ removeBinding(b->targetObject(), b->targetPropertyIndex());
+}
+
+void QQmlPropertyPrivate::removeBinding(QObject *o, int index)
+{
+ Q_ASSERT(o);
+
+ QObject *target;
+ int targetIndex;
+ findAliasTarget(o, index, &target, &targetIndex);
+ removeOldBinding(target, targetIndex);
+}
+
+void QQmlPropertyPrivate::removeBinding(const QQmlProperty &that)
+{
+ if (!that.d || !that.isProperty() || !that.d->object)
+ return;
+
+ removeBinding(that.d->object, that.d->core.encodedIndex());
}
QQmlAbstractBinding *
-QQmlPropertyPrivate::binding(QObject *object, int coreIndex, int valueTypeIndex)
+QQmlPropertyPrivate::binding(QObject *object, int index)
{
QQmlData *data = QQmlData::get(object);
if (!data)
return 0;
- QQmlPropertyData *propertyData =
- data->propertyCache?data->propertyCache->property(coreIndex):0;
- if (propertyData && propertyData->isAlias()) {
- QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
+ findAliasTarget(object, index, &object, &index);
- QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
- if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex) || aCoreIndex == -1)
- return 0;
-
- // This will either be a value type sub-reference or an alias to a value-type sub-reference not both
- Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1);
- aValueTypeIndex = (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex;
- return binding(aObject, aCoreIndex, aValueTypeIndex);
- }
+ int coreIndex;
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex);
if (!data->hasBindingBit(coreIndex))
return 0;
QQmlAbstractBinding *binding = data->bindings;
- while (binding && binding->propertyIndex() != coreIndex)
+ while (binding && binding->targetPropertyIndex() != coreIndex)
binding = binding->nextBinding();
if (binding && valueTypeIndex != -1) {
- if (binding->bindingType() == QQmlAbstractBinding::ValueTypeProxy) {
+ if (binding->isValueTypeProxy()) {
int index = QQmlPropertyData::encodeValueTypePropertyIndex(coreIndex, valueTypeIndex);
binding = static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index);
}
@@ -786,11 +820,11 @@ QQmlPropertyPrivate::binding(QObject *object, int coreIndex, int valueTypeIndex)
void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex,
QObject **targetObject, int *targetBindingIndex)
{
- int coreIndex;
- int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(bindingIndex, &coreIndex);
-
QQmlData *data = QQmlData::get(object, false);
if (data) {
+ int coreIndex;
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(bindingIndex, &coreIndex);
+
QQmlPropertyData *propertyData =
data->propertyCache?data->propertyCache->property(coreIndex):0;
if (propertyData && propertyData->isAlias()) {
@@ -817,119 +851,30 @@ void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex,
*targetBindingIndex = bindingIndex;
}
-QQmlAbstractBinding *
-QQmlPropertyPrivate::setBinding(QObject *object, int coreIndex, int valueTypeIndex,
- QQmlAbstractBinding *newBinding, WriteFlags flags)
-{
- QQmlData *data = QQmlData::get(object, 0 != newBinding);
- QQmlAbstractBinding *binding = 0;
-
- if (data) {
- QQmlPropertyData *propertyData =
- data->propertyCache?data->propertyCache->property(coreIndex):0;
- if (propertyData && propertyData->isAlias()) {
- QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
- QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
- if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) {
- if (newBinding) newBinding->destroy();
- return 0;
- }
-
- // This will either be a value type sub-reference or an alias to a value-type sub-reference not both
- Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1);
- aValueTypeIndex = (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex;
- return setBinding(aObject, aCoreIndex, aValueTypeIndex, newBinding, flags);
- }
- }
-
- if (data && data->hasBindingBit(coreIndex)) {
- binding = data->bindings;
-
- while (binding && binding->propertyIndex() != coreIndex)
- binding = binding->nextBinding();
- }
-
- int index = coreIndex;
- if (valueTypeIndex != -1)
- index = QQmlPropertyData::encodeValueTypePropertyIndex(index, valueTypeIndex);
-
- if (binding && valueTypeIndex != -1 && binding->bindingType() == QQmlAbstractBinding::ValueTypeProxy)
- binding = static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index);
-
- if (binding) {
- binding->removeFromObject();
- binding->setEnabled(false, 0);
- }
-
- if (newBinding) {
- if (newBinding->propertyIndex() != index || newBinding->object() != object)
- newBinding->retargetBinding(object, index);
-
- Q_ASSERT(newBinding->propertyIndex() == index);
- Q_ASSERT(newBinding->object() == object);
-
- newBinding->addToObject();
- newBinding->setEnabled(true, flags);
- }
-
- return binding;
-}
-
-QQmlAbstractBinding *
-QQmlPropertyPrivate::setBindingNoEnable(QObject *object, int coreIndex, int valueTypeIndex,
- QQmlAbstractBinding *newBinding)
+void QQmlPropertyPrivate::setBinding(QQmlAbstractBinding *binding, BindingFlags flags, WriteFlags writeFlags)
{
- QQmlData *data = QQmlData::get(object, 0 != newBinding);
- QQmlAbstractBinding *binding = 0;
+ Q_ASSERT(binding);
- if (data) {
- QQmlPropertyData *propertyData =
- data->propertyCache?data->propertyCache->property(coreIndex):0;
- if (propertyData && propertyData->isAlias()) {
- QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
-
- QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
- if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) {
- if (newBinding) newBinding->destroy();
- return 0;
- }
-
- // This will either be a value type sub-reference or an alias to a value-type sub-reference not both
- Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1);
- aValueTypeIndex = (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex;
- return setBindingNoEnable(aObject, aCoreIndex, aValueTypeIndex, newBinding);
- }
- }
-
- if (data && data->hasBindingBit(coreIndex)) {
- binding = data->bindings;
+ QObject *object = binding->targetObject();
+ int index = binding->targetPropertyIndex();
- while (binding && binding->propertyIndex() != coreIndex)
- binding = binding->nextBinding();
+#ifndef QT_NO_DEBUG
+ int coreIndex;
+ QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex);
+ QQmlData *data = QQmlData::get(object, true);
+ if (data->propertyCache) {
+ QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex);
+ Q_ASSERT(propertyData && !propertyData->isAlias());
}
+#endif
- int index = coreIndex;
- if (valueTypeIndex != -1)
- index = QQmlPropertyData::encodeValueTypePropertyIndex(index, valueTypeIndex);
-
- if (binding && valueTypeIndex != -1 && binding->bindingType() == QQmlAbstractBinding::ValueTypeProxy)
- binding = static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index);
-
- if (binding)
- binding->removeFromObject();
-
- if (newBinding) {
- if (newBinding->propertyIndex() != index || newBinding->object() != object)
- newBinding->retargetBinding(object, index);
+ removeOldBinding(object, index, flags);
- Q_ASSERT(newBinding->propertyIndex() == index);
- Q_ASSERT(newBinding->object() == object);
+ binding->addToObject();
+ if (!(flags & DontEnable))
+ binding->setEnabled(true, writeFlags);
- newBinding->addToObject();
- }
-
- return binding;
}
/*!
@@ -946,9 +891,9 @@ QQmlPropertyPrivate::signalExpression(const QQmlProperty &that)
if (!data)
return 0;
- QQmlAbstractBoundSignal *signalHandler = data->signalHandlers;
+ QQmlBoundSignal *signalHandler = data->signalHandlers;
- while (signalHandler && signalHandler->index() != QQmlPropertyPrivate::get(that)->signalIndex())
+ while (signalHandler && signalHandler->signalIndex() != QQmlPropertyPrivate::get(that)->signalIndex())
signalHandler = signalHandler->m_nextSignal;
if (signalHandler)
@@ -959,48 +904,41 @@ QQmlPropertyPrivate::signalExpression(const QQmlProperty &that)
/*!
Set the signal expression associated with this signal property to \a expr.
- Returns the existing signal expression (if any), otherwise null.
-
- A reference to \a expr will be added by QML. Ownership of the return value
- reference is assumed by the caller.
+ A reference to \a expr will be added by QML.
*/
-QQmlBoundSignalExpressionPointer
-QQmlPropertyPrivate::setSignalExpression(const QQmlProperty &that,
- QQmlBoundSignalExpression *expr)
+void QQmlPropertyPrivate::setSignalExpression(const QQmlProperty &that, QQmlBoundSignalExpression *expr)
{
if (expr)
expr->addref();
- return QQmlPropertyPrivate::takeSignalExpression(that, expr);
+ QQmlPropertyPrivate::takeSignalExpression(that, expr);
}
/*!
Set the signal expression associated with this signal property to \a expr.
- Returns the existing signal expression (if any), otherwise null.
-
- Ownership of \a expr transfers to QML. Ownership of the return value
- reference is assumed by the caller.
+ Ownership of \a expr transfers to QML.
*/
-QQmlBoundSignalExpressionPointer
-QQmlPropertyPrivate::takeSignalExpression(const QQmlProperty &that,
+void QQmlPropertyPrivate::takeSignalExpression(const QQmlProperty &that,
QQmlBoundSignalExpression *expr)
{
if (!(that.type() & QQmlProperty::SignalProperty)) {
if (expr)
expr->release();
- return 0;
+ return;
}
QQmlData *data = QQmlData::get(that.d->object, 0 != expr);
if (!data)
- return 0;
+ return;
- QQmlAbstractBoundSignal *signalHandler = data->signalHandlers;
+ QQmlBoundSignal *signalHandler = data->signalHandlers;
- while (signalHandler && signalHandler->index() != QQmlPropertyPrivate::get(that)->signalIndex())
+ while (signalHandler && signalHandler->signalIndex() != QQmlPropertyPrivate::get(that)->signalIndex())
signalHandler = signalHandler->m_nextSignal;
- if (signalHandler)
- return signalHandler->takeExpression(expr);
+ if (signalHandler) {
+ signalHandler->takeExpression(expr);
+ return;
+ }
if (expr) {
int signalIndex = QQmlPropertyPrivate::get(that)->signalIndex();
@@ -1008,7 +946,6 @@ QQmlPropertyPrivate::takeSignalExpression(const QQmlProperty &that,
expr->context()->engine);
signal->takeExpression(expr);
}
- return 0;
}
/*!
@@ -1125,7 +1062,7 @@ QVariant QQmlPropertyPrivate::readValueProperty()
}
// helper function to allow assignment / binding to QList<QUrl> properties.
-static QVariant resolvedUrlSequence(const QVariant &value, QQmlContextData *context)
+QVariant QQmlPropertyPrivate::resolvedUrlSequence(const QVariant &value, QQmlContextData *context)
{
QList<QUrl> urls;
if (value.userType() == qMetaTypeId<QUrl>()) {
@@ -1138,16 +1075,22 @@ static QVariant resolvedUrlSequence(const QVariant &value, QQmlContextData *cont
urls = value.value<QList<QUrl> >();
} else if (value.userType() == qMetaTypeId<QStringList>()) {
QStringList urlStrings = value.value<QStringList>();
- for (int i = 0; i < urlStrings.size(); ++i)
+ const int urlStringsSize = urlStrings.size();
+ urls.reserve(urlStringsSize);
+ for (int i = 0; i < urlStringsSize; ++i)
urls.append(QUrl(urlStrings.at(i)));
} else if (value.userType() == qMetaTypeId<QList<QString> >()) {
QList<QString> urlStrings = value.value<QList<QString> >();
- for (int i = 0; i < urlStrings.size(); ++i)
+ const int urlStringsSize = urlStrings.size();
+ urls.reserve(urlStringsSize);
+ for (int i = 0; i < urlStringsSize; ++i)
urls.append(QUrl(urlStrings.at(i)));
} // note: QList<QByteArray> is not currently supported.
QList<QUrl> resolvedUrls;
- for (int i = 0; i < urls.size(); ++i) {
+ const int urlsSize = urls.size();
+ resolvedUrls.reserve(urlsSize);
+ for (int i = 0; i < urlsSize; ++i) {
QUrl u = urls.at(i);
if (context && u.isRelative() && !u.isEmpty())
u = context->resolvedUrl(u);
@@ -1210,12 +1153,8 @@ QQmlPropertyPrivate::writeValueProperty(QObject *object,
QQmlContextData *context, WriteFlags flags)
{
// Remove any existing bindings on this property
- if (!(flags & DontRemoveBinding) && object) {
- QQmlAbstractBinding *binding = setBinding(object, core.coreIndex,
- core.getValueTypeCoreIndex(),
- 0, flags);
- if (binding) binding->destroy();
- }
+ if (!(flags & DontRemoveBinding) && object)
+ removeBinding(object, core.encodedIndex());
bool rv = false;
if (core.isValueTypeVirtual()) {
@@ -1255,7 +1194,7 @@ bool QQmlPropertyPrivate::write(QObject *object,
// Enum values come through the script engine as doubles
if (value.userType() == QVariant::Double) {
double integral;
- double fractional = modf(value.toDouble(), &integral);
+ double fractional = std::modf(value.toDouble(), &integral);
if (qFuzzyIsNull(fractional))
v.convert(QVariant::Int);
}
@@ -1414,7 +1353,12 @@ bool QQmlPropertyPrivate::write(QObject *object,
if (!ok) {
v = value;
- if (v.convert(propertyType)) {
+ if (variantType == QVariant::Double && propertyType == QVariant::String) {
+ QString number;
+ QV4::RuntimeHelpers::numberToString(&number, v.toDouble());
+ v = number;
+ ok = true;
+ } else if (v.convert(propertyType)) {
ok = true;
} else if (v.isValid() && value.isNull()) {
// For historical reasons converting a null QVariant to another type will do the trick
@@ -1475,166 +1419,6 @@ bool QQmlPropertyPrivate::write(QObject *object,
return true;
}
-// Returns true if successful, false if an error description was set on expression
-bool QQmlPropertyPrivate::writeBinding(QObject *object,
- const QQmlPropertyData &core,
- QQmlContextData *context,
- QQmlJavaScriptExpression *expression,
- const QV4::Value &result, bool isUndefined,
- WriteFlags flags)
-{
- Q_ASSERT(object);
- Q_ASSERT(core.coreIndex != -1);
-
- QQmlEngine *engine = context->engine;
- QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(engine);
-
-#define QUICK_STORE(cpptype, conversion) \
- { \
- cpptype o = (conversion); \
- int status = -1; \
- void *argv[] = { &o, 0, &status, &flags }; \
- QMetaObject::metacall(object, QMetaObject::WriteProperty, core.coreIndex, argv); \
- return true; \
- } \
-
-
- if (!isUndefined && !core.isValueTypeVirtual()) {
- switch (core.propType) {
- case QMetaType::Int:
- if (result.isInteger())
- QUICK_STORE(int, result.integerValue())
- else if (result.isNumber())
- QUICK_STORE(int, result.doubleValue())
- break;
- case QMetaType::Double:
- if (result.isNumber())
- QUICK_STORE(double, result.asDouble())
- break;
- case QMetaType::Float:
- if (result.isNumber())
- QUICK_STORE(float, result.asDouble())
- break;
- case QMetaType::QString:
- if (result.isString())
- QUICK_STORE(QString, result.toQStringNoThrow())
- break;
- default:
- if (const QV4::QQmlValueTypeWrapper *vtw = result.as<const QV4::QQmlValueTypeWrapper>()) {
- if (vtw->d()->valueType->typeId == core.propType) {
- return vtw->write(object, core.coreIndex);
- }
- }
- break;
- }
- }
-#undef QUICK_STORE
-
- int type = core.isValueTypeVirtual()?core.valueTypePropType:core.propType;
-
- QQmlJavaScriptExpression::DeleteWatcher watcher(expression);
-
- QVariant value;
- bool isVarProperty = core.isVarProperty();
-
- if (isUndefined) {
- } else if (core.isQList()) {
- value = QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QObject *> >());
- } else if (result.isNull() && core.isQObject()) {
- value = QVariant::fromValue((QObject *)0);
- } else if (core.propType == qMetaTypeId<QList<QUrl> >()) {
- value = resolvedUrlSequence(QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QUrl> >()), context);
- } else if (!isVarProperty && type != qMetaTypeId<QJSValue>()) {
- value = QV8Engine::getV4(v8engine)->toVariant(result, type);
- }
-
- if (expression->hasError()) {
- return false;
- } else if (isVarProperty) {
- QV4::FunctionObject *f = result.asFunctionObject();
- if (f && f->isBinding()) {
- // we explicitly disallow this case to avoid confusion. Users can still store one
- // in an array in a var property if they need to, but the common case is user error.
- expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
- expression->delayedError()->setErrorObject(object);
- return false;
- }
-
- QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
- Q_ASSERT(vmemo);
- vmemo->setVMEProperty(core.coreIndex, result);
- } else if (isUndefined && core.isResettable()) {
- void *args[] = { 0 };
- QMetaObject::metacall(object, QMetaObject::ResetProperty, core.coreIndex, args);
- } else if (isUndefined && type == qMetaTypeId<QVariant>()) {
- writeValueProperty(object, core, QVariant(), context, flags);
- } else if (type == qMetaTypeId<QJSValue>()) {
- QV4::FunctionObject *f = result.asFunctionObject();
- if (f && f->isBinding()) {
- expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
- expression->delayedError()->setErrorObject(object);
- return false;
- }
- writeValueProperty(object, core, QVariant::fromValue(
- QJSValue(QV8Engine::getV4(v8engine), result.asReturnedValue())),
- context, flags);
- } else if (isUndefined) {
- QString errorStr = QLatin1String("Unable to assign [undefined] to ");
- if (!QMetaType::typeName(type))
- errorStr += QLatin1String("[unknown property type]");
- else
- errorStr += QLatin1String(QMetaType::typeName(type));
- expression->delayedError()->setErrorDescription(errorStr);
- expression->delayedError()->setErrorObject(object);
- return false;
- } else if (QV4::FunctionObject *f = result.asFunctionObject()) {
- if (f->isBinding())
- expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
- else
- expression->delayedError()->setErrorDescription(QLatin1String("Unable to assign a function to a property of any type other than var."));
- expression->delayedError()->setErrorObject(object);
- return false;
- } else if (!writeValueProperty(object, core, value, context, flags)) {
-
- if (watcher.wasDeleted())
- return true;
-
- const char *valueType = 0;
- const char *propertyType = 0;
-
- if (value.userType() == QMetaType::QObjectStar) {
- if (QObject *o = *(QObject *const *)value.constData()) {
- valueType = o->metaObject()->className();
-
- QQmlMetaObject propertyMetaObject = rawMetaObjectForType(QQmlEnginePrivate::get(engine), type);
- if (!propertyMetaObject.isNull())
- propertyType = propertyMetaObject.className();
- }
- } else if (value.userType() != QVariant::Invalid) {
- if (value.userType() == QMetaType::VoidStar)
- valueType = "null";
- else
- valueType = QMetaType::typeName(value.userType());
- }
-
- if (!valueType)
- valueType = "undefined";
- if (!propertyType)
- propertyType = QMetaType::typeName(type);
- if (!propertyType)
- propertyType = "[unknown property type]";
-
- expression->delayedError()->setErrorDescription(QLatin1String("Unable to assign ") +
- QLatin1String(valueType) +
- QLatin1String(" to ") +
- QLatin1String(propertyType));
- expression->delayedError()->setErrorObject(object);
- return false;
- }
-
- return true;
-}
-
QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engine, int userType)
{
QMetaType metaType(userType);
diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h
index 98e310ebce..51a1db7b90 100644
--- a/src/qml/qml/qqmlproperty_p.h
+++ b/src/qml/qml/qqmlproperty_p.h
@@ -58,6 +58,7 @@ QT_BEGIN_NAMESPACE
class QQmlContext;
class QQmlEnginePrivate;
class QQmlJavaScriptExpression;
+
class Q_QML_PRIVATE_EXPORT QQmlPropertyPrivate : public QQmlRefCount
{
public:
@@ -103,15 +104,18 @@ public:
QQmlContextData *, WriteFlags flags = 0);
static void findAliasTarget(QObject *, int, QObject **, int *);
- static QQmlAbstractBinding *setBinding(QObject *, int coreIndex,
- int valueTypeIndex /* -1 */,
- QQmlAbstractBinding *,
- WriteFlags flags = DontRemoveBinding);
- static QQmlAbstractBinding *setBindingNoEnable(QObject *, int coreIndex,
- int valueTypeIndex /* -1 */,
- QQmlAbstractBinding *);
- static QQmlAbstractBinding *binding(QObject *, int coreIndex,
- int valueTypeIndex /* -1 */);
+ enum BindingFlag {
+ None = 0,
+ DontEnable = 0x1
+ };
+ Q_DECLARE_FLAGS(BindingFlags, BindingFlag)
+
+ static void setBinding(QQmlAbstractBinding *binding, BindingFlags flags = None, WriteFlags writeFlags = DontRemoveBinding);
+
+ static void removeBinding(const QQmlProperty &that);
+ static void removeBinding(QObject *o, int index);
+ static void removeBinding(QQmlAbstractBinding *b);
+ static QQmlAbstractBinding *binding(QObject *, int index);
static QQmlPropertyData saveValueType(const QQmlPropertyData &,
const QMetaObject *, int,
@@ -128,20 +132,13 @@ public:
// "Public" (to QML) methods
static QQmlAbstractBinding *binding(const QQmlProperty &that);
- static QQmlAbstractBinding *setBinding(const QQmlProperty &that,
- QQmlAbstractBinding *,
- WriteFlags flags = DontRemoveBinding);
+ static void setBinding(const QQmlProperty &that, QQmlAbstractBinding *);
static QQmlBoundSignalExpression *signalExpression(const QQmlProperty &that);
- static QQmlBoundSignalExpressionPointer setSignalExpression(const QQmlProperty &that,
+ static void setSignalExpression(const QQmlProperty &that,
QQmlBoundSignalExpression *);
- static QQmlBoundSignalExpressionPointer takeSignalExpression(const QQmlProperty &that,
+ static void takeSignalExpression(const QQmlProperty &that,
QQmlBoundSignalExpression *);
static bool write(const QQmlProperty &that, const QVariant &, WriteFlags);
- static bool writeBinding(QObject *, const QQmlPropertyData &,
- QQmlContextData *context,
- QQmlJavaScriptExpression *expression,
- const QV4::Value &result, bool isUndefined,
- WriteFlags flags);
static int valueTypeCoreIndex(const QQmlProperty &that);
static int bindingIndex(const QQmlProperty &that);
static int bindingIndex(const QQmlPropertyData &that);
@@ -150,9 +147,12 @@ public:
const QObject *receiver, int method_index,
int type = 0, int *types = 0);
static void flushSignal(const QObject *sender, int signal_index);
+
+ static QVariant resolvedUrlSequence(const QVariant &value, QQmlContextData *context);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyPrivate::WriteFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyPrivate::BindingFlags)
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 0018275b95..e8c9989fdf 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -42,7 +42,7 @@
#include <private/qqmlaccessors_p.h>
#include <private/qmetaobjectbuilder_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <QtCore/qdebug.h>
@@ -231,10 +231,10 @@ void QQmlPropertyData::lazyLoad(const QMetaMethod &m)
/*!
Creates a new empty QQmlPropertyCache.
*/
-QQmlPropertyCache::QQmlPropertyCache(QJSEngine *e)
-: engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
- signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
- _metaObject(0), argumentsCache(0)
+QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e)
+ : engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
+ signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
+ _metaObject(0), argumentsCache(0)
{
Q_ASSERT(engine);
}
@@ -242,10 +242,10 @@ QQmlPropertyCache::QQmlPropertyCache(QJSEngine *e)
/*!
Creates a new QQmlPropertyCache of \a metaObject.
*/
-QQmlPropertyCache::QQmlPropertyCache(QJSEngine *e, const QMetaObject *metaObject)
-: engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
- signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
- _metaObject(0), argumentsCache(0)
+QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e, const QMetaObject *metaObject)
+ : engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
+ signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
+ _metaObject(0), argumentsCache(0)
{
Q_ASSERT(engine);
Q_ASSERT(metaObject);
@@ -346,25 +346,6 @@ void QQmlPropertyCache::appendProperty(const QString &name,
setNamedProperty(name, index + propertyOffset(), propertyIndexCache.data() + index, (old != 0));
}
-void QQmlPropertyCache::appendProperty(const QHashedCStringRef &name,
- quint32 flags, int coreIndex, int propType, int notifyIndex)
-{
- QQmlPropertyData data;
- data.propType = propType;
- data.coreIndex = coreIndex;
- data.notifyIndex = notifyIndex;
- data.flags = flags;
-
- QQmlPropertyData *old = findNamedProperty(name);
- if (old)
- data.markAsOverrideOf(old);
-
- int index = propertyIndexCache.count();
- propertyIndexCache.append(data);
-
- setNamedProperty(name, index + propertyOffset(), propertyIndexCache.data() + index, (old != 0));
-}
-
void QQmlPropertyCache::appendSignal(const QString &name, quint32 flags, int coreIndex,
const int *types, const QList<QByteArray> &names)
{
@@ -402,43 +383,6 @@ void QQmlPropertyCache::appendSignal(const QString &name, quint32 flags, int cor
setNamedProperty(handlerName, signalHandlerIndex + signalOffset(), signalHandlerIndexCache.data() + signalHandlerIndex, (old != 0));
}
-void QQmlPropertyCache::appendSignal(const QHashedCStringRef &name, quint32 flags, int coreIndex,
- const int *types, const QList<QByteArray> &names)
-{
- QQmlPropertyData data;
- data.propType = QVariant::Invalid;
- data.coreIndex = coreIndex;
- data.flags = flags;
- data.arguments = 0;
-
- QQmlPropertyData handler = data;
- handler.flags |= QQmlPropertyData::IsSignalHandler;
-
- if (types) {
- int argumentCount = *types;
- QQmlPropertyCacheMethodArguments *args = createArgumentsObject(argumentCount, names);
- ::memcpy(args->arguments, types, (argumentCount + 1) * sizeof(int));
- args->argumentsValid = true;
- data.arguments = args;
- }
-
- QQmlPropertyData *old = findNamedProperty(name);
- if (old)
- data.markAsOverrideOf(old);
-
- int methodIndex = methodIndexCache.count();
- methodIndexCache.append(data);
-
- int signalHandlerIndex = signalHandlerIndexCache.count();
- signalHandlerIndexCache.append(handler);
-
- QString handlerName = QLatin1String("on") + name.toUtf16();
- handlerName[2] = handlerName[2].toUpper();
-
- setNamedProperty(name, methodIndex + methodOffset(), methodIndexCache.data() + methodIndex, (old != 0));
- setNamedProperty(handlerName, signalHandlerIndex + signalOffset(), signalHandlerIndexCache.data() + signalHandlerIndex, (old != 0));
-}
-
void QQmlPropertyCache::appendMethod(const QString &name, quint32 flags, int coreIndex,
const QList<QByteArray> &names)
{
@@ -466,33 +410,6 @@ void QQmlPropertyCache::appendMethod(const QString &name, quint32 flags, int cor
setNamedProperty(name, methodIndex + methodOffset(), methodIndexCache.data() + methodIndex, (old != 0));
}
-void QQmlPropertyCache::appendMethod(const QHashedCStringRef &name, quint32 flags, int coreIndex,
- const QList<QByteArray> &names)
-{
- int argumentCount = names.count();
-
- QQmlPropertyData data;
- data.propType = QMetaType::QVariant;
- data.coreIndex = coreIndex;
-
- QQmlPropertyCacheMethodArguments *args = createArgumentsObject(argumentCount, names);
- for (int ii = 0; ii < argumentCount; ++ii)
- args->arguments[ii + 1] = QMetaType::QVariant;
- args->argumentsValid = true;
- data.arguments = args;
-
- data.flags = flags;
-
- QQmlPropertyData *old = findNamedProperty(name);
- if (old)
- data.markAsOverrideOf(old);
-
- int methodIndex = methodIndexCache.count();
- methodIndexCache.append(data);
-
- setNamedProperty(name, methodIndex + methodOffset(), methodIndexCache.data() + methodIndex, (old != 0));
-}
-
// Returns this property cache's metaObject. May be null if it hasn't been created yet.
const QMetaObject *QQmlPropertyCache::metaObject() const
{
@@ -818,7 +735,7 @@ void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
data->propType = registerResult == -1 ? QMetaType::UnknownType : registerResult;
}
}
- data->flags |= flagsForPropertyType(data->propType, qobject_cast<QQmlEngine*>(engine));
+ data->flags |= flagsForPropertyType(data->propType, engine->qmlEngine());
}
data->flags &= ~QQmlPropertyData::NotFullyResolved;
@@ -837,7 +754,7 @@ void QQmlPropertyCache::updateRecur(const QMetaObject *metaObject)
void QQmlPropertyCache::update(const QMetaObject *metaObject)
{
Q_ASSERT(metaObject);
- Q_ASSERT(stringCache.isEmpty());
+ stringCache.clear();
// Preallocate enough space in the index caches for all the properties/methods/signals that
// are not cached in a parent cache so that the caches never need to be reallocated as this
@@ -862,7 +779,6 @@ void QQmlPropertyCache::update(const QMetaObject *metaObject)
*/
void QQmlPropertyCache::invalidate(const QMetaObject *metaObject)
{
- stringCache.clear();
propertyIndexCache.clear();
methodIndexCache.clear();
signalHandlerIndexCache.clear();
@@ -894,19 +810,17 @@ void QQmlPropertyCache::invalidate(const QMetaObject *metaObject)
This is different from QMetaMethod::methodIndex().
*/
QQmlPropertyData *
-QQmlPropertyCache::signal(int index, QQmlPropertyCache **c) const
+QQmlPropertyCache::signal(int index) const
{
if (index < 0 || index >= (signalHandlerIndexCacheStart + signalHandlerIndexCache.count()))
return 0;
if (index < signalHandlerIndexCacheStart)
- return _parent->signal(index, c);
+ return _parent->signal(index);
QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&methodIndexCache.at(index - signalHandlerIndexCacheStart));
- if (rv->notFullyResolved()) resolve(rv);
Q_ASSERT(rv->isSignal() || rv->coreIndex == -1);
- if (c) *c = const_cast<QQmlPropertyCache *>(this);
- return rv;
+ return ensureResolved(rv);
}
int QQmlPropertyCache::methodIndexToSignalIndex(int index) const
@@ -1102,52 +1016,6 @@ QQmlPropertyCacheMethodArguments *QQmlPropertyCache::createArgumentsObject(int a
return args;
}
-/*! \internal
- \a index MUST be in the signal index range (see QObjectPrivate::signalIndex()).
- This is different from QMetaMethod::methodIndex().
-*/
-QString QQmlPropertyCache::signalParameterStringForJS(int index, QString *errorString)
-{
- QQmlPropertyCache *c = 0;
- QQmlPropertyData *signalData = signal(index, &c);
- if (!signalData)
- return QString();
-
- typedef QQmlPropertyCacheMethodArguments A;
-
- if (signalData->arguments) {
- A *arguments = static_cast<A *>(signalData->arguments);
- if (arguments->signalParameterStringForJS) {
- if (arguments->parameterError) {
- if (errorString)
- *errorString = *arguments->signalParameterStringForJS;
- return QString();
- }
- return *arguments->signalParameterStringForJS;
- }
- }
-
- QList<QByteArray> parameterNameList = signalParameterNames(index);
-
- if (!signalData->arguments) {
- A *args = c->createArgumentsObject(parameterNameList.count(), parameterNameList);
- signalData->arguments = args;
- }
-
- QString error;
- QString parameters = signalParameterStringForJS(QV8Engine::getV4(engine), parameterNameList, &error);
-
- A *arguments = static_cast<A *>(signalData->arguments);
- arguments->signalParameterStringForJS = new QString(!error.isEmpty() ? error : parameters);
- if (!error.isEmpty()) {
- arguments->parameterError = true;
- if (errorString)
- *errorString = *arguments->signalParameterStringForJS;
- return QString();
- }
- return *arguments->signalParameterStringForJS;
-}
-
QString QQmlPropertyCache::signalParameterStringForJS(QV4::ExecutionEngine *engine, const QList<QByteArray> &parameterNameList, QString *errorString)
{
bool unnamedParameter = false;
@@ -1406,19 +1274,19 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
if (data->propType != 0)
returnType = QMetaType::typeName(data->propType);
- QByteArray signature = methods.at(ii).first.toUtf8() + "(";
+ QByteArray signature = methods.at(ii).first.toUtf8() + '(';
QQmlPropertyCacheMethodArguments *arguments = 0;
if (data->hasArguments()) {
arguments = (QQmlPropertyCacheMethodArguments *)data->arguments;
Q_ASSERT(arguments->argumentsValid);
for (int ii = 0; ii < arguments->arguments[0]; ++ii) {
- if (ii != 0) signature.append(",");
+ if (ii != 0) signature.append(',');
signature.append(QMetaType::typeName(arguments->arguments[1 + ii]));
}
}
- signature.append(")");
+ signature.append(')');
QMetaMethodBuilder method;
if (data->isSignal()) {
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 6ed9ec0d36..610709ef7f 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -54,7 +54,7 @@
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qvector.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
QT_BEGIN_NAMESPACE
@@ -174,7 +174,6 @@ public:
int propType; // When !NotFullyResolved
const char *propTypeName; // When NotFullyResolved
};
- int coreIndex;
union {
// The notify index is in the range returned by QObjectPrivate::signalIndex().
// This is different from QMetaMethod::methodIndex().
@@ -208,6 +207,7 @@ public:
qintptr accessorData;
};
};
+ int coreIndex;
private:
friend class QQmlPropertyData;
@@ -243,8 +243,8 @@ class QQmlPropertyCacheMethodArguments;
class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount, public QQmlCleanup
{
public:
- QQmlPropertyCache(QJSEngine *);
- QQmlPropertyCache(QJSEngine *, const QMetaObject *);
+ QQmlPropertyCache(QV4::ExecutionEngine *);
+ QQmlPropertyCache(QV4::ExecutionEngine *, const QMetaObject *);
virtual ~QQmlPropertyCache();
void update(const QMetaObject *);
@@ -267,16 +267,10 @@ public:
int methodCount, int signalCount);
void appendProperty(const QString &,
quint32 flags, int coreIndex, int propType, int notifyIndex);
- void appendProperty(const QHashedCStringRef &,
- quint32 flags, int coreIndex, int propType, int notifyIndex);
void appendSignal(const QString &, quint32, int coreIndex, const int *types = 0,
const QList<QByteArray> &names = QList<QByteArray>());
- void appendSignal(const QHashedCStringRef &, quint32, int coreIndex, const int *types = 0,
- const QList<QByteArray> &names = QList<QByteArray>());
void appendMethod(const QString &, quint32 flags, int coreIndex,
const QList<QByteArray> &names = QList<QByteArray>());
- void appendMethod(const QHashedCStringRef &, quint32 flags, int coreIndex,
- const QList<QByteArray> &names = QList<QByteArray>());
const QMetaObject *metaObject() const;
const QMetaObject *createMetaObject();
@@ -290,7 +284,7 @@ public:
QQmlPropertyData *property(int) const;
QQmlPropertyData *method(int) const;
- QQmlPropertyData *signal(int index) const { return signal(index, 0); }
+ QQmlPropertyData *signal(int index) const;
int methodIndexToSignalIndex(int) const;
QStringList propertyNames() const;
@@ -313,7 +307,6 @@ public:
static int originalClone(QObject *, int index);
QList<QByteArray> signalParameterNames(int index) const;
- QString signalParameterStringForJS(int index, QString *errorString = 0);
static QString signalParameterStringForJS(QV4::ExecutionEngine *engine, const QList<QByteArray> &parameterNameList, QString *errorString = 0);
const char *className() const;
@@ -347,9 +340,7 @@ private:
QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
- QQmlPropertyCacheMethodArguments *createArgumentsObject(int count,
- const QList<QByteArray> &names);
- QQmlPropertyData *signal(int, QQmlPropertyCache **) const;
+ QQmlPropertyCacheMethodArguments *createArgumentsObject(int count, const QList<QByteArray> &names);
typedef QVector<QQmlPropertyData> IndexCache;
typedef QStringMultiHash<QPair<int, QQmlPropertyData *> > StringCache;
@@ -377,8 +368,10 @@ private:
_hasPropertyOverrides |= isOverride;
}
- QJSEngine *engine;
+public:
+ QV4::ExecutionEngine *engine;
+private:
QQmlPropertyCache *_parent;
int propertyIndexCacheStart;
int methodIndexCacheStart;
diff --git a/src/qml/qml/qqmlpropertyvalueinterceptor_p.h b/src/qml/qml/qqmlpropertyvalueinterceptor_p.h
index ea267f9c30..6403e85f2a 100644
--- a/src/qml/qml/qqmlpropertyvalueinterceptor_p.h
+++ b/src/qml/qml/qqmlpropertyvalueinterceptor_p.h
@@ -60,7 +60,7 @@ public:
virtual void write(const QVariant &value) = 0;
private:
- friend class QQmlVMEMetaObject;
+ friend class QQmlInterceptorMetaObject;
int m_coreIndex;
int m_valueTypeCoreIndex;
diff --git a/src/qml/qml/qqmlproxymetaobject.cpp b/src/qml/qml/qqmlproxymetaobject.cpp
index bf735a9f0c..ba5215b831 100644
--- a/src/qml/qml/qqmlproxymetaobject.cpp
+++ b/src/qml/qml/qqmlproxymetaobject.cpp
@@ -59,8 +59,10 @@ QQmlProxyMetaObject::~QQmlProxyMetaObject()
proxies = 0;
}
-int QQmlProxyMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
+int QQmlProxyMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void **a)
{
+ Q_ASSERT(object == o);
+
if ((c == QMetaObject::ReadProperty ||
c == QMetaObject::WriteProperty) &&
id >= metaObjects->last().propertyOffset) {
@@ -108,7 +110,7 @@ int QQmlProxyMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
}
if (parent)
- return parent->metaCall(c, id, a);
+ return parent->metaCall(o, c, id, a);
else
return object->qt_metacall(c, id, a);
}
diff --git a/src/qml/qml/qqmlproxymetaobject_p.h b/src/qml/qml/qqmlproxymetaobject_p.h
index 862b0fb7c2..6ae35fe11f 100644
--- a/src/qml/qml/qqmlproxymetaobject_p.h
+++ b/src/qml/qml/qqmlproxymetaobject_p.h
@@ -71,7 +71,7 @@ public:
virtual ~QQmlProxyMetaObject();
protected:
- virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+ virtual int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a);
private:
QList<ProxyData> *metaObjects;
diff --git a/src/qml/qml/qqmlscriptstring_p.h b/src/qml/qml/qqmlscriptstring_p.h
index 24bfdcdd4e..aa0a1e5695 100644
--- a/src/qml/qml/qqmlscriptstring_p.h
+++ b/src/qml/qml/qqmlscriptstring_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLSCRIPTSTRING_P_H
#define QQMLSCRIPTSTRING_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qqmlscriptstring.h"
#include <QtQml/qqmlcontext.h>
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index d713e9ee03..1e671542be 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -81,7 +81,7 @@
#define ASSERT_MAINTHREAD() do { if (m_thread->isThisThread()) qFatal("QQmlTypeLoader: Caller not in main thread"); } while (false)
#define ASSERT_LOADTHREAD() do { if (!m_thread->isThisThread()) qFatal("QQmlTypeLoader: Caller not in load thread"); } while (false)
-#define ASSERT_CALLBACK() do { if(!m_manager || !m_manager->m_thread->isThisThread()) qFatal("QQmlDataBlob: An API call was made outside a callback"); } while(false)
+#define ASSERT_CALLBACK() do { if (!m_typeLoader || !m_typeLoader->m_thread->isThisThread()) qFatal("QQmlDataBlob: An API call was made outside a callback"); } while (false)
#else
@@ -647,6 +647,8 @@ void QQmlDataBlob::notifyComplete(QQmlDataBlob *blob)
{
Q_ASSERT(m_waitingFor.contains(blob));
Q_ASSERT(blob->status() == Error || blob->status() == Complete);
+ QQmlCompilingProfiler prof(QQmlEnginePrivate::get(typeLoader()->engine())->profiler,
+ blob->url());
m_inCallback = true;
@@ -909,97 +911,116 @@ void QQmlTypeLoader::unlock()
m_thread->unlock();
}
-/*!
-Load the provided \a blob from the network or filesystem.
+struct PlainLoader {
+ void loadThread(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->loadThread(blob);
+ }
+ void load(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->m_thread->load(blob);
+ }
+ void loadAsync(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->m_thread->loadAsync(blob);
+ }
+};
-The loader must be locked.
-*/
-void QQmlTypeLoader::load(QQmlDataBlob *blob, Mode mode)
+struct StaticLoader {
+ const QByteArray &data;
+ StaticLoader(const QByteArray &data) : data(data) {}
+
+ void loadThread(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->loadWithStaticDataThread(blob, data);
+ }
+ void load(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->m_thread->loadWithStaticData(blob, data);
+ }
+ void loadAsync(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->m_thread->loadWithStaticDataAsync(blob, data);
+ }
+};
+
+struct CachedLoader {
+ const QQmlPrivate::CachedQmlUnit *unit;
+ CachedLoader(const QQmlPrivate::CachedQmlUnit *unit) : unit(unit) {}
+
+ void loadThread(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->loadWithCachedUnitThread(blob, unit);
+ }
+ void load(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->m_thread->loadWithCachedUnit(blob, unit);
+ }
+ void loadAsync(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->m_thread->loadWithCachedUnit(blob, unit);
+ }
+};
+
+template<typename Loader>
+void QQmlTypeLoader::doLoad(const Loader &loader, QQmlDataBlob *blob, Mode mode)
{
#ifdef DATABLOB_DEBUG
- qWarning("QQmlTypeLoader::load(%s): %s thread", qPrintable(blob->m_url.toString()),
+ qWarning("QQmlTypeLoader::doLoad(%s): %s thread", qPrintable(blob->m_url.toString()),
m_thread->isThisThread()?"Compile":"Engine");
#endif
blob->startLoading();
if (m_thread->isThisThread()) {
unlock();
- loadThread(blob);
+ loader.loadThread(this, blob);
lock();
- } else if (mode == PreferSynchronous) {
+ } else if (mode == Asynchronous) {
+ blob->m_data.setIsAsync(true);
unlock();
- m_thread->load(blob);
+ loader.loadAsync(this, blob);
lock();
- if (!blob->isCompleteOrError())
- blob->m_data.setIsAsync(true);
} else {
- Q_ASSERT(mode == Asynchronous);
- blob->m_data.setIsAsync(true);
unlock();
- m_thread->loadAsync(blob);
+ loader.load(this, blob);
lock();
+ if (mode == PreferSynchronous) {
+ if (!blob->isCompleteOrError())
+ blob->m_data.setIsAsync(true);
+ } else {
+ Q_ASSERT(mode == Synchronous);
+ while (!blob->isCompleteOrError()) {
+ unlock();
+ m_thread->waitForNextMessage();
+ lock();
+ }
+ }
}
}
/*!
-Load the provided \a blob with \a data. The blob's URL is not used by the data loader in this case.
+Load the provided \a blob from the network or filesystem.
The loader must be locked.
*/
-void QQmlTypeLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &data, Mode mode)
+void QQmlTypeLoader::load(QQmlDataBlob *blob, Mode mode)
{
-#ifdef DATABLOB_DEBUG
- qWarning("QQmlTypeLoader::loadWithStaticData(%s, data): %s thread", qPrintable(blob->m_url.toString()),
- m_thread->isThisThread()?"Compile":"Engine");
-#endif
+ doLoad(PlainLoader(), blob, mode);
+}
- blob->startLoading();
+/*!
+Load the provided \a blob with \a data. The blob's URL is not used by the data loader in this case.
- if (m_thread->isThisThread()) {
- unlock();
- loadWithStaticDataThread(blob, data);
- lock();
- } else if (mode == PreferSynchronous) {
- unlock();
- m_thread->loadWithStaticData(blob, data);
- lock();
- if (!blob->isCompleteOrError())
- blob->m_data.setIsAsync(true);
- } else {
- Q_ASSERT(mode == Asynchronous);
- blob->m_data.setIsAsync(true);
- unlock();
- m_thread->loadWithStaticDataAsync(blob, data);
- lock();
- }
+The loader must be locked.
+*/
+void QQmlTypeLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &data, Mode mode)
+{
+ doLoad(StaticLoader(data), blob, mode);
}
void QQmlTypeLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit, Mode mode)
{
-#ifdef DATABLOB_DEBUG
- qWarning("QQmlTypeLoader::loadWithUnitFcatory(%s, data): %s thread", qPrintable(blob->m_url.toString()),
- m_thread->isThisThread()?"Compile":"Engine");
-#endif
-
- blob->startLoading();
-
- if (m_thread->isThisThread()) {
- unlock();
- loadWithCachedUnitThread(blob, unit);
- lock();
- } else if (mode == PreferSynchronous) {
- unlock();
- m_thread->loadWithCachedUnit(blob, unit);
- lock();
- if (!blob->isCompleteOrError())
- blob->m_data.setIsAsync(true);
- } else {
- Q_ASSERT(mode == Asynchronous);
- blob->m_data.setIsAsync(true);
- unlock();
- m_thread->loadWithCachedUnitAsync(blob, unit);
- lock();
- }
+ doLoad(CachedLoader(unit), blob, mode);
}
void QQmlTypeLoader::loadWithStaticDataThread(QQmlDataBlob *blob, const QByteArray &data)
@@ -1194,6 +1215,8 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, QQmlFile *file)
void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d)
{
QML_MEMORY_SCOPE_URL(blob->url());
+ QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob->url());
+
blob->m_inCallback = true;
blob->dataReceived(d);
@@ -1212,6 +1235,8 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d)
void QQmlTypeLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
{
QML_MEMORY_SCOPE_URL(blob->url());
+ QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob->url());
+
blob->m_inCallback = true;
blob->initializeFromCachedUnit(unit);
@@ -1612,6 +1637,20 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode)
} else {
QQmlTypeLoader::load(typeData, mode);
}
+ } else if ((mode == PreferSynchronous || mode == Synchronous) && QQmlFile::isSynchronous(url)) {
+ // this was started Asynchronous, but we need to force Synchronous
+ // completion now (if at all possible with this type of URL).
+
+ if (!m_thread->isThisThread()) {
+ // this only works when called directly from the UI thread, but not
+ // when recursively called on the QML thread via resolveTypes()
+
+ while (!typeData->isCompleteOrError()) {
+ unlock();
+ m_thread->waitForNextMessage();
+ lock();
+ }
+ }
}
typeData->addref();
@@ -1623,12 +1662,12 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode)
Returns a QQmlTypeData for the given \a data with the provided base \a url. The
QQmlTypeData will not be cached.
*/
-QQmlTypeData *QQmlTypeLoader::getType(const QByteArray &data, const QUrl &url)
+QQmlTypeData *QQmlTypeLoader::getType(const QByteArray &data, const QUrl &url, Mode mode)
{
LockHolder<QQmlTypeLoader> holder(this);
QQmlTypeData *typeData = new QQmlTypeData(url, this);
- QQmlTypeLoader::loadWithStaticData(typeData, data);
+ QQmlTypeLoader::loadWithStaticData(typeData, data, mode);
return typeData;
}
@@ -2114,6 +2153,7 @@ void QQmlTypeData::dataReceived(const Data &data)
QmlIR::IRBuilder compiler(QV8Engine::get(qmlEngine)->illegalNames());
if (!compiler.generateFromQml(code, finalUrlString(), m_document.data())) {
QList<QQmlError> errors;
+ errors.reserve(compiler.errors.count());
foreach (const QQmlJS::DiagnosticMessage &msg, compiler.errors) {
QQmlError e;
e.setUrl(finalUrl());
@@ -2238,8 +2278,6 @@ void QQmlTypeData::compile()
m_compiledData = new QQmlCompiledData(typeLoader()->engine());
- QQmlCompilingProfiler prof(QQmlEnginePrivate::get(typeLoader()->engine())->profiler, finalUrlString());
-
QQmlTypeCompiler compiler(QQmlEnginePrivate::get(typeLoader()->engine()), m_compiledData, this, m_document.data());
if (!compiler.compile()) {
setError(compiler.compilationErrors());
@@ -2282,8 +2320,8 @@ void QQmlTypeData::resolveTypes()
m_namespaces.insert(csRef.prefix);
}
- int majorVersion = -1;
- int minorVersion = -1;
+ int majorVersion = csRef.majorVersion > -1 ? csRef.majorVersion : -1;
+ int minorVersion = csRef.minorVersion > -1 ? csRef.minorVersion : -1;
if (!resolveType(typeName, majorVersion, minorVersion, ref))
return;
@@ -2452,12 +2490,10 @@ void QQmlScriptData::initialize(QQmlEngine *engine)
addref();
}
-QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *parentCtxt)
+QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parentCtxt)
{
if (m_loaded)
- return m_value;
-
- QV4::PersistentValue rv;
+ return m_value.value();
Q_ASSERT(parentCtxt && parentCtxt->engine);
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(parentCtxt->engine);
@@ -2507,8 +2543,9 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare
} else {
scriptsArray = ctxt->importedScripts.valueRef();
}
+ QV4::ScopedValue v(scope);
for (int ii = 0; ii < scripts.count(); ++ii)
- scriptsArray->putIndexed(ii, *scripts.at(ii)->scriptData()->scriptValueForContext(ctxt).valueRef());
+ scriptsArray->putIndexed(ii, (v = scripts.at(ii)->scriptData()->scriptValueForContext(ctxt)));
if (!hasEngine())
initialize(parentCtxt->engine);
@@ -2516,13 +2553,13 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare
if (!m_program) {
if (shared)
m_loaded = true;
- return QV4::PersistentValue();
+ return QV4::Encode::undefined();
}
- QV4::ScopedValue qmlglobal(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, 0));
- QV4::QmlContextWrapper::takeContextOwnership(qmlglobal);
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, v4->rootContext()->newQmlContext(ctxt, 0));
+ qmlContext->takeContextOwnership();
- m_program->qml.set(scope.engine, qmlglobal);
+ m_program->qmlContext.set(scope.engine, qmlContext);
m_program->run();
if (scope.engine->hasException) {
QQmlError error = scope.engine->catchExceptionAsQmlError();
@@ -2530,13 +2567,13 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare
ep->warning(error);
}
- rv.set(scope.engine, qmlglobal);
+ QV4::ScopedValue retval(scope, qmlContext->d()->qml);
if (shared) {
- m_value = rv;
+ m_value.set(scope.engine, retval);
m_loaded = true;
}
- return rv;
+ return retval->asReturnedValue();
}
void QQmlScriptData::clear()
@@ -2594,7 +2631,7 @@ void QQmlScriptBlob::dataReceived(const Data &data)
return;
}
if (!unit) {
- unit.take(new EmptyCompilationUnit);
+ unit.adopt(new EmptyCompilationUnit);
}
irUnit.javaScriptCompilationUnit = unit;
irUnit.imports = collector.imports;
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index d9ea273698..6433601ba8 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -60,7 +60,7 @@
#include <private/qflagpointer_p.h>
#include <private/qqmlirbuilder_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4script_p.h>
QT_BEGIN_NAMESPACE
@@ -215,7 +215,7 @@ class Q_AUTOTEST_EXPORT QQmlTypeLoader
{
Q_DECLARE_TR_FUNCTIONS(QQmlTypeLoader)
public:
- enum Mode { PreferSynchronous, Asynchronous };
+ enum Mode { PreferSynchronous, Asynchronous, Synchronous };
class Q_QML_PRIVATE_EXPORT Blob : public QQmlDataBlob
{
@@ -283,7 +283,7 @@ public:
QQmlImportDatabase *importDatabase();
QQmlTypeData *getType(const QUrl &url, Mode mode = PreferSynchronous);
- QQmlTypeData *getType(const QByteArray &, const QUrl &url);
+ QQmlTypeData *getType(const QByteArray &, const QUrl &url, Mode mode = PreferSynchronous);
QQmlScriptBlob *getScript(const QUrl &);
QQmlQmldirData *getQmldir(const QUrl &);
@@ -362,6 +362,13 @@ private:
QmldirCache m_qmldirCache;
ImportDirCache m_importDirCache;
ImportQmlDirCache m_importQmlDirCache;
+
+ template<typename Loader>
+ void doLoad(const Loader &loader, QQmlDataBlob *blob, Mode mode);
+
+ friend struct PlainLoader;
+ friend struct CachedLoader;
+ friend struct StaticLoader;
};
class Q_AUTOTEST_EXPORT QQmlTypeData : public QQmlTypeLoader::Blob
@@ -474,7 +481,7 @@ public:
QQmlTypeNameCache *importCache;
QList<QQmlScriptBlob *> scripts;
- QV4::PersistentValue scriptValueForContext(QQmlContextData *parentCtxt);
+ QV4::ReturnedValue scriptValueForContext(QQmlContextData *parentCtxt);
protected:
virtual void clear(); // From QQmlCleanup
diff --git a/src/qml/qml/qqmltypenamecache.cpp b/src/qml/qml/qqmltypenamecache.cpp
index d0658f2c3c..23cc12c895 100644
--- a/src/qml/qml/qqmltypenamecache.cpp
+++ b/src/qml/qml/qqmltypenamecache.cpp
@@ -125,7 +125,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, cons
const Import *i = static_cast<const Import *>(importNamespace);
Q_ASSERT(i->scriptIndex == -1);
- QMap<const Import *, QStringHash<Import> >::const_iterator it = m_namespacedImports.find(i);
+ QMap<const Import *, QStringHash<Import> >::const_iterator it = m_namespacedImports.constFind(i);
if (it != m_namespacedImports.constEnd()) {
Result r = query(*it, name);
if (r.isValid())
diff --git a/src/qml/qml/qqmltypenotavailable_p.h b/src/qml/qml/qqmltypenotavailable_p.h
index f69a4f8732..324e07b80c 100644
--- a/src/qml/qml/qqmltypenotavailable_p.h
+++ b/src/qml/qml/qqmltypenotavailable_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLTYPENOTAVAILABLE_H
#define QQMLTYPENOTAVAILABLE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 8a2118ef27..6c29f2fbb5 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -48,12 +48,8 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlTypeWrapper);
-Heap::QmlTypeWrapper::QmlTypeWrapper(ExecutionEngine *engine)
- : Heap::Object(engine)
- , mode(IncludeEnums)
- , type(Q_NULLPTR)
- , typeNamespace(Q_NULLPTR)
- , importNamespace(Q_NULLPTR)
+Heap::QmlTypeWrapper::QmlTypeWrapper()
+ : mode(IncludeEnums)
{
}
@@ -103,7 +99,7 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q
Q_ASSERT(t);
Scope scope(engine);
- Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->alloc<QmlTypeWrapper>(engine));
+ Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QmlTypeWrapper>());
w->d()->mode = mode; w->d()->object = o; w->d()->type = t;
return w.asReturnedValue();
}
@@ -117,26 +113,26 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q
Q_ASSERT(importNamespace);
Scope scope(engine);
- Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->alloc<QmlTypeWrapper>(engine));
+ Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QmlTypeWrapper>());
w->d()->mode = mode; w->d()->object = o; w->d()->typeNamespace = t; w->d()->importNamespace = importNamespace;
t->addref();
return w.asReturnedValue();
}
-ReturnedValue QmlTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<QmlTypeWrapper>());
- QV4::ExecutionEngine *v4 = static_cast<QmlTypeWrapper *>(m)->engine();
+ QV4::ExecutionEngine *v4 = static_cast<const QmlTypeWrapper *>(m)->engine();
QV4::Scope scope(v4);
- Scoped<QmlTypeWrapper> w(scope, static_cast<QmlTypeWrapper *>(m));
+ Scoped<QmlTypeWrapper> w(scope, static_cast<const QmlTypeWrapper *>(m));
if (hasProperty)
*hasProperty = true;
- QQmlContextData *context = v4->v8Engine->callingContext();
+ QQmlContextData *context = v4->callingQmlContext();
QObject *object = w->d()->object;
@@ -182,14 +178,14 @@ ReturnedValue QmlTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
if (name->startsWithUpper()) {
bool ok = false;
- int value = type->enumValue(name, &ok);
+ int value = type->enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok);
if (ok)
return QV4::Primitive::fromInt32(value).asReturnedValue();
// Fall through to base implementation
} else if (w->d()->object) {
- QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
+ QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(QQmlEnginePrivate::get(v4->qmlEngine())), object);
if (ao)
return QV4::QObjectWrapper::getQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, hasProperty);
@@ -240,12 +236,13 @@ void QmlTypeWrapper::put(Managed *m, String *name, const Value &value)
return;
QV4::Scope scope(v4);
- QQmlContextData *context = v4->v8Engine->callingContext();
+ QQmlContextData *context = v4->callingQmlContext();
QQmlType *type = w->d()->type;
if (type && !type->isSingleton() && w->d()->object) {
QObject *object = w->d()->object;
- QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
+ QQmlEngine *e = scope.engine->qmlEngine();
+ QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(QQmlEnginePrivate::get(e)), object);
if (ao)
QV4::QObjectWrapper::setQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value);
} else if (type && type->isSingleton()) {
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index 660d2836ff..e67b457c59 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -48,7 +48,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qpointer.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
@@ -66,7 +66,7 @@ struct QmlTypeWrapper : Object {
ExcludeEnums
};
- QmlTypeWrapper(QV4::ExecutionEngine *engine);
+ QmlTypeWrapper();
~QmlTypeWrapper();
TypeNameMode mode;
QPointer<QObject> object;
@@ -94,7 +94,7 @@ struct Q_QML_EXPORT QmlTypeWrapper : Object
Heap::QmlTypeWrapper::TypeNameMode = Heap::QmlTypeWrapper::IncludeEnums);
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static PropertyAttributes query(const Managed *, String *name);
static bool isEqualTo(Managed *that, Managed *o);
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 6825e5f004..53b1ffccb5 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -518,7 +518,9 @@ void QQmlEasingValueType::setBezierCurve(const QVariantList &customCurveVariant)
if ((variantList.count() % 6) == 0) {
bool allRealsOk = true;
QList<qreal> reals;
- for (int i = 0; i < variantList.count(); i++) {
+ const int variantListCount = variantList.count();
+ reals.reserve(variantListCount);
+ for (int i = 0; i < variantListCount; i++) {
bool ok;
const qreal real = variantList.at(i).toReal(&ok);
reals.append(real);
diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h
index 2c02cc0aa1..abd73d7f35 100644
--- a/src/qml/qml/qqmlvaluetype_p.h
+++ b/src/qml/qml/qqmlvaluetype_p.h
@@ -209,7 +209,6 @@ struct QQmlEasingValueType
{
QEasingCurve v;
Q_GADGET
- Q_ENUMS(Type)
Q_PROPERTY(QQmlEasingValueType::Type type READ type WRITE setType FINAL)
Q_PROPERTY(qreal amplitude READ amplitude WRITE setAmplitude FINAL)
@@ -243,6 +242,7 @@ public:
SineCurve = QEasingCurve::SineCurve, CosineCurve = QEasingCurve::CosineCurve,
Bezier = QEasingCurve::BezierSpline
};
+ Q_ENUM(Type)
Type type() const;
qreal amplitude() const;
diff --git a/src/qml/qml/qqmlvaluetypeproxybinding.cpp b/src/qml/qml/qqmlvaluetypeproxybinding.cpp
index cfc9b196d2..3bc8493cbb 100644
--- a/src/qml/qml/qqmlvaluetypeproxybinding.cpp
+++ b/src/qml/qml/qqmlvaluetypeproxybinding.cpp
@@ -35,80 +35,42 @@
QT_BEGIN_NAMESPACE
-// Used in qqmlabstractbinding.cpp
-QQmlAbstractBinding::VTable QQmlValueTypeProxyBinding_vtable = {
- QQmlAbstractBinding::default_destroy<QQmlValueTypeProxyBinding>,
- QQmlAbstractBinding::default_expression,
- QQmlValueTypeProxyBinding::propertyIndex,
- QQmlValueTypeProxyBinding::object,
- QQmlValueTypeProxyBinding::setEnabled,
- QQmlValueTypeProxyBinding::update,
- QQmlAbstractBinding::default_retargetBinding
-};
-
QQmlValueTypeProxyBinding::QQmlValueTypeProxyBinding(QObject *o, int index)
-: QQmlAbstractBinding(ValueTypeProxy), m_object(o), m_index(index), m_bindings(0)
+ : QQmlAbstractBinding(),
+ m_bindings(0)
{
+ m_target = o;
+ m_targetIndex = index;
}
QQmlValueTypeProxyBinding::~QQmlValueTypeProxyBinding()
{
- QQmlAbstractBinding *binding = m_bindings;
- // This must be identical to the logic in QQmlData::destroyed()
+ QQmlAbstractBinding *binding = m_bindings.data();
while (binding) {
- QQmlAbstractBinding *next = binding->nextBinding();
binding->setAddedToObject(false);
- binding->setNextBinding(0);
- binding->destroy();
- binding = next;
+ binding = binding->nextBinding();
}
}
-void QQmlValueTypeProxyBinding::setEnabled(QQmlAbstractBinding *_This,
- bool e, QQmlPropertyPrivate::WriteFlags flags)
+void QQmlValueTypeProxyBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags)
{
- QQmlValueTypeProxyBinding *This = static_cast<QQmlValueTypeProxyBinding *>(_This);
-
- if (e) {
- QQmlAbstractBinding *bindings = This->m_bindings;
- This->recursiveEnable(bindings, flags);
- } else {
- QQmlAbstractBinding *bindings = This->m_bindings;
- This->recursiveDisable(bindings);
+ QQmlAbstractBinding *b = m_bindings.data();
+ while (b) {
+ b->setEnabled(e, flags);
+ b = b->nextBinding();
}
}
-void QQmlValueTypeProxyBinding::recursiveEnable(QQmlAbstractBinding *b, QQmlPropertyPrivate::WriteFlags flags)
-{
- if (!b)
- return;
-
- recursiveEnable(b->nextBinding(), flags);
-
- if (b)
- b->setEnabled(true, flags);
-}
-
-void QQmlValueTypeProxyBinding::recursiveDisable(QQmlAbstractBinding *b)
-{
- if (!b)
- return;
-
- recursiveDisable(b->nextBinding());
-
- if (b)
- b->setEnabled(false, 0);
-}
-
-void QQmlValueTypeProxyBinding::update(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags)
+bool QQmlValueTypeProxyBinding::isValueTypeProxy() const
{
+ return true;
}
QQmlAbstractBinding *QQmlValueTypeProxyBinding::binding(int propertyIndex)
{
- QQmlAbstractBinding *binding = m_bindings;
+ QQmlAbstractBinding *binding = m_bindings.data();
- while (binding && binding->propertyIndex() != propertyIndex)
+ while (binding && binding->targetPropertyIndex() != propertyIndex)
binding = binding->nextBinding();
return binding;
@@ -119,23 +81,20 @@ Removes a collection of bindings, corresponding to the set bits in \a mask.
*/
void QQmlValueTypeProxyBinding::removeBindings(quint32 mask)
{
- QQmlAbstractBinding *binding = m_bindings;
+ QQmlAbstractBinding *binding = m_bindings.data();
QQmlAbstractBinding *lastBinding = 0;
while (binding) {
- int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(binding->propertyIndex());
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(binding->targetPropertyIndex());
if (valueTypeIndex != -1 && (mask & (1 << valueTypeIndex))) {
QQmlAbstractBinding *remove = binding;
+ remove->setAddedToObject(false);
binding = remove->nextBinding();
if (lastBinding == 0)
m_bindings = remove->nextBinding();
else
lastBinding->setNextBinding(remove->nextBinding());
-
- remove->setAddedToObject(false);
- remove->setNextBinding(0);
- remove->destroy();
} else {
lastBinding = binding;
binding = binding->nextBinding();
@@ -143,24 +102,4 @@ void QQmlValueTypeProxyBinding::removeBindings(quint32 mask)
}
}
-int QQmlValueTypeProxyBinding::propertyIndex(const QQmlAbstractBinding *This)
-{
- return static_cast<const QQmlValueTypeProxyBinding *>(This)->m_index;
-}
-
-QObject *QQmlValueTypeProxyBinding::object(const QQmlAbstractBinding *This)
-{
- return static_cast<const QQmlValueTypeProxyBinding *>(This)->m_object;
-}
-
-int QQmlValueTypeProxyBinding::propertyIndex() const
-{
- return m_index;
-}
-
-QObject *QQmlValueTypeProxyBinding::object() const
-{
- return m_object;
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlvaluetypeproxybinding_p.h b/src/qml/qml/qqmlvaluetypeproxybinding_p.h
index 873fbb4af1..4afadfc17d 100644
--- a/src/qml/qml/qqmlvaluetypeproxybinding_p.h
+++ b/src/qml/qml/qqmlvaluetypeproxybinding_p.h
@@ -54,30 +54,18 @@ class QQmlValueTypeProxyBinding : public QQmlAbstractBinding
public:
QQmlValueTypeProxyBinding(QObject *o, int coreIndex);
- int propertyIndex() const;
- QObject *object() const;
-
- QQmlAbstractBinding *binding(int propertyIndex);
-
+ QQmlAbstractBinding *binding(int targetPropertyIndex);
void removeBindings(quint32 mask);
- // "Inherited" from QQmlAbstractBinding
- static void setEnabled(QQmlAbstractBinding *, bool, QQmlPropertyPrivate::WriteFlags);
- static void update(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags);
- static int propertyIndex(const QQmlAbstractBinding *);
- static QObject *object(const QQmlAbstractBinding *);
+ virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags);
+ virtual bool isValueTypeProxy() const;
protected:
~QQmlValueTypeProxyBinding();
private:
- void recursiveEnable(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags);
- void recursiveDisable(QQmlAbstractBinding *);
-
friend class QQmlAbstractBinding;
- QObject *m_object;
- int m_index;
- QQmlAbstractBinding *m_bindings;
+ Ptr m_bindings;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index e87d9ede77..8ddf91ef3c 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -43,7 +43,6 @@
#include <private/qv4engine_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4variantobject_p.h>
-#include <private/qv4qmlextensions_p.h>
#include <private/qv4alloca_p.h>
QT_BEGIN_NAMESPACE
@@ -56,7 +55,7 @@ namespace Heap {
struct QQmlValueTypeReference : QQmlValueTypeWrapper
{
- QQmlValueTypeReference(ExecutionEngine *engine);
+ QQmlValueTypeReference() {}
QPointer<QObject> object;
int property;
};
@@ -78,11 +77,6 @@ DEFINE_OBJECT_VTABLE(QV4::QQmlValueTypeReference);
using namespace QV4;
-Heap::QQmlValueTypeWrapper::QQmlValueTypeWrapper(ExecutionEngine *engine)
- : Heap::Object(engine)
-{
-}
-
Heap::QQmlValueTypeWrapper::~QQmlValueTypeWrapper()
{
if (gadgetPtr) {
@@ -108,11 +102,6 @@ QVariant Heap::QQmlValueTypeWrapper::toVariant() const
}
-Heap::QQmlValueTypeReference::QQmlValueTypeReference(ExecutionEngine *engine)
- : Heap::QQmlValueTypeWrapper(engine)
-{
-}
-
bool QQmlValueTypeReference::readReferenceValue() const
{
if (!d()->object)
@@ -165,13 +154,13 @@ bool QQmlValueTypeReference::readReferenceValue() const
void QQmlValueTypeWrapper::initProto(ExecutionEngine *v4)
{
- if (v4->qmlExtensions()->valueTypeWrapperPrototype)
+ if (v4->valueTypeWrapperPrototype()->d())
return;
Scope scope(v4);
ScopedObject o(scope, v4->newObject());
- o->defineDefaultProperty(v4->id_toString, method_toString, 1);
- v4->qmlExtensions()->valueTypeWrapperPrototype = o->d();
+ o->defineDefaultProperty(v4->id_toString(), method_toString, 1);
+ v4->jsObjects[QV4::ExecutionEngine::ValueTypeProto] = o->d();
}
ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *object, int property, const QMetaObject *metaObject, int typeId)
@@ -179,10 +168,9 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj
Scope scope(engine);
initProto(engine);
- Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->alloc<QQmlValueTypeReference>(engine));
- ScopedObject proto(scope, engine->qmlExtensions()->valueTypeWrapperPrototype);
- r->setPrototype(proto);
- r->d()->object = object; r->d()->property = property;
+ Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->allocObject<QQmlValueTypeReference>());
+ r->d()->object = object;
+ r->d()->property = property;
r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject);
r->d()->valueType = QQmlValueTypeFactory::valueType(typeId);
r->d()->gadgetPtr = 0;
@@ -194,9 +182,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVaria
Scope scope(engine);
initProto(engine);
- Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->alloc<QQmlValueTypeWrapper>(engine));
- ScopedObject proto(scope, engine->qmlExtensions()->valueTypeWrapperPrototype);
- r->setPrototype(proto);
+ Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->allocObject<QQmlValueTypeWrapper>());
r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject);
r->d()->valueType = QQmlValueTypeFactory::valueType(typeId);
r->d()->gadgetPtr = 0;
@@ -292,7 +278,7 @@ bool QQmlValueTypeWrapper::write(QObject *target, int propertyIndex) const
ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
{
- Object *o = ctx->thisObject().asObject();
+ Object *o = ctx->thisObject().as<Object>();
if (!o)
return ctx->engine()->throwTypeError();
QQmlValueTypeWrapper *w = o->as<QQmlValueTypeWrapper>();
@@ -327,14 +313,14 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
return Encode(ctx->engine()->newString(result));
}
-ReturnedValue QQmlValueTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<QQmlValueTypeWrapper>());
- QQmlValueTypeWrapper *r = static_cast<QQmlValueTypeWrapper *>(m);
+ const QQmlValueTypeWrapper *r = static_cast<const QQmlValueTypeWrapper *>(m);
QV4::ExecutionEngine *v4 = r->engine();
// Note: readReferenceValue() can change the reference->type.
- if (QQmlValueTypeReference *reference = r->as<QQmlValueTypeReference>()) {
+ if (const QQmlValueTypeReference *reference = r->as<QQmlValueTypeReference>()) {
if (!reference->readReferenceValue())
return Primitive::undefinedValue().asReturnedValue();
}
@@ -346,12 +332,9 @@ ReturnedValue QQmlValueTypeWrapper::get(Managed *m, String *name, bool *hasPrope
if (hasProperty)
*hasProperty = true;
- if (result->isFunction()) {
+ if (result->isFunction())
// calling a Q_INVOKABLE function of a value type
- Scope scope(v4);
- ScopedContext c(scope, v4->rootContext());
- return QV4::QObjectMethod::create(c, r, result->coreIndex);
- }
+ return QV4::QObjectMethod::create(v4->rootContext(), r, result->coreIndex);
#define VALUE_TYPE_LOAD(metatype, cpptype, constructor) \
if (result->propType == metatype) { \
@@ -410,45 +393,41 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
QMetaProperty property = metaObject->property(pd->coreIndex);
Q_ASSERT(property.isValid());
- QQmlBinding *newBinding = 0;
-
- QV4::ScopedFunctionObject f(scope, value);
- if (reference && f) {
- if (!f->isBinding()) {
- // assigning a JS function to a non-var-property is not allowed.
- QString error = QStringLiteral("Cannot assign JavaScript function to value-type property");
- ScopedString e(scope, v4->newString(error));
- v4->throwError(e);
- return;
- }
+ if (reference) {
+ QV4::ScopedFunctionObject f(scope, value);
+ if (f) {
+ if (!f->isBinding()) {
+ // assigning a JS function to a non-var-property is not allowed.
+ QString error = QStringLiteral("Cannot assign JavaScript function to value-type property");
+ ScopedString e(scope, v4->newString(error));
+ v4->throwError(e);
+ return;
+ }
- QQmlContextData *context = QmlContextWrapper::callingContext(v4);
+ QQmlContextData *context = v4->callingQmlContext();
- QQmlPropertyData cacheData;
- cacheData.setFlags(QQmlPropertyData::IsWritable |
- QQmlPropertyData::IsValueTypeVirtual);
- cacheData.propType = writeBackPropertyType;
- cacheData.coreIndex = reference->d()->property;
- cacheData.valueTypeFlags = 0;
- cacheData.valueTypeCoreIndex = pd->coreIndex;
- cacheData.valueTypePropType = property.userType();
+ QQmlPropertyData cacheData;
+ cacheData.setFlags(QQmlPropertyData::IsWritable |
+ QQmlPropertyData::IsValueTypeVirtual);
+ cacheData.propType = writeBackPropertyType;
+ cacheData.coreIndex = reference->d()->property;
+ cacheData.valueTypeFlags = 0;
+ cacheData.valueTypeCoreIndex = pd->coreIndex;
+ cacheData.valueTypePropType = property.userType();
- QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
- bindingFunction->initBindingLocation();
+ QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
+ bindingFunction->initBindingLocation();
- newBinding = new QQmlBinding(value, reference->d()->object, context);
- newBinding->setTarget(reference->d()->object, cacheData, context);
- }
+ QQmlBinding *newBinding = new QQmlBinding(value, reference->d()->object, context);
+ newBinding->setTarget(reference->d()->object, cacheData);
+ QQmlPropertyPrivate::setBinding(newBinding);
+ return;
+ } else {
+ QQmlPropertyPrivate::removeBinding(reference->d()->object, QQmlPropertyData::encodeValueTypePropertyIndex(reference->d()->property, pd->coreIndex));
- if (reference) {
- QQmlAbstractBinding *oldBinding =
- QQmlPropertyPrivate::setBinding(reference->d()->object, reference->d()->property, pd->coreIndex, newBinding);
- if (oldBinding)
- oldBinding->destroy();
+ }
}
- if (newBinding)
- return;
QVariant v = v4->toVariant(value, property.userType());
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index cad48e661c..156b4c85d8 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -48,7 +48,7 @@
#include <QtCore/qglobal.h>
#include <private/qtqmlglobal_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
@@ -61,7 +61,7 @@ namespace QV4 {
namespace Heap {
struct QQmlValueTypeWrapper : Object {
- QQmlValueTypeWrapper(ExecutionEngine *engine);
+ QQmlValueTypeWrapper() {}
~QQmlValueTypeWrapper();
QQmlRefPointer<QQmlPropertyCache> propertyCache;
mutable void *gadgetPtr;
@@ -76,6 +76,7 @@ struct QQmlValueTypeWrapper : Object {
struct Q_QML_EXPORT QQmlValueTypeWrapper : Object
{
V4_OBJECT2(QQmlValueTypeWrapper, Object)
+ V4_PROTOTYPE(valueTypeWrapperPrototype)
static void destroy(Heap::Base *b);
public:
@@ -89,7 +90,7 @@ public:
int typeId() const;
bool write(QObject *target, int propertyIndex) const;
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static bool isEqualTo(Managed *m, Managed *other);
static PropertyAttributes query(const Managed *, String *name);
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 97fc382c33..e85b3dc82c 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 BasysKom GmbH.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -51,8 +52,8 @@
QT_BEGIN_NAMESPACE
-QQmlVMEVariantQObjectPtr::QQmlVMEVariantQObjectPtr(bool isVar)
- : QQmlGuard<QObject>(0), m_target(0), m_isVar(isVar), m_index(-1)
+QQmlVMEVariantQObjectPtr::QQmlVMEVariantQObjectPtr()
+ : QQmlGuard<QObject>(0), m_target(0), m_index(-1)
{
}
@@ -62,20 +63,19 @@ QQmlVMEVariantQObjectPtr::~QQmlVMEVariantQObjectPtr()
void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *)
{
- if (m_target && m_index >= 0) {
- if (m_isVar && m_target->varPropertiesInitialized && !m_target->varProperties.isUndefined()) {
- // Set the var property to NULL
- QV4::ExecutionEngine *v4 = m_target->varProperties.engine();
- if (v4) {
- QV4::Scope scope(v4);
- QV4::ScopedArrayObject a(scope, m_target->varProperties.value());
- if (a)
- a->putIndexed(m_index - m_target->firstVarPropertyIndex, QV4::ScopedValue(scope, QV4::Primitive::nullValue()));
- }
+ if (!m_target || QQmlData::wasDeleted(m_target->object))
+ return;
+
+ if (m_index >= 0) {
+ QV4::ExecutionEngine *v4 = m_target->properties.engine();
+ if (v4) {
+ QV4::Scope scope(v4);
+ QV4::Scoped<QV4::MemberData> sp(scope, m_target->properties.value());
+ if (sp)
+ *(sp->data() + m_index) = QV4::Primitive::nullValue();
}
- if (!QQmlData::wasDeleted(m_target->object))
- m_target->activate(m_target->object, m_target->methodOffset() + m_index, 0);
+ m_target->activate(m_target->object, m_target->methodOffset() + m_index, 0);
}
}
@@ -86,620 +86,509 @@ void QQmlVMEVariantQObjectPtr::setGuardedValue(QObject *obj, QQmlVMEMetaObject *
setObject(obj);
}
-class QQmlVMEVariant
-{
-public:
- inline QQmlVMEVariant();
- inline ~QQmlVMEVariant();
-
- inline const void *dataPtr() const;
- inline void *dataPtr();
- inline int dataType() const;
- inline size_t dataSize() const;
-
- inline QObject *asQObject();
- inline const QVariant &asQVariant();
- inline int asInt();
- inline bool asBool();
- inline double asDouble();
- inline const QString &asQString();
- inline const QUrl &asQUrl();
- inline const QTime &asQTime();
- inline const QDate &asQDate();
- inline const QDateTime &asQDateTime();
- inline const QRectF &asQRectF();
- inline const QPointF &asQPointF();
- inline const QSizeF &asQSizeF();
- inline const QJSValue &asQJSValue();
-
- inline void setValue(QObject *v, QQmlVMEMetaObject *target, int index);
- inline void setValue(const QVariant &);
- inline void setValue(int);
- inline void setValue(bool);
- inline void setValue(double);
- inline void setValue(const QString &);
- inline void setValue(const QUrl &);
- inline void setValue(const QTime &);
- inline void setValue(const QDate &);
- inline void setValue(const QDateTime &);
- inline void setValue(const QRectF &);
- inline void setValue(const QPointF &);
- inline void setValue(const QSizeF &);
- inline void setValue(const QJSValue &);
-
- inline void setDataType(int t);
-
- inline void ensureValueType(int);
-
-private:
- int type;
- void *data[8]; // Large enough to hold all types
-
- inline void cleanup();
-};
-
class QQmlVMEMetaObjectEndpoint : public QQmlNotifierEndpoint
{
public:
QQmlVMEMetaObjectEndpoint();
- static void vmecallback(QQmlNotifierEndpoint *, void **);
void tryConnect();
QFlagPointer<QQmlVMEMetaObject> metaObject;
};
-
-QQmlVMEVariant::QQmlVMEVariant()
-: type(QVariant::Invalid)
-{
-}
-
-QQmlVMEVariant::~QQmlVMEVariant()
-{
- cleanup();
-}
-
-void QQmlVMEVariant::cleanup()
-{
- if (type == QVariant::Invalid) {
- } else if (type == QMetaType::Int ||
- type == QMetaType::Bool ||
- type == QMetaType::Double) {
- type = QVariant::Invalid;
- } else if (type == QMetaType::QObjectStar) {
- ((QQmlVMEVariantQObjectPtr*)dataPtr())->~QQmlVMEVariantQObjectPtr();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QString) {
- ((QString *)dataPtr())->~QString();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QUrl) {
- ((QUrl *)dataPtr())->~QUrl();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QTime) {
- ((QTime *)dataPtr())->~QTime();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QDate) {
- ((QDate *)dataPtr())->~QDate();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QDateTime) {
- ((QDateTime *)dataPtr())->~QDateTime();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QRectF) {
- ((QRectF *)dataPtr())->~QRectF();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QPointF) {
- ((QPointF *)dataPtr())->~QPointF();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QSizeF) {
- ((QSizeF *)dataPtr())->~QSizeF();
- type = QVariant::Invalid;
- } else if (type == qMetaTypeId<QVariant>()) {
- ((QVariant *)dataPtr())->~QVariant();
- type = QVariant::Invalid;
- } else if (type == qMetaTypeId<QJSValue>()) {
- ((QJSValue *)dataPtr())->~QJSValue();
- type = QVariant::Invalid;
- } else {
- if (QQml_valueTypeProvider()->destroyValueType(type, dataPtr(), dataSize())) {
- type = QVariant::Invalid;
- }
- }
-}
-
-int QQmlVMEVariant::dataType() const
+QQmlVMEMetaObjectEndpoint::QQmlVMEMetaObjectEndpoint()
+ : QQmlNotifierEndpoint(QQmlNotifierEndpoint::QQmlVMEMetaObjectEndpoint)
{
- return type;
}
-const void *QQmlVMEVariant::dataPtr() const
+void QQmlVMEMetaObjectEndpoint_callback(QQmlNotifierEndpoint *e, void **)
{
- return &data;
+ QQmlVMEMetaObjectEndpoint *vmee = static_cast<QQmlVMEMetaObjectEndpoint*>(e);
+ vmee->tryConnect();
}
-void *QQmlVMEVariant::dataPtr()
+void QQmlVMEMetaObjectEndpoint::tryConnect()
{
- return &data;
-}
+ int aliasId = this - metaObject->aliasEndpoints;
-size_t QQmlVMEVariant::dataSize() const
-{
- return sizeof(data);
-}
+ if (metaObject.flag()) {
+ // This is actually notify
+ int sigIdx = metaObject->methodOffset() + aliasId + metaObject->metaData->propertyCount;
+ metaObject->activate(metaObject->object, sigIdx, 0);
+ } else {
+ QQmlVMEMetaData::AliasData *d = metaObject->metaData->aliasData() + aliasId;
+ if (!d->isObjectAlias()) {
+ QQmlContextData *ctxt = metaObject->ctxt;
+ QObject *target = ctxt->idValues[d->contextIdx].data();
+ if (!target)
+ return;
-QObject *QQmlVMEVariant::asQObject()
-{
- if (type != QMetaType::QObjectStar)
- setValue((QObject *)0, 0, -1);
+ if (d->notifySignal != -1)
+ connect(target, d->notifySignal, ctxt->engine);
+ }
- return *(QQmlGuard<QObject> *)(dataPtr());
+ metaObject.setFlag();
+ }
}
-const QVariant &QQmlVMEVariant::asQVariant()
-{
- if (type != QMetaType::QVariant)
- setValue(QVariant());
- return *(QVariant *)(dataPtr());
-}
-
-int QQmlVMEVariant::asInt()
+QQmlInterceptorMetaObject::QQmlInterceptorMetaObject(QObject *obj, QQmlPropertyCache *cache)
+ : object(obj),
+ cache(cache),
+ interceptors(0),
+ hasAssignedMetaObjectData(false)
{
- if (type != QMetaType::Int)
- setValue(int(0));
+ QObjectPrivate *op = QObjectPrivate::get(obj);
+
+ if (op->metaObject) {
+ parent = op->metaObject;
+ // Use the extra flag in QBiPointer to know if we can safely cast parent.asT1() to QQmlVMEMetaObject*
+ parent.setFlagValue(QQmlData::get(obj)->hasVMEMetaObject);
+ } else {
+ parent = obj->metaObject();
+ }
- return *(int *)(dataPtr());
+ op->metaObject = this;
+ QQmlData::get(obj)->hasInterceptorMetaObject = true;
}
-bool QQmlVMEVariant::asBool()
+QQmlInterceptorMetaObject::~QQmlInterceptorMetaObject()
{
- if (type != QMetaType::Bool)
- setValue(bool(false));
- return *(bool *)(dataPtr());
}
-double QQmlVMEVariant::asDouble()
+void QQmlInterceptorMetaObject::registerInterceptor(int index, int valueIndex, QQmlPropertyValueInterceptor *interceptor)
{
- if (type != QMetaType::Double)
- setValue(double(0));
-
- return *(double *)(dataPtr());
+ interceptor->m_coreIndex = index;
+ interceptor->m_valueTypeCoreIndex = valueIndex;
+ interceptor->m_next = interceptors;
+ interceptors = interceptor;
}
-const QString &QQmlVMEVariant::asQString()
+int QQmlInterceptorMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void **a)
{
- if (type != QMetaType::QString)
- setValue(QString());
+ Q_ASSERT(o == object);
+ Q_UNUSED(o);
- return *(QString *)(dataPtr());
+ if (intercept(c, id, a))
+ return -1;
+ return object->qt_metacall(c, id, a);
}
-const QUrl &QQmlVMEVariant::asQUrl()
+bool QQmlInterceptorMetaObject::intercept(QMetaObject::Call c, int id, void **a)
{
- if (type != QMetaType::QUrl)
- setValue(QUrl());
+ if (c == QMetaObject::WriteProperty && interceptors &&
+ !(*reinterpret_cast<int*>(a[3]) & QQmlPropertyPrivate::BypassInterceptor)) {
- return *(QUrl *)(dataPtr());
-}
+ for (QQmlPropertyValueInterceptor *vi = interceptors; vi; vi = vi->m_next) {
+ if (vi->m_coreIndex != id)
+ continue;
-const QTime &QQmlVMEVariant::asQTime()
-{
- if (type != QMetaType::QTime)
- setValue(QTime());
+ int valueIndex = vi->m_valueTypeCoreIndex;
+ int type = QQmlData::get(object)->propertyCache->property(id)->propType;
- return *(QTime *)(dataPtr());
-}
+ if (type != QVariant::Invalid) {
+ if (valueIndex != -1) {
+ QQmlValueType *valueType = QQmlValueTypeFactory::valueType(type);
+ Q_ASSERT(valueType);
-const QDate &QQmlVMEVariant::asQDate()
-{
- if (type != QMetaType::QDate)
- setValue(QDate());
+ //
+ // Consider the following case:
+ // color c = { 0.1, 0.2, 0.3 }
+ // interceptor exists on c.r
+ // write { 0.2, 0.4, 0.6 }
+ //
+ // The interceptor may choose not to update the r component at this
+ // point (for example, a behavior that creates an animation). But we
+ // need to ensure that the g and b components are updated correctly.
+ //
+ // So we need to perform a full write where the value type is:
+ // r = old value, g = new value, b = new value
+ //
+ // And then call the interceptor which may or may not write the
+ // new value to the r component.
+ //
+ // This will ensure that the other components don't contain stale data
+ // and any relevant signals are emitted.
+ //
+ // To achieve this:
+ // (1) Store the new value type as a whole (needed due to
+ // aliasing between a[0] and static storage in value type).
+ // (2) Read the entire existing value type from object -> valueType temp.
+ // (3) Read the previous value of the component being changed
+ // from the valueType temp.
+ // (4) Write the entire new value type into the temp.
+ // (5) Overwrite the component being changed with the old value.
+ // (6) Perform a full write to the value type (which may emit signals etc).
+ // (7) Issue the interceptor call with the new component value.
+ //
- return *(QDate *)(dataPtr());
-}
+ QMetaProperty valueProp = valueType->metaObject()->property(valueIndex);
+ QVariant newValue(type, a[0]);
-const QDateTime &QQmlVMEVariant::asQDateTime()
-{
- if (type != QMetaType::QDateTime)
- setValue(QDateTime());
+ valueType->read(object, id);
+ QVariant prevComponentValue = valueProp.read(valueType);
- return *(QDateTime *)(dataPtr());
-}
+ valueType->setValue(newValue);
+ QVariant newComponentValue = valueProp.read(valueType);
-const QRectF &QQmlVMEVariant::asQRectF()
-{
- if (type != QMetaType::QRectF)
- setValue(QRectF());
+ // Don't apply the interceptor if the intercepted value has not changed
+ bool updated = false;
+ if (newComponentValue != prevComponentValue) {
+ valueProp.write(valueType, prevComponentValue);
+ valueType->write(object, id, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
- return *(QRectF *)(dataPtr());
+ vi->write(newComponentValue);
+ updated = true;
+ }
+
+ if (updated)
+ return true;
+ } else {
+ vi->write(QVariant(type, a[0]));
+ return true;
+ }
+ }
+ }
+ }
+ return false;
}
-const QSizeF &QQmlVMEVariant::asQSizeF()
+
+QAbstractDynamicMetaObject *QQmlInterceptorMetaObject::toDynamicMetaObject(QObject *o)
{
- if (type != QMetaType::QSizeF)
- setValue(QSizeF());
+ if (!hasAssignedMetaObjectData) {
+ *static_cast<QMetaObject *>(this) = *cache->createMetaObject();
- return *(QSizeF *)(dataPtr());
-}
+ if (parent.isT1())
+ this->d.superdata = parent.asT1()->toDynamicMetaObject(o);
+ else
+ this->d.superdata = parent.asT2();
-const QPointF &QQmlVMEVariant::asQPointF()
-{
- if (type != QMetaType::QPointF)
- setValue(QPointF());
+ hasAssignedMetaObjectData = true;
+ }
- return *(QPointF *)(dataPtr());
+ return this;
}
-const QJSValue &QQmlVMEVariant::asQJSValue()
+QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
+ QQmlPropertyCache *cache,
+ const QQmlVMEMetaData *meta)
+ : QQmlInterceptorMetaObject(obj, cache),
+ ctxt(QQmlData::get(obj, true)->outerContext), metaData(meta),
+ aliasEndpoints(0),
+ methods(0)
{
- if (type != qMetaTypeId<QJSValue>())
- setValue(QJSValue());
+ cache->addref();
- return *(QJSValue *)(dataPtr());
-}
+ QQmlData::get(obj)->hasVMEMetaObject = true;
-void QQmlVMEVariant::setValue(QObject *v, QQmlVMEMetaObject *target, int index)
-{
- if (type != QMetaType::QObjectStar) {
- cleanup();
- type = QMetaType::QObjectStar;
- new (dataPtr()) QQmlVMEVariantQObjectPtr(false);
- }
- reinterpret_cast<QQmlVMEVariantQObjectPtr*>(dataPtr())->setGuardedValue(v, target, index);
-}
+ int qobject_type = qMetaTypeId<QObject*>();
+ int variant_type = qMetaTypeId<QVariant>();
+ // Need JS wrapper to ensure properties are marked.
+ // ### FIXME: I hope that this can be removed once we have the proper scope chain
+ // set up and the JS wrappers always exist.
+ bool needsJSWrapper = (metaData->propertyCount > 0);
-void QQmlVMEVariant::setValue(const QVariant &v)
-{
- if (type != qMetaTypeId<QVariant>()) {
- cleanup();
- type = qMetaTypeId<QVariant>();
- new (dataPtr()) QVariant(v);
- } else {
- *(QVariant *)(dataPtr()) = v;
+ // ### Optimize
+ for (int ii = 0; ii < metaData->propertyCount; ++ii) {
+ int t = (metaData->propertyData() + ii)->propertyType;
+ if (t == qobject_type || t == variant_type) {
+ needsJSWrapper = true;
+ break;
+ }
}
-}
-void QQmlVMEVariant::setValue(int v)
-{
- if (type != QMetaType::Int) {
- cleanup();
- type = QMetaType::Int;
- }
- *(int *)(dataPtr()) = v;
+ if (needsJSWrapper)
+ ensureQObjectWrapper();
}
-void QQmlVMEVariant::setValue(bool v)
+QQmlVMEMetaObject::~QQmlVMEMetaObject()
{
- if (type != QMetaType::Bool) {
- cleanup();
- type = QMetaType::Bool;
- }
- *(bool *)(dataPtr()) = v;
+ if (parent.isT1()) parent.asT1()->objectDestroyed(object);
+ delete [] aliasEndpoints;
+ delete [] methods;
+
+ qDeleteAll(varObjectGuards);
+
+ cache->release();
}
-void QQmlVMEVariant::setValue(double v)
+QV4::MemberData *QQmlVMEMetaObject::propertiesAsMemberData()
{
- if (type != QMetaType::Double) {
- cleanup();
- type = QMetaType::Double;
+ if (properties.isUndefined()) {
+ if (properties.valueRef())
+ // in some situations, the QObject wrapper (and associated data,
+ // such as the varProperties array) will have been cleaned up, but the
+ // QObject ptr will not yet have been deleted (eg, waiting on deleteLater).
+ // In this situation, return 0.
+ return 0;
+ allocateProperties();
}
- *(double *)(dataPtr()) = v;
+
+ return static_cast<QV4::MemberData*>(properties.asManaged());
}
-void QQmlVMEVariant::setValue(const QString &v)
+void QQmlVMEMetaObject::writeProperty(int id, int v)
{
- if (type != QMetaType::QString) {
- cleanup();
- type = QMetaType::QString;
- new (dataPtr()) QString(v);
- } else {
- *(QString *)(dataPtr()) = v;
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = QV4::Primitive::fromInt32(v);
}
-void QQmlVMEVariant::setValue(const QUrl &v)
+void QQmlVMEMetaObject::writeProperty(int id, bool v)
{
- if (type != QMetaType::QUrl) {
- cleanup();
- type = QMetaType::QUrl;
- new (dataPtr()) QUrl(v);
- } else {
- *(QUrl *)(dataPtr()) = v;
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = QV4::Primitive::fromBoolean(v);
}
-void QQmlVMEVariant::setValue(const QTime &v)
+void QQmlVMEMetaObject::writeProperty(int id, double v)
{
- if (type != QMetaType::QTime) {
- cleanup();
- type = QMetaType::QTime;
- new (dataPtr()) QTime(v);
- } else {
- *(QTime *)(dataPtr()) = v;
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = QV4::Primitive::fromDouble(v);
}
-void QQmlVMEVariant::setValue(const QDate &v)
+void QQmlVMEMetaObject::writeProperty(int id, const QString& v)
{
- if (type != QMetaType::QDate) {
- cleanup();
- type = QMetaType::QDate;
- new (dataPtr()) QDate(v);
- } else {
- *(QDate *)(dataPtr()) = v;
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newString(v);
}
-void QQmlVMEVariant::setValue(const QDateTime &v)
+void QQmlVMEMetaObject::writeProperty(int id, const QUrl& v)
{
- if (type != QMetaType::QDateTime) {
- cleanup();
- type = QMetaType::QDateTime;
- new (dataPtr()) QDateTime(v);
- } else {
- *(QDateTime *)(dataPtr()) = v;
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-void QQmlVMEVariant::setValue(const QRectF &v)
+void QQmlVMEMetaObject::writeProperty(int id, const QDate& v)
{
- if (type != QMetaType::QRectF) {
- cleanup();
- type = QMetaType::QRectF;
- new (dataPtr()) QRectF(v);
- } else {
- *(QRectF *)(dataPtr()) = v;
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-void QQmlVMEVariant::setValue(const QPointF &v)
+void QQmlVMEMetaObject::writeProperty(int id, const QDateTime& v)
{
- if (type != QMetaType::QPointF) {
- cleanup();
- type = QMetaType::QPointF;
- new (dataPtr()) QPointF(v);
- } else {
- *(QPointF *)(dataPtr()) = v;
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-void QQmlVMEVariant::setValue(const QSizeF &v)
+void QQmlVMEMetaObject::writeProperty(int id, const QPointF& v)
{
- if (type != QMetaType::QSizeF) {
- cleanup();
- type = QMetaType::QSizeF;
- new (dataPtr()) QSizeF(v);
- } else {
- *(QSizeF *)(dataPtr()) = v;
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-void QQmlVMEVariant::setValue(const QJSValue &v)
+void QQmlVMEMetaObject::writeProperty(int id, const QSizeF& v)
{
- if (type != qMetaTypeId<QJSValue>()) {
- cleanup();
- type = qMetaTypeId<QJSValue>();
- new (dataPtr()) QJSValue(v);
- } else {
- *(QJSValue *)(dataPtr()) = v;
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-void QQmlVMEVariant::setDataType(int t)
+void QQmlVMEMetaObject::writeProperty(int id, const QRectF& v)
{
- type = t;
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-void QQmlVMEVariant::ensureValueType(int t)
+void QQmlVMEMetaObject::writeProperty(int id, QObject* v)
{
- if (type != t) {
- cleanup();
- type = t;
- QQml_valueTypeProvider()->initValueType(t, dataPtr(), dataSize());
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = QV4::QObjectWrapper::wrap(cache->engine, v);
+
+ QQmlVMEVariantQObjectPtr *guard = getQObjectGuardForProperty(id);
+ if (v && !guard) {
+ guard = new QQmlVMEVariantQObjectPtr();
+ varObjectGuards.append(guard);
}
+ if (guard)
+ guard->setGuardedValue(v, this, id);
}
-QQmlVMEMetaObjectEndpoint::QQmlVMEMetaObjectEndpoint()
+int QQmlVMEMetaObject::readPropertyAsInt(int id)
{
- setCallback(QQmlNotifierEndpoint::QQmlVMEMetaObjectEndpoint);
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return 0;
+
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ if (!sv->isInt32())
+ return 0;
+ return sv->integerValue();
}
-void QQmlVMEMetaObjectEndpoint_callback(QQmlNotifierEndpoint *e, void **)
+bool QQmlVMEMetaObject::readPropertyAsBool(int id)
{
- QQmlVMEMetaObjectEndpoint *vmee = static_cast<QQmlVMEMetaObjectEndpoint*>(e);
- vmee->tryConnect();
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return false;
+
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ if (!sv->isBoolean())
+ return false;
+ return sv->booleanValue();
}
-void QQmlVMEMetaObjectEndpoint::tryConnect()
+double QQmlVMEMetaObject::readPropertyAsDouble(int id)
{
- int aliasId = this - metaObject->aliasEndpoints;
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return 0.0;
- if (metaObject.flag()) {
- // This is actually notify
- int sigIdx = metaObject->methodOffset() + aliasId + metaObject->metaData->propertyCount;
- metaObject->activate(metaObject->object, sigIdx, 0);
- } else {
- QQmlVMEMetaData::AliasData *d = metaObject->metaData->aliasData() + aliasId;
- if (!d->isObjectAlias()) {
- QQmlContextData *ctxt = metaObject->ctxt;
- QObject *target = ctxt->idValues[d->contextIdx].data();
- if (!target)
- return;
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ if (!sv->isDouble())
+ return 0.0;
+ return sv->doubleValue();
+}
- if (d->notifySignal != -1)
- connect(target, d->notifySignal, ctxt->engine);
- }
+QString QQmlVMEMetaObject::readPropertyAsString(int id)
+{
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QString();
- metaObject.setFlag();
- }
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ if (!sv->isString())
+ return QString();
+ return sv->stringValue()->toQString();
}
-QAbstractDynamicMetaObject *QQmlVMEMetaObject::toDynamicMetaObject(QObject *o)
+QUrl QQmlVMEMetaObject::readPropertyAsUrl(int id)
{
- if (!hasAssignedMetaObjectData) {
- *static_cast<QMetaObject *>(this) = *cache->createMetaObject();
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QUrl();
- if (parent.isT1())
- this->d.superdata = parent.asT1()->toDynamicMetaObject(o);
- else
- this->d.superdata = parent.asT2();
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::Url)
+ return QUrl();
+ return v->d()->data.value<QUrl>();
+}
- hasAssignedMetaObjectData = true;
- }
+QDate QQmlVMEMetaObject::readPropertyAsDate(int id)
+{
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QDate();
- return this;
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::Date)
+ return QDate();
+ return v->d()->data.value<QDate>();
}
-QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
- QQmlPropertyCache *cache,
- const QQmlVMEMetaData *meta, QV4::ExecutionContext *qmlBindingContext, QQmlCompiledData *compiledData)
-: object(obj),
- ctxt(QQmlData::get(obj, true)->outerContext), cache(cache), metaData(meta),
- hasAssignedMetaObjectData(false), data(0), aliasEndpoints(0), firstVarPropertyIndex(-1),
- varPropertiesInitialized(false), interceptors(0), v8methods(0)
+QDateTime QQmlVMEMetaObject::readPropertyAsDateTime(int id)
{
- QObjectPrivate *op = QObjectPrivate::get(obj);
-
- if (op->metaObject) {
- parent = op->metaObject;
- // Use the extra flag in QBiPointer to know if we can safely cast parent.asT1() to QQmlVMEMetaObject*
- parent.setFlagValue(QQmlData::get(obj)->hasVMEMetaObject);
- } else
- parent = obj->metaObject();
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QDateTime();
- op->metaObject = this;
- QQmlData::get(obj)->hasVMEMetaObject = true;
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::DateTime)
+ return QDateTime();
+ return v->d()->data.value<QDateTime>();
+}
- data = new QQmlVMEVariant[metaData->propertyCount - metaData->varPropertyCount];
+QSizeF QQmlVMEMetaObject::readPropertyAsSizeF(int id)
+{
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QSizeF();
- aConnected.resize(metaData->aliasCount);
- int list_type = qMetaTypeId<QQmlListProperty<QObject> >();
- int qobject_type = qMetaTypeId<QObject*>();
- int variant_type = qMetaTypeId<QVariant>();
- // Need JS wrapper to ensure variant and var properties are marked.
- // ### FIXME: I hope that this can be removed once we have the proper scope chain
- // set up and the JS wrappers always exist.
- bool needsJSWrapper = (metaData->varPropertyCount > 0);
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::SizeF)
+ return QSizeF();
+ return v->d()->data.value<QSizeF>();
+}
- // ### Optimize
- for (int ii = 0; ii < metaData->propertyCount - metaData->varPropertyCount; ++ii) {
- int t = (metaData->propertyData() + ii)->propertyType;
- if (t == list_type) {
- listProperties.append(List(methodOffset() + ii, this));
- data[ii].setValue(listProperties.count() - 1);
- } else if (!needsJSWrapper && (t == qobject_type || t == variant_type)) {
- needsJSWrapper = true;
- }
- }
+QPointF QQmlVMEMetaObject::readPropertyAsPointF(int id)
+{
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QPointF();
- firstVarPropertyIndex = metaData->propertyCount - metaData->varPropertyCount;
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::PointF)
+ return QPointF();
+ return v->d()->data.value<QPointF>();
+}
- if (needsJSWrapper)
- ensureQObjectWrapper();
+QObject* QQmlVMEMetaObject::readPropertyAsQObject(int id)
+{
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return 0;
- if (qmlBindingContext && metaData->methodCount) {
- v8methods = new QV4::PersistentValue[metaData->methodCount];
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::QObjectWrapper *wrapper = sv->as<QV4::QObjectWrapper>();
+ if (!wrapper)
+ return 0;
+ return wrapper->object();
+}
- QV4::CompiledData::CompilationUnit *compilationUnit = compiledData->compilationUnit;
- QV4::Scope scope(QQmlEnginePrivate::get(ctxt->engine)->v4engine());
- QV4::ScopedObject o(scope);
- for (int index = 0; index < metaData->methodCount; ++index) {
- QQmlVMEMetaData::MethodData *data = metaData->methodData() + index;
+QList<QObject *> *QQmlVMEMetaObject::readPropertyAsList(int id)
+{
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return 0;
- QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[data->runtimeFunctionIndex];
- o = QV4::FunctionObject::createScriptFunction(qmlBindingContext, runtimeFunction);
- v8methods[index].set(qmlBindingContext->engine(), o);
- }
+ QV4::Scope scope(cache->engine);
+ QV4::Scoped<QV4::VariantObject> v(scope, *(md->data() + id));
+ if (!v || (int)v->d()->data.userType() != qMetaTypeId<QList<QObject *> >()) {
+ QVariant variant(qVariantFromValue(QList<QObject*>()));
+ v = cache->engine->newVariantObject(variant);
+ *(md->data() + id) = v;
}
+ return static_cast<QList<QObject *> *>(v->d()->data.data());
}
-QQmlVMEMetaObject::~QQmlVMEMetaObject()
+QRectF QQmlVMEMetaObject::readPropertyAsRectF(int id)
{
- if (parent.isT1()) parent.asT1()->objectDestroyed(object);
- delete [] data;
- delete [] aliasEndpoints;
- delete [] v8methods;
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QRectF();
- qDeleteAll(varObjectGuards);
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::RectF)
+ return QRectF();
+ return v->d()->data.value<QRectF>();
}
-int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
+int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void **a)
{
- int id = _id;
- if (c == QMetaObject::WriteProperty && interceptors &&
- !(*reinterpret_cast<int*>(a[3]) & QQmlPropertyPrivate::BypassInterceptor)) {
+ Q_ASSERT(o == object);
+ Q_UNUSED(o);
- for (QQmlPropertyValueInterceptor *vi = interceptors; vi; vi = vi->m_next) {
- if (vi->m_coreIndex != id)
- continue;
-
- int valueIndex = vi->m_valueTypeCoreIndex;
- int type = QQmlData::get(object)->propertyCache->property(id)->propType;
-
- if (type != QVariant::Invalid) {
- if (valueIndex != -1) {
- QQmlValueType *valueType = QQmlValueTypeFactory::valueType(type);
- Q_ASSERT(valueType);
-
- //
- // Consider the following case:
- // color c = { 0.1, 0.2, 0.3 }
- // interceptor exists on c.r
- // write { 0.2, 0.4, 0.6 }
- //
- // The interceptor may choose not to update the r component at this
- // point (for example, a behavior that creates an animation). But we
- // need to ensure that the g and b components are updated correctly.
- //
- // So we need to perform a full write where the value type is:
- // r = old value, g = new value, b = new value
- //
- // And then call the interceptor which may or may not write the
- // new value to the r component.
- //
- // This will ensure that the other components don't contain stale data
- // and any relevant signals are emitted.
- //
- // To achieve this:
- // (1) Store the new value type as a whole (needed due to
- // aliasing between a[0] and static storage in value type).
- // (2) Read the entire existing value type from object -> valueType temp.
- // (3) Read the previous value of the component being changed
- // from the valueType temp.
- // (4) Write the entire new value type into the temp.
- // (5) Overwrite the component being changed with the old value.
- // (6) Perform a full write to the value type (which may emit signals etc).
- // (7) Issue the interceptor call with the new component value.
- //
-
- QMetaProperty valueProp = valueType->metaObject()->property(valueIndex);
- QVariant newValue(type, a[0]);
-
- valueType->read(object, id);
- QVariant prevComponentValue = valueProp.read(valueType);
-
- valueType->setValue(newValue);
- QVariant newComponentValue = valueProp.read(valueType);
+ int id = _id;
- // Don't apply the interceptor if the intercepted value has not changed
- bool updated = false;
- if (newComponentValue != prevComponentValue) {
- valueProp.write(valueType, prevComponentValue);
- valueType->write(object, id, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
+ if (intercept(c, _id, a))
+ return -1;
- vi->write(newComponentValue);
- updated = true;
- }
-
- if (updated)
- return -1;
- } else {
- vi->write(QVariant(type, a[0]));
- return -1;
- }
- }
- }
- }
if (c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty || c == QMetaObject::ResetProperty) {
if (id >= propOffset()) {
id -= propOffset();
@@ -708,8 +597,7 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
int t = (metaData->propertyData() + id)->propertyType;
bool needActivate = false;
- if (id >= firstVarPropertyIndex) {
- Q_ASSERT(t == QMetaType::QVariant);
+ if (t == QQmlVMEMetaData::VarPropertyType) {
// the context can be null if accessing var properties from cpp after re-parenting an item.
QQmlEnginePrivate *ep = (ctxt == 0 || ctxt->engine == 0) ? 0 : QQmlEnginePrivate::get(ctxt->engine);
QV8Engine *v8e = (ep == 0) ? 0 : ep->v8engine();
@@ -729,110 +617,128 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
if (c == QMetaObject::ReadProperty) {
switch(t) {
case QVariant::Int:
- *reinterpret_cast<int *>(a[0]) = data[id].asInt();
+ *reinterpret_cast<int *>(a[0]) = readPropertyAsInt(id);
break;
case QVariant::Bool:
- *reinterpret_cast<bool *>(a[0]) = data[id].asBool();
+ *reinterpret_cast<bool *>(a[0]) = readPropertyAsBool(id);
break;
case QVariant::Double:
- *reinterpret_cast<double *>(a[0]) = data[id].asDouble();
+ *reinterpret_cast<double *>(a[0]) = readPropertyAsDouble(id);
break;
case QVariant::String:
- *reinterpret_cast<QString *>(a[0]) = data[id].asQString();
+ *reinterpret_cast<QString *>(a[0]) = readPropertyAsString(id);
break;
case QVariant::Url:
- *reinterpret_cast<QUrl *>(a[0]) = data[id].asQUrl();
+ *reinterpret_cast<QUrl *>(a[0]) = readPropertyAsUrl(id);
break;
case QVariant::Date:
- *reinterpret_cast<QDate *>(a[0]) = data[id].asQDate();
+ *reinterpret_cast<QDate *>(a[0]) = readPropertyAsDate(id);
break;
case QVariant::DateTime:
- *reinterpret_cast<QDateTime *>(a[0]) = data[id].asQDateTime();
+ *reinterpret_cast<QDateTime *>(a[0]) = readPropertyAsDateTime(id);
break;
case QVariant::RectF:
- *reinterpret_cast<QRectF *>(a[0]) = data[id].asQRectF();
+ *reinterpret_cast<QRectF *>(a[0]) = readPropertyAsRectF(id);
break;
case QVariant::SizeF:
- *reinterpret_cast<QSizeF *>(a[0]) = data[id].asQSizeF();
+ *reinterpret_cast<QSizeF *>(a[0]) = readPropertyAsSizeF(id);
break;
case QVariant::PointF:
- *reinterpret_cast<QPointF *>(a[0]) = data[id].asQPointF();
+ *reinterpret_cast<QPointF *>(a[0]) = readPropertyAsPointF(id);
break;
case QMetaType::QObjectStar:
- *reinterpret_cast<QObject **>(a[0]) = data[id].asQObject();
+ *reinterpret_cast<QObject **>(a[0]) = readPropertyAsQObject(id);
break;
case QMetaType::QVariant:
*reinterpret_cast<QVariant *>(a[0]) = readPropertyAsVariant(id);
break;
default:
- QQml_valueTypeProvider()->readValueType(data[id].dataType(), data[id].dataPtr(), data->dataSize(), t, a[0]);
+ {
+ if (t == qMetaTypeId<QQmlListProperty<QObject> >()) {
+ QList<QObject *> *list = readPropertyAsList(id);
+ QQmlListProperty<QObject> *p = static_cast<QQmlListProperty<QObject> *>(a[0]);
+ *p = QQmlListProperty<QObject>(object, list,
+ list_append, list_count, list_at,
+ list_clear);
+ p->dummy1 = this;
+ p->dummy2 = reinterpret_cast<void *>(quintptr(methodOffset() + id));
+ } else {
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md) {
+ QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
+ if (v)
+ QQml_valueTypeProvider()->readValueType(v->d()->data, a[0], t);
+ }
+ }
break;
}
- if (t == qMetaTypeId<QQmlListProperty<QObject> >()) {
- int listIndex = data[id].asInt();
- const List *list = &listProperties.at(listIndex);
- *reinterpret_cast<QQmlListProperty<QObject> *>(a[0]) =
- QQmlListProperty<QObject>(object, const_cast<List *>(list),
- list_append, list_count, list_at,
- list_clear);
}
} else if (c == QMetaObject::WriteProperty) {
switch(t) {
case QVariant::Int:
- needActivate = *reinterpret_cast<int *>(a[0]) != data[id].asInt();
- data[id].setValue(*reinterpret_cast<int *>(a[0]));
+ needActivate = *reinterpret_cast<int *>(a[0]) != readPropertyAsInt(id);
+ writeProperty(id, *reinterpret_cast<int *>(a[0]));
break;
case QVariant::Bool:
- needActivate = *reinterpret_cast<bool *>(a[0]) != data[id].asBool();
- data[id].setValue(*reinterpret_cast<bool *>(a[0]));
+ needActivate = *reinterpret_cast<bool *>(a[0]) != readPropertyAsBool(id);
+ writeProperty(id, *reinterpret_cast<bool *>(a[0]));
break;
case QVariant::Double:
- needActivate = *reinterpret_cast<double *>(a[0]) != data[id].asDouble();
- data[id].setValue(*reinterpret_cast<double *>(a[0]));
+ needActivate = *reinterpret_cast<double *>(a[0]) != readPropertyAsDouble(id);
+ writeProperty(id, *reinterpret_cast<double *>(a[0]));
break;
case QVariant::String:
- needActivate = *reinterpret_cast<QString *>(a[0]) != data[id].asQString();
- data[id].setValue(*reinterpret_cast<QString *>(a[0]));
+ needActivate = *reinterpret_cast<QString *>(a[0]) != readPropertyAsString(id);
+ writeProperty(id, *reinterpret_cast<QString *>(a[0]));
break;
case QVariant::Url:
- needActivate = *reinterpret_cast<QUrl *>(a[0]) != data[id].asQUrl();
- data[id].setValue(*reinterpret_cast<QUrl *>(a[0]));
+ needActivate = *reinterpret_cast<QUrl *>(a[0]) != readPropertyAsUrl(id);
+ writeProperty(id, *reinterpret_cast<QUrl *>(a[0]));
break;
case QVariant::Date:
- needActivate = *reinterpret_cast<QDate *>(a[0]) != data[id].asQDate();
- data[id].setValue(*reinterpret_cast<QDate *>(a[0]));
+ needActivate = *reinterpret_cast<QDate *>(a[0]) != readPropertyAsDate(id);
+ writeProperty(id, *reinterpret_cast<QDate *>(a[0]));
break;
case QVariant::DateTime:
- needActivate = *reinterpret_cast<QDateTime *>(a[0]) != data[id].asQDateTime();
- data[id].setValue(*reinterpret_cast<QDateTime *>(a[0]));
+ needActivate = *reinterpret_cast<QDateTime *>(a[0]) != readPropertyAsDateTime(id);
+ writeProperty(id, *reinterpret_cast<QDateTime *>(a[0]));
break;
case QVariant::RectF:
- needActivate = *reinterpret_cast<QRectF *>(a[0]) != data[id].asQRectF();
- data[id].setValue(*reinterpret_cast<QRectF *>(a[0]));
+ needActivate = *reinterpret_cast<QRectF *>(a[0]) != readPropertyAsRectF(id);
+ writeProperty(id, *reinterpret_cast<QRectF *>(a[0]));
break;
case QVariant::SizeF:
- needActivate = *reinterpret_cast<QSizeF *>(a[0]) != data[id].asQSizeF();
- data[id].setValue(*reinterpret_cast<QSizeF *>(a[0]));
+ needActivate = *reinterpret_cast<QSizeF *>(a[0]) != readPropertyAsSizeF(id);
+ writeProperty(id, *reinterpret_cast<QSizeF *>(a[0]));
break;
case QVariant::PointF:
- needActivate = *reinterpret_cast<QPointF *>(a[0]) != data[id].asQPointF();
- data[id].setValue(*reinterpret_cast<QPointF *>(a[0]));
+ needActivate = *reinterpret_cast<QPointF *>(a[0]) != readPropertyAsPointF(id);
+ writeProperty(id, *reinterpret_cast<QPointF *>(a[0]));
break;
case QMetaType::QObjectStar:
- needActivate = *reinterpret_cast<QObject **>(a[0]) != data[id].asQObject();
- data[id].setValue(*reinterpret_cast<QObject **>(a[0]), this, id);
+ needActivate = *reinterpret_cast<QObject **>(a[0]) != readPropertyAsQObject(id);
+ writeProperty(id, *reinterpret_cast<QObject **>(a[0]));
break;
case QMetaType::QVariant:
writeProperty(id, *reinterpret_cast<QVariant *>(a[0]));
break;
- default:
- data[id].ensureValueType(t);
- needActivate = !QQml_valueTypeProvider()->equalValueType(t, a[0], data[id].dataPtr(), data[id].dataSize());
- QQml_valueTypeProvider()->writeValueType(t, a[0], data[id].dataPtr(), data[id].dataSize());
+ default: {
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md) {
+ QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
+ if (!v) {
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant());
+ v = (md->data() + id)->as<QV4::VariantObject>();
+ QQml_valueTypeProvider()->initValueType(t, v->d()->data);
+ }
+ needActivate = !QQml_valueTypeProvider()->equalValueType(t, a[0], v->d()->data);
+ QQml_valueTypeProvider()->writeValueType(t, a[0], v->d()->data);
+ }
break;
}
+ }
}
}
@@ -874,10 +780,8 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
int flags = *reinterpret_cast<int*>(a[3]);
if (flags & QQmlPropertyPrivate::RemoveBindingOnAliasWrite) {
QQmlData *targetData = QQmlData::get(target);
- if (targetData && targetData->hasBindingBit(d->propertyIndex())) {
- QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(target, d->propertyIndex(), d->isValueTypeAlias()?d->valueTypeIndex():-1, 0);
- if (binding) binding->destroy();
- }
+ if (targetData && targetData->hasBindingBit(d->propertyIndex()))
+ QQmlPropertyPrivate::removeBinding(target, d->propertyIdx);
}
}
@@ -975,129 +879,125 @@ QV4::ReturnedValue QQmlVMEMetaObject::method(int index)
{
if (!ctxt || !ctxt->isValid()) {
qWarning("QQmlVMEMetaObject: Internal error - attempted to evaluate a function in an invalid context");
- return QV4::Primitive::undefinedValue().asReturnedValue();
+ return QV4::Encode::undefined();
}
- if (!v8methods)
- v8methods = new QV4::PersistentValue[metaData->methodCount];
+ if (!methods)
+ return QV4::Encode::undefined();
- return v8methods[index].value();
+ return methods[index].value();
}
QV4::ReturnedValue QQmlVMEMetaObject::readVarProperty(int id)
{
- Q_ASSERT(id >= firstVarPropertyIndex);
+ Q_ASSERT((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType);
- if (ensureVarPropertiesAllocated()) {
- QV4::Scope scope(varProperties.engine());
- QV4::ScopedObject o(scope, varProperties.value());
- return o->getIndexed(id - firstVarPropertyIndex);
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ return (md->data() + id)->asReturnedValue();
return QV4::Primitive::undefinedValue().asReturnedValue();
}
QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id)
{
- if (id >= firstVarPropertyIndex) {
- if (ensureVarPropertiesAllocated()) {
- QV4::ExecutionEngine *v4 = varProperties.engine();
- QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, varProperties.value());
- QV4::ScopedValue val(scope, o->getIndexed(id - firstVarPropertyIndex));
- return scope.engine->toVariant(val, -1);
- }
- return QVariant();
- } else {
- if (data[id].dataType() == QMetaType::QObjectStar) {
- return QVariant::fromValue(data[id].asQObject());
- } else {
- return data[id].asQVariant();
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md) {
+ const QV4::QObjectWrapper *wrapper = (md->data() + id)->as<QV4::QObjectWrapper>();
+ if (wrapper)
+ return QVariant::fromValue(wrapper->object());
+ const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
+ if (v)
+ return v->d()->data;
+ return cache->engine->toVariant(*(md->data() + id), -1);
}
+ return QVariant();
}
void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value)
{
- Q_ASSERT(id >= firstVarPropertyIndex);
- if (!ensureVarPropertiesAllocated())
+ Q_ASSERT((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType);
+
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
return;
- QV4::Scope scope(varProperties.engine());
// Importantly, if the current value is a scarce resource, we need to ensure that it
// gets automatically released by the engine if no other references to it exist.
- QV4::ScopedObject vp(scope, varProperties.value());
- QV4::Scoped<QV4::VariantObject> oldv(scope, vp->getIndexed(id - firstVarPropertyIndex));
- if (!!oldv)
- oldv->removeVmePropertyReference();
+ QV4::VariantObject *oldVariant = (md->data() + id)->as<QV4::VariantObject>();
+ if (oldVariant)
+ oldVariant->removeVmePropertyReference();
QObject *valueObject = 0;
QQmlVMEVariantQObjectPtr *guard = getQObjectGuardForProperty(id);
- QV4::ScopedObject o(scope, value);
- if (o) {
- // And, if the new value is a scarce resource, we need to ensure that it does not get
- // automatically released by the engine until no other references to it exist.
- if (QV4::VariantObject *v = o->as<QV4::VariantObject>()) {
- v->addVmePropertyReference();
- } else if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) {
- // We need to track this QObject to signal its deletion
- valueObject = wrapper->object();
-
- // Do we already have a QObject guard for this property?
- if (valueObject && !guard) {
- guard = new QQmlVMEVariantQObjectPtr(true);
- varObjectGuards.append(guard);
- }
+ // And, if the new value is a scarce resource, we need to ensure that it does not get
+ // automatically released by the engine until no other references to it exist.
+ if (QV4::VariantObject *v = const_cast<QV4::VariantObject*>(value.as<QV4::VariantObject>())) {
+ v->addVmePropertyReference();
+ } else if (QV4::QObjectWrapper *wrapper = const_cast<QV4::QObjectWrapper*>(value.as<QV4::QObjectWrapper>())) {
+ // We need to track this QObject to signal its deletion
+ valueObject = wrapper->object();
+
+ // Do we already have a QObject guard for this property?
+ if (valueObject && !guard) {
+ guard = new QQmlVMEVariantQObjectPtr();
+ varObjectGuards.append(guard);
}
}
- if (guard) {
+ if (guard)
guard->setGuardedValue(valueObject, this, id);
- }
// Write the value and emit change signal as appropriate.
- vp->putIndexed(id - firstVarPropertyIndex, value);
+ *(md->data() + id) = value;
activate(object, methodOffset() + id, 0);
}
void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
{
- if (id >= firstVarPropertyIndex) {
- if (!ensureVarPropertiesAllocated())
+ if ((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType) {
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
return;
- QV4::Scope scope(varProperties.engine());
-
// Importantly, if the current value is a scarce resource, we need to ensure that it
// gets automatically released by the engine if no other references to it exist.
- QV4::ScopedObject vp(scope, varProperties.value());
- QV4::Scoped<QV4::VariantObject> oldv(scope, vp->getIndexed(id - firstVarPropertyIndex));
- if (!!oldv)
+ QV4::VariantObject *oldv = (md->data() + id)->as<QV4::VariantObject>();
+ if (oldv)
oldv->removeVmePropertyReference();
// And, if the new value is a scarce resource, we need to ensure that it does not get
// automatically released by the engine until no other references to it exist.
- QV4::ScopedValue newv(scope, scope.engine->fromVariant(value));
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue newv(scope, cache->engine->fromVariant(value));
QV4::Scoped<QV4::VariantObject> v(scope, newv);
if (!!v)
v->addVmePropertyReference();
// Write the value and emit change signal as appropriate.
QVariant currentValue = readPropertyAsVariant(id);
- vp->putIndexed(id - firstVarPropertyIndex, newv);
+ *(md->data() + id) = newv;
if ((currentValue.userType() != value.userType() || currentValue != value))
activate(object, methodOffset() + id, 0);
} else {
bool needActivate = false;
if (value.userType() == QMetaType::QObjectStar) {
QObject *o = *(QObject *const *)value.data();
- needActivate = (data[id].dataType() != QMetaType::QObjectStar || data[id].asQObject() != o);
- data[id].setValue(o, this, id);
+ needActivate = readPropertyAsQObject(id) != o; // TODO: still correct?
+ writeProperty(id, o);
} else {
- needActivate = (data[id].dataType() != qMetaTypeId<QVariant>() ||
- data[id].asQVariant().userType() != value.userType() ||
- data[id].asQVariant() != value);
- data[id].setValue(value);
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md) {
+ QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
+ needActivate = (!v ||
+ v->d()->data.userType() != value.userType() ||
+ v->d()->data != value);
+ if (v)
+ v->removeVmePropertyReference();
+ *(md->data() + id) = cache->engine->newVariantObject(value);
+ v = static_cast<QV4::VariantObject *>(md->data() + id);
+ v->addVmePropertyReference();
+ }
}
if (needActivate)
@@ -1112,34 +1012,28 @@ void QQmlVMEMetaObject::listChanged(int id)
void QQmlVMEMetaObject::list_append(QQmlListProperty<QObject> *prop, QObject *o)
{
- List *list = static_cast<List *>(prop->data);
+ QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data);
list->append(o);
- list->mo->activate(prop->object, list->notifyIndex, 0);
+ static_cast<QQmlVMEMetaObject *>(prop->dummy1)->activate(prop->object, reinterpret_cast<quintptr>(prop->dummy2), 0);
}
int QQmlVMEMetaObject::list_count(QQmlListProperty<QObject> *prop)
{
- return static_cast<List *>(prop->data)->count();
+ QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data);
+ return list->count();
}
QObject *QQmlVMEMetaObject::list_at(QQmlListProperty<QObject> *prop, int index)
{
- return static_cast<List *>(prop->data)->at(index);
+ QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data);
+ return list->at(index);
}
void QQmlVMEMetaObject::list_clear(QQmlListProperty<QObject> *prop)
{
- List *list = static_cast<List *>(prop->data);
+ QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data);
list->clear();
- list->mo->activate(prop->object, list->notifyIndex, 0);
-}
-
-void QQmlVMEMetaObject::registerInterceptor(int index, int valueIndex, QQmlPropertyValueInterceptor *interceptor)
-{
- interceptor->m_coreIndex = index;
- interceptor->m_valueTypeCoreIndex = valueIndex;
- interceptor->m_next = interceptors;
- interceptors = interceptor;
+ static_cast<QQmlVMEMetaObject *>(prop->dummy1)->activate(prop->object, reinterpret_cast<quintptr>(prop->dummy2), 0);
}
quint16 QQmlVMEMetaObject::vmeMethodLineNumber(int index)
@@ -1179,11 +1073,11 @@ void QQmlVMEMetaObject::setVmeMethod(int index, const QV4::Value &function)
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
- if (!v8methods)
- v8methods = new QV4::PersistentValue[metaData->methodCount];
+ if (!methods)
+ methods = new QV4::PersistentValue[metaData->methodCount];
int methodIndex = index - methodOffset() - plainSignals;
- v8methods[methodIndex].set(function.asObject()->engine(), function);
+ methods[methodIndex].set(function.as<QV4::Object>()->engine(), function);
}
QV4::ReturnedValue QQmlVMEMetaObject::vmeProperty(int index)
@@ -1205,57 +1099,34 @@ void QQmlVMEMetaObject::setVMEProperty(int index, const QV4::Value &v)
return writeVarProperty(index - propOffset(), v);
}
-bool QQmlVMEMetaObject::ensureVarPropertiesAllocated()
-{
- if (!varPropertiesInitialized)
- allocateVarPropertiesArray();
-
- // in some situations, the QObject's v8object (and associated v8 data,
- // such as the varProperties array) will have been cleaned up, but the
- // QObject ptr will not yet have been deleted (eg, waiting on deleteLater).
- // In this situation, the varProperties handle will be (and should remain)
- // empty.
- return !varProperties.isUndefined();
-}
-
void QQmlVMEMetaObject::ensureQObjectWrapper()
{
- QQmlEnginePrivate *ep = (ctxt == 0 || ctxt->engine == 0) ? 0 : QQmlEnginePrivate::get(ctxt->engine);
- QV4::ExecutionEngine *v4 = (ep == 0) ? 0 : ep->v4engine();
+ Q_ASSERT(cache && cache->engine);
+ QV4::ExecutionEngine *v4 = cache->engine;
QV4::QObjectWrapper::wrap(v4, object);
}
void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e)
{
- QQmlEnginePrivate *ep = (ctxt == 0 || ctxt->engine == 0) ? 0 : QQmlEnginePrivate::get(ctxt->engine);
- QV4::ExecutionEngine *v4 = (ep == 0) ? 0 : ep->v4engine();
+ QV4::ExecutionEngine *v4 = cache ? cache->engine : 0;
if (v4 != e)
return;
- varProperties.markOnce(e);
-
- // add references created by VMEVariant properties
- int maxDataIdx = metaData->propertyCount - metaData->varPropertyCount;
- for (int ii = 0; ii < maxDataIdx; ++ii) { // XXX TODO: optimize?
- if (data[ii].dataType() == QMetaType::QObjectStar) {
- // possible QObject reference.
- if (QObject *ref = data[ii].asQObject())
- QV4::QObjectWrapper::markWrapper(ref, e);
- }
- }
+ properties.markOnce(e);
if (QQmlVMEMetaObject *parent = parentVMEMetaObject())
parent->mark(e);
}
-void QQmlVMEMetaObject::allocateVarPropertiesArray()
+void QQmlVMEMetaObject::allocateProperties()
{
- QQmlEngine *qml = qmlEngine(object);
- assert(qml);
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(qml->handle());
- QV4::Scope scope(v4);
- varProperties.set(scope.engine, v4->newArrayObject(metaData->varPropertyCount));
- varPropertiesInitialized = true;
+ Q_ASSERT(cache && cache->engine);
+ Q_ASSERT(!properties.valueRef());
+ QV4::ExecutionEngine *v4 = cache->engine;
+ QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, metaData->propertyCount);
+ properties.set(v4, data);
+ for (uint i = 0; i < data->size; ++i)
+ data->data[i] = QV4::Encode::undefined();
}
bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const
@@ -1290,22 +1161,21 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex,
void QQmlVMEMetaObject::connectAlias(int aliasId)
{
- if (!aConnected.testBit(aliasId)) {
-
- if (!aliasEndpoints)
- aliasEndpoints = new QQmlVMEMetaObjectEndpoint[metaData->aliasCount];
+ if (!aliasEndpoints)
+ aliasEndpoints = new QQmlVMEMetaObjectEndpoint[metaData->aliasCount];
- aConnected.setBit(aliasId);
+ QQmlVMEMetaData::AliasData *d = metaData->aliasData() + aliasId;
- QQmlVMEMetaData::AliasData *d = metaData->aliasData() + aliasId;
-
- QQmlVMEMetaObjectEndpoint *endpoint = aliasEndpoints + aliasId;
- endpoint->metaObject = this;
-
- endpoint->connect(&ctxt->idValues[d->contextIdx].bindings);
-
- endpoint->tryConnect();
+ QQmlVMEMetaObjectEndpoint *endpoint = aliasEndpoints + aliasId;
+ if (endpoint->metaObject.data()) {
+ // already connected
+ Q_ASSERT(endpoint->metaObject.data() == this);
+ return;
}
+
+ endpoint->metaObject = this;
+ endpoint->connect(&ctxt->idValues[d->contextIdx].bindings);
+ endpoint->tryConnect();
}
void QQmlVMEMetaObject::connectAliasSignal(int index, bool indexInSignalRange)
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index f3048d426a..7da44e3b82 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 BasysKom GmbH.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -63,7 +64,7 @@
#include <private/qv8engine_p.h>
#include <private/qflagpointer_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
QT_BEGIN_NAMESPACE
@@ -71,13 +72,11 @@ QT_BEGIN_NAMESPACE
struct QQmlVMEMetaData
{
- short varPropertyCount;
short propertyCount;
short aliasCount;
short signalCount;
short methodCount;
- short dummyForAlignment; // Add padding to ensure that the following
- // AliasData/PropertyData/MethodData is int aligned.
+ // Make sure this structure is always aligned to int
struct AliasData {
int contextIdx;
@@ -108,6 +107,10 @@ struct QQmlVMEMetaData
}
};
+ enum {
+ VarPropertyType = -1
+ };
+
struct PropertyData {
int propertyType;
};
@@ -135,29 +138,67 @@ class QQmlVMEMetaObject;
class QQmlVMEVariantQObjectPtr : public QQmlGuard<QObject>
{
public:
- inline QQmlVMEVariantQObjectPtr(bool isVar);
+ inline QQmlVMEVariantQObjectPtr();
inline ~QQmlVMEVariantQObjectPtr();
inline void objectDestroyed(QObject *);
inline void setGuardedValue(QObject *obj, QQmlVMEMetaObject *target, int index);
QQmlVMEMetaObject *m_target;
- unsigned m_isVar : 1;
- int m_index : 31;
+ int m_index;
+};
+
+
+class Q_QML_PRIVATE_EXPORT QQmlInterceptorMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ QQmlInterceptorMetaObject(QObject *obj, QQmlPropertyCache *cache);
+ ~QQmlInterceptorMetaObject();
+
+ void registerInterceptor(int index, int valueIndex, QQmlPropertyValueInterceptor *interceptor);
+
+ static QQmlInterceptorMetaObject *get(QObject *obj);
+
+ virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *o);
+
+ // Used by auto-tests for inspection
+ QQmlPropertyCache *propertyCache() const { return cache; }
+
+protected:
+ virtual int metaCall(QObject *o, QMetaObject::Call c, int id, void **a);
+ bool intercept(QMetaObject::Call c, int id, void **a);
+
+public:
+ QObject *object;
+ QQmlPropertyCache *cache;
+ QBiPointer<QDynamicMetaObjectData, const QMetaObject> parent;
+
+ QQmlPropertyValueInterceptor *interceptors;
+ bool hasAssignedMetaObjectData;
};
+inline QQmlInterceptorMetaObject *QQmlInterceptorMetaObject::get(QObject *obj)
+{
+ if (obj) {
+ if (QQmlData *data = QQmlData::get(obj)) {
+ if (data->hasInterceptorMetaObject)
+ return static_cast<QQmlInterceptorMetaObject *>(QObjectPrivate::get(obj)->metaObject);
+ }
+ }
+
+ return 0;
+}
+
class QQmlVMEVariant;
class QQmlRefCount;
class QQmlVMEMetaObjectEndpoint;
-class Q_QML_PRIVATE_EXPORT QQmlVMEMetaObject : public QAbstractDynamicMetaObject
+class Q_QML_PRIVATE_EXPORT QQmlVMEMetaObject : public QQmlInterceptorMetaObject
{
public:
- QQmlVMEMetaObject(QObject *obj, QQmlPropertyCache *cache, const QQmlVMEMetaData *data,
- QV4::ExecutionContext *qmlBindingContext = 0, QQmlCompiledData *compiledData = 0);
+ QQmlVMEMetaObject(QObject *obj, QQmlPropertyCache *cache, const QQmlVMEMetaData *data);
~QQmlVMEMetaObject();
bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const;
- void registerInterceptor(int index, int valueIndex, QQmlPropertyValueInterceptor *interceptor);
QV4::ReturnedValue vmeMethod(int index);
quint16 vmeMethodLineNumber(int index);
void setVmeMethod(int index, const QV4::Value &function);
@@ -166,27 +207,20 @@ public:
void connectAliasSignal(int index, bool indexInSignalRange);
- virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *o);
-
- // Used by auto-tests for inspection
- QQmlPropertyCache *propertyCache() const { return cache; }
-
static inline QQmlVMEMetaObject *get(QObject *o);
static QQmlVMEMetaObject *getForProperty(QObject *o, int coreIndex);
static QQmlVMEMetaObject *getForMethod(QObject *o, int coreIndex);
static QQmlVMEMetaObject *getForSignal(QObject *o, int coreIndex);
protected:
- virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+ virtual int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a);
public:
friend class QQmlVMEMetaObjectEndpoint;
friend class QQmlVMEVariantQObjectPtr;
friend class QQmlPropertyCache;
- QObject *object;
QQmlGuardedContextData ctxt;
- QQmlPropertyCache *cache;
const QQmlVMEMetaData *metaData;
inline int propOffset() const;
@@ -194,26 +228,44 @@ public:
inline int signalOffset() const;
inline int signalCount() const;
- bool hasAssignedMetaObjectData;
- QQmlVMEVariant *data;
QQmlVMEMetaObjectEndpoint *aliasEndpoints;
- QV4::WeakValue varProperties;
- int firstVarPropertyIndex;
- bool varPropertiesInitialized;
- inline void allocateVarPropertiesArray();
- inline bool ensureVarPropertiesAllocated();
+ QV4::WeakValue properties;
+ inline void allocateProperties();
+ QV4::MemberData *propertiesAsMemberData();
+
+ int readPropertyAsInt(int id);
+ bool readPropertyAsBool(int id);
+ double readPropertyAsDouble(int id);
+ QString readPropertyAsString(int id);
+ QSizeF readPropertyAsSizeF(int id);
+ QPointF readPropertyAsPointF(int id);
+ QUrl readPropertyAsUrl(int id);
+ QDate readPropertyAsDate(int id);
+ QDateTime readPropertyAsDateTime(int id);
+ QRectF readPropertyAsRectF(int id);
+ QObject *readPropertyAsQObject(int id);
+ QList<QObject *> *readPropertyAsList(int id);
+
+ void writeProperty(int id, int v);
+ void writeProperty(int id, bool v);
+ void writeProperty(int id, double v);
+ void writeProperty(int id, const QString& v);
+ void writeProperty(int id, const QPointF& v);
+ void writeProperty(int id, const QSizeF& v);
+ void writeProperty(int id, const QUrl& v);
+ void writeProperty(int id, const QDate& v);
+ void writeProperty(int id, const QDateTime& v);
+ void writeProperty(int id, const QRectF& v);
+ void writeProperty(int id, QObject *v);
void ensureQObjectWrapper();
void mark(QV4::ExecutionEngine *e);
void connectAlias(int aliasId);
- QBitArray aConnected;
- QQmlPropertyValueInterceptor *interceptors;
-
- QV4::PersistentValue *v8methods;
+ QV4::PersistentValue *methods;
QV4::ReturnedValue method(int);
QV4::ReturnedValue readVarProperty(int);
@@ -221,19 +273,9 @@ public:
QVariant readPropertyAsVariant(int);
void writeProperty(int, const QVariant &);
- QBiPointer<QDynamicMetaObjectData, const QMetaObject> parent;
-
inline QQmlVMEMetaObject *parentVMEMetaObject() const;
void listChanged(int);
- class List : public QList<QObject*>
- {
- public:
- List(int lpi, QQmlVMEMetaObject *mo) : notifyIndex(lpi), mo(mo) {}
- int notifyIndex;
- QQmlVMEMetaObject *mo;
- };
- QList<List> listProperties;
static void list_append(QQmlListProperty<QObject> *, QObject *);
static int list_count(QQmlListProperty<QObject> *);
@@ -245,8 +287,6 @@ public:
QList<QQmlVMEVariantQObjectPtr *> varObjectGuards;
QQmlVMEVariantQObjectPtr *getQObjectGuardForProperty(int) const;
-
- friend class QV8GCCallback;
};
QQmlVMEMetaObject *QQmlVMEMetaObject::get(QObject *obj)
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 5586bdbb50..3521384d77 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -60,6 +60,7 @@
#include <private/qv4objectproto_p.h>
#include <private/qv4scopedvalue_p.h>
#include <private/qv4arraybuffer_p.h>
+#include <private/qv4jsonobject_p.h>
using namespace QV4;
@@ -94,16 +95,6 @@ static inline QQmlXMLHttpRequestData *xhrdata(ExecutionEngine *v4)
return (QQmlXMLHttpRequestData *)v4->v8Engine->xmlHttpRequestData();
}
-static ReturnedValue constructMeObject(const Value &thisObj, ExecutionEngine *v4)
-{
- Scope scope(v4);
- ScopedObject meObj(scope, v4->newObject());
- meObj->put(ScopedString(scope, v4->newString(QStringLiteral("ThisObject"))), thisObj);
- ScopedValue v(scope, QmlContextWrapper::qmlScope(v4, v4->v8Engine->callingContext(), 0));
- meObj->put(ScopedString(scope, v4->newString(QStringLiteral("ActivationObject"))), v);
- return meObj.asReturnedValue();
-}
-
QQmlXMLHttpRequestData::QQmlXMLHttpRequestData()
{
}
@@ -179,7 +170,7 @@ public:
namespace Heap {
struct NamedNodeMap : Object {
- NamedNodeMap(ExecutionEngine *engine, NodeImpl *data, const QList<NodeImpl *> &list);
+ NamedNodeMap(NodeImpl *data, const QList<NodeImpl *> &list);
~NamedNodeMap() {
if (d)
d->release();
@@ -189,7 +180,7 @@ struct NamedNodeMap : Object {
};
struct NodeList : Object {
- NodeList(ExecutionEngine *engine, NodeImpl *data);
+ NodeList(NodeImpl *data);
~NodeList() {
if (d)
d->release();
@@ -198,11 +189,11 @@ struct NodeList : Object {
};
struct NodePrototype : Object {
- NodePrototype(ExecutionEngine *engine);
+ NodePrototype();
};
struct Node : Object {
- Node(ExecutionEngine *engine, NodeImpl *data);
+ Node(NodeImpl *data);
~Node() {
if (d)
d->release();
@@ -222,13 +213,12 @@ public:
static ReturnedValue create(ExecutionEngine *, NodeImpl *, const QList<NodeImpl *> &);
// JS API
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
};
-Heap::NamedNodeMap::NamedNodeMap(ExecutionEngine *engine, NodeImpl *data, const QList<NodeImpl *> &list)
- : Heap::Object(engine)
- , list(list)
+Heap::NamedNodeMap::NamedNodeMap(NodeImpl *data, const QList<NodeImpl *> &list)
+ : list(list)
, d(data)
{
if (d)
@@ -244,17 +234,16 @@ public:
V4_NEEDS_DESTROY
// JS API
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
// C++ API
static ReturnedValue create(ExecutionEngine *, NodeImpl *);
};
-Heap::NodeList::NodeList(ExecutionEngine *engine, NodeImpl *data)
- : Heap::Object(engine)
- , d(data)
+Heap::NodeList::NodeList(NodeImpl *data)
+ : d(data)
{
if (d)
d->addref();
@@ -273,6 +262,7 @@ public:
static ReturnedValue method_get_nodeName(CallContext *ctx);
static ReturnedValue method_get_nodeValue(CallContext *ctx);
static ReturnedValue method_get_nodeType(CallContext *ctx);
+ static ReturnedValue method_get_namespaceUri(CallContext *ctx);
static ReturnedValue method_get_parentNode(CallContext *ctx);
static ReturnedValue method_get_childNodes(CallContext *ctx);
@@ -293,15 +283,15 @@ public:
};
-Heap::NodePrototype::NodePrototype(ExecutionEngine *engine)
- : Heap::Object(engine)
+Heap::NodePrototype::NodePrototype()
{
- Scope scope(engine);
+ Scope scope(internalClass->engine);
ScopedObject o(scope, this);
o->defineAccessorProperty(QStringLiteral("nodeName"), QV4::NodePrototype::method_get_nodeName, 0);
o->defineAccessorProperty(QStringLiteral("nodeValue"), QV4::NodePrototype::method_get_nodeValue, 0);
o->defineAccessorProperty(QStringLiteral("nodeType"), QV4::NodePrototype::method_get_nodeType, 0);
+ o->defineAccessorProperty(QStringLiteral("namespaceUri"), QV4::NodePrototype::method_get_namespaceUri, 0);
o->defineAccessorProperty(QStringLiteral("parentNode"), QV4::NodePrototype::method_get_parentNode, 0);
o->defineAccessorProperty(QStringLiteral("childNodes"), QV4::NodePrototype::method_get_childNodes, 0);
@@ -326,9 +316,8 @@ struct Node : public Object
bool isNull() const;
};
-Heap::Node::Node(ExecutionEngine *engine, NodeImpl *data)
- : Heap::Object(engine)
- , d(data)
+Heap::Node::Node(NodeImpl *data)
+ : d(data)
{
if (d)
d->addref();
@@ -466,6 +455,16 @@ ReturnedValue NodePrototype::method_get_nodeType(CallContext *ctx)
return Encode(r->d()->d->type);
}
+ReturnedValue NodePrototype::method_get_namespaceUri(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ if (!r)
+ return ctx->engine()->throwTypeError();
+
+ return Encode(ctx->d()->engine->newString(r->d()->d->namespaceUri));
+}
+
ReturnedValue NodePrototype::method_get_parentNode(CallContext *ctx)
{
Scope scope(ctx);
@@ -577,7 +576,7 @@ ReturnedValue NodePrototype::getProto(ExecutionEngine *v4)
Scope scope(v4);
QQmlXMLHttpRequestData *d = xhrdata(v4);
if (d->nodePrototype.isUndefined()) {
- ScopedObject p(scope, v4->memoryManager->alloc<NodePrototype>(v4));
+ ScopedObject p(scope, v4->memoryManager->allocObject<NodePrototype>());
d->nodePrototype.set(v4, p);
v4->v8Engine->freezeObject(p);
}
@@ -588,7 +587,7 @@ ReturnedValue Node::create(ExecutionEngine *v4, NodeImpl *data)
{
Scope scope(v4);
- Scoped<Node> instance(scope, v4->memoryManager->alloc<Node>(v4, data));
+ Scoped<Node> instance(scope, v4->memoryManager->allocObject<Node>(data));
ScopedObject p(scope);
switch (data->type) {
@@ -856,7 +855,8 @@ ReturnedValue Document::load(ExecutionEngine *v4, const QByteArray &data)
return Encode::null();
}
- ScopedObject instance(scope, v4->memoryManager->alloc<Node>(v4, document));
+ ScopedObject instance(scope, v4->memoryManager->allocObject<Node>(document));
+ document->release(); // the GC should own the NodeImpl via Node now
ScopedObject p(scope);
instance->setPrototype((p = Document::prototype(v4)));
return instance.asReturnedValue();
@@ -867,10 +867,10 @@ bool Node::isNull() const
return d()->d == 0;
}
-ReturnedValue NamedNodeMap::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue NamedNodeMap::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
Q_ASSERT(m->as<NamedNodeMap>());
- NamedNodeMap *r = static_cast<NamedNodeMap *>(m);
+ const NamedNodeMap *r = static_cast<const NamedNodeMap *>(m);
QV4::ExecutionEngine *v4 = r->engine();
if ((int)index < r->d()->list.count()) {
@@ -883,14 +883,14 @@ ReturnedValue NamedNodeMap::getIndexed(Managed *m, uint index, bool *hasProperty
return Encode::undefined();
}
-ReturnedValue NamedNodeMap::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue NamedNodeMap::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<NamedNodeMap>());
- NamedNodeMap *r = static_cast<NamedNodeMap *>(m);
+ const NamedNodeMap *r = static_cast<const NamedNodeMap *>(m);
QV4::ExecutionEngine *v4 = r->engine();
name->makeIdentifier(v4);
- if (name->equals(v4->id_length))
+ if (name->equals(v4->id_length()))
return Primitive::fromInt32(r->d()->list.count()).asReturnedValue();
QString str = name->toQString();
@@ -909,13 +909,13 @@ ReturnedValue NamedNodeMap::get(Managed *m, String *name, bool *hasProperty)
ReturnedValue NamedNodeMap::create(ExecutionEngine *v4, NodeImpl *data, const QList<NodeImpl *> &list)
{
- return (v4->memoryManager->alloc<NamedNodeMap>(v4, data, list))->asReturnedValue();
+ return (v4->memoryManager->allocObject<NamedNodeMap>(data, list))->asReturnedValue();
}
-ReturnedValue NodeList::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue NodeList::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
Q_ASSERT(m->as<NodeList>());
- NodeList *r = static_cast<NodeList *>(m);
+ const NodeList *r = static_cast<const NodeList *>(m);
QV4::ExecutionEngine *v4 = r->engine();
if ((int)index < r->d()->d->children.count()) {
@@ -928,22 +928,22 @@ ReturnedValue NodeList::getIndexed(Managed *m, uint index, bool *hasProperty)
return Encode::undefined();
}
-ReturnedValue NodeList::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue NodeList::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<NodeList>());
- NodeList *r = static_cast<NodeList *>(m);
+ const NodeList *r = static_cast<const NodeList *>(m);
QV4::ExecutionEngine *v4 = r->engine();
name->makeIdentifier(v4);
- if (name->equals(v4->id_length))
+ if (name->equals(v4->id_length()))
return Primitive::fromInt32(r->d()->d->children.count()).asReturnedValue();
return Object::get(m, name, hasProperty);
}
ReturnedValue NodeList::create(ExecutionEngine *v4, NodeImpl *data)
{
- return (v4->memoryManager->alloc<NodeList>(v4, data))->asReturnedValue();
+ return (v4->memoryManager->allocObject<NodeList>(data))->asReturnedValue();
}
ReturnedValue Document::method_documentElement(CallContext *ctx)
@@ -998,7 +998,7 @@ public:
Opened = 1, HeadersReceived = 2,
Loading = 3, Done = 4 };
- QQmlXMLHttpRequest(ExecutionEngine *engine, QNetworkAccessManager *manager);
+ QQmlXMLHttpRequest(QNetworkAccessManager *manager);
virtual ~QQmlXMLHttpRequest();
bool sendFlag() const;
@@ -1007,21 +1007,23 @@ public:
int replyStatus() const;
QString replyStatusText() const;
- ReturnedValue open(const Value &me, const QString &, const QUrl &, LoadType);
- ReturnedValue send(const Value &me, const QByteArray &);
- ReturnedValue abort(const Value &me);
+ ReturnedValue open(Object *thisObject, QQmlContextData *context, const QString &, const QUrl &, LoadType);
+ ReturnedValue send(Object *thisObject, QQmlContextData *context, const QByteArray &);
+ ReturnedValue abort(Object *thisObject, QQmlContextData *context);
void addHeader(const QString &, const QString &);
QString header(const QString &name);
QString headers();
-
QString responseBody();
const QByteArray & rawResponseBody() const;
bool receivedXml() const;
const QString & responseType() const;
void setResponseType(const QString &);
+
+ QV4::ReturnedValue jsonResponseBody(QV4::ExecutionEngine*);
+ QV4::ReturnedValue xmlResponseBody(QV4::ExecutionEngine*);
private slots:
void readyRead();
void error(QNetworkReply::NetworkError);
@@ -1030,7 +1032,6 @@ private slots:
private:
void requestFromUrl(const QUrl &url);
- ExecutionEngine *v4;
State m_state;
bool m_errorFlag;
bool m_sendFlag;
@@ -1054,12 +1055,11 @@ private:
#endif
void readEncoding();
- ReturnedValue getMe() const;
- void setMe(const Value &me);
- PersistentValue m_me;
+ PersistentValue m_thisObject;
+ QQmlGuardedContextData m_qmlContext;
- void dispatchCallbackImpl(const Value &me);
- void dispatchCallback(const Value &me);
+ static void dispatchCallback(Object *thisObj, QQmlContextData *context);
+ void dispatchCallback();
int m_status;
QString m_statusText;
@@ -1072,13 +1072,14 @@ private:
QNetworkAccessManager *networkAccessManager() { return m_nam; }
QString m_responseType;
+ QV4::PersistentValue m_parsedDocument;
};
-QQmlXMLHttpRequest::QQmlXMLHttpRequest(ExecutionEngine *engine, QNetworkAccessManager *manager)
- : v4(engine)
- , m_state(Unsent), m_errorFlag(false), m_sendFlag(false)
+QQmlXMLHttpRequest::QQmlXMLHttpRequest(QNetworkAccessManager *manager)
+ : m_state(Unsent), m_errorFlag(false), m_sendFlag(false)
, m_redirectCount(0), m_gotXml(false), m_textCodec(0), m_network(0), m_nam(manager)
, m_responseType()
+ , m_parsedDocument()
{
}
@@ -1112,7 +1113,7 @@ QString QQmlXMLHttpRequest::replyStatusText() const
return m_statusText;
}
-ReturnedValue QQmlXMLHttpRequest::open(const Value &me, const QString &method, const QUrl &url, LoadType loadType)
+ReturnedValue QQmlXMLHttpRequest::open(Object *thisObject, QQmlContextData *context, const QString &method, const QUrl &url, LoadType loadType)
{
destroyNetwork();
m_sendFlag = false;
@@ -1123,7 +1124,7 @@ ReturnedValue QQmlXMLHttpRequest::open(const Value &me, const QString &method, c
m_request.setAttribute(QNetworkRequest::SynchronousRequestAttribute, loadType == SynchronousLoad);
m_state = Opened;
m_addedHeaders.clear();
- dispatchCallback(me);
+ dispatchCallback(thisObject, context);
return Encode::undefined();
}
@@ -1229,11 +1230,12 @@ void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url)
m_network = networkAccessManager()->put(request, m_data);
} else if (m_method == QLatin1String("DELETE")) {
m_network = networkAccessManager()->deleteResource(request);
- } else if (m_method == QLatin1String("OPTIONS")) {
+ } else if ((m_method == QLatin1String("OPTIONS")) ||
+ m_method == QLatin1String("PROPFIND")) {
QBuffer *buffer = new QBuffer;
buffer->setData(m_data);
buffer->open(QIODevice::ReadOnly);
- m_network = networkAccessManager()->sendCustomRequest(request, QByteArrayLiteral("OPTIONS"), buffer);
+ m_network = networkAccessManager()->sendCustomRequest(request, QByteArray(m_method.toUtf8().constData()), buffer);
buffer->setParent(m_network);
}
@@ -1257,21 +1259,22 @@ void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url)
}
}
-ReturnedValue QQmlXMLHttpRequest::send(const Value &me, const QByteArray &data)
+ReturnedValue QQmlXMLHttpRequest::send(Object *thisObject, QQmlContextData *context, const QByteArray &data)
{
m_errorFlag = false;
m_sendFlag = true;
m_redirectCount = 0;
m_data = data;
- setMe(me);
+ m_thisObject = thisObject;
+ m_qmlContext = context;
requestFromUrl(m_url);
return Encode::undefined();
}
-ReturnedValue QQmlXMLHttpRequest::abort(const Value &me)
+ReturnedValue QQmlXMLHttpRequest::abort(Object *thisObject, QQmlContextData *context)
{
destroyNetwork();
m_responseEntityBody = QByteArray();
@@ -1284,7 +1287,7 @@ ReturnedValue QQmlXMLHttpRequest::abort(const Value &me)
m_state = Done;
m_sendFlag = false;
- dispatchCallback(me);
+ dispatchCallback(thisObject, context);
}
m_state = Unsent;
@@ -1292,16 +1295,6 @@ ReturnedValue QQmlXMLHttpRequest::abort(const Value &me)
return Encode::undefined();
}
-ReturnedValue QQmlXMLHttpRequest::getMe() const
-{
- return m_me.value();
-}
-
-void QQmlXMLHttpRequest::setMe(const Value &me)
-{
- m_me.set(v4, me);
-}
-
void QQmlXMLHttpRequest::readyRead()
{
m_status =
@@ -1309,14 +1302,11 @@ void QQmlXMLHttpRequest::readyRead()
m_statusText =
QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
- Scope scope(v4);
- ScopedValue me(scope, m_me.value());
-
// ### We assume if this is called the headers are now available
if (m_state < HeadersReceived) {
m_state = HeadersReceived;
fillHeadersList ();
- dispatchCallback(me);
+ dispatchCallback();
}
bool wasEmpty = m_responseEntityBody.isEmpty();
@@ -1324,7 +1314,7 @@ void QQmlXMLHttpRequest::readyRead()
if (wasEmpty && !m_responseEntityBody.isEmpty())
m_state = Loading;
- dispatchCallback(me);
+ dispatchCallback();
}
static const char *errorToString(QNetworkReply::NetworkError error)
@@ -1355,26 +1345,26 @@ void QQmlXMLHttpRequest::error(QNetworkReply::NetworkError error)
qWarning().nospace() << " " << error << ' ' << errorToString(error) << ' ' << m_statusText;
}
- Scope scope(v4);
- ScopedValue me(scope, m_me.value());
-
if (error == QNetworkReply::ContentAccessDenied ||
error == QNetworkReply::ContentOperationNotPermittedError ||
error == QNetworkReply::ContentNotFoundError ||
error == QNetworkReply::AuthenticationRequiredError ||
error == QNetworkReply::ContentReSendError ||
error == QNetworkReply::UnknownContentError ||
- error == QNetworkReply::ProtocolInvalidOperationError) {
+ error == QNetworkReply::ProtocolInvalidOperationError ||
+ error == QNetworkReply::InternalServerError ||
+ error == QNetworkReply::OperationNotImplementedError ||
+ error == QNetworkReply::ServiceUnavailableError ||
+ error == QNetworkReply::UnknownServerError) {
m_state = Loading;
- dispatchCallback(me);
+ dispatchCallback();
} else {
m_errorFlag = true;
m_responseEntityBody = QByteArray();
}
m_state = Done;
-
- dispatchCallback(me);
+ dispatchCallback();
}
#define XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION 15
@@ -1406,7 +1396,7 @@ void QQmlXMLHttpRequest::finished()
if (m_state < HeadersReceived) {
m_state = HeadersReceived;
fillHeadersList ();
- dispatchCallback(*m_me.valueRef());
+ dispatchCallback();
}
m_responseEntityBody.append(m_network->readAll());
readEncoding();
@@ -1423,15 +1413,14 @@ void QQmlXMLHttpRequest::finished()
destroyNetwork();
if (m_state < Loading) {
m_state = Loading;
- dispatchCallback(*m_me.valueRef());
+ dispatchCallback();
}
m_state = Done;
- dispatchCallback(*m_me.valueRef());
+ dispatchCallback();
- Scope scope(v4);
- ScopedValue v(scope, Primitive::undefinedValue());
- setMe(v);
+ m_thisObject.clear();
+ m_qmlContext.setContextData(0);
}
@@ -1474,6 +1463,32 @@ void QQmlXMLHttpRequest::setResponseType(const QString &responseType)
m_responseType = responseType;
}
+QV4::ReturnedValue QQmlXMLHttpRequest::jsonResponseBody(QV4::ExecutionEngine* engine)
+{
+ if (m_parsedDocument.isEmpty()) {
+ Scope scope(engine);
+
+ QJsonParseError error;
+ const QString& jtext = responseBody();
+ JsonParser parser(scope.engine, jtext.constData(), jtext.length());
+ ScopedValue jsonObject(scope, parser.parse(&error));
+ if (error.error != QJsonParseError::NoError)
+ return engine->throwSyntaxError(QStringLiteral("JSON.parse: Parse error"));
+
+ m_parsedDocument.set(scope.engine, jsonObject);
+ }
+
+ return m_parsedDocument.value();
+}
+
+QV4::ReturnedValue QQmlXMLHttpRequest::xmlResponseBody(QV4::ExecutionEngine* engine)
+{
+ if (m_parsedDocument.isEmpty()) {
+ m_parsedDocument.set(engine, Document::load(engine, rawResponseBody()));
+ }
+
+ return m_parsedDocument.value();
+}
#ifndef QT_NO_TEXTCODEC
QTextCodec* QQmlXMLHttpRequest::findTextCodec() const
@@ -1519,57 +1534,38 @@ const QByteArray &QQmlXMLHttpRequest::rawResponseBody() const
return m_responseEntityBody;
}
-void QQmlXMLHttpRequest::dispatchCallbackImpl(const Value &me)
+void QQmlXMLHttpRequest::dispatchCallback(Object *thisObj, QQmlContextData *context)
{
- QV4::Scope scope(v4);
- ScopedObject o(scope, me);
- if (!o) {
- v4->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ThisObject"));
- return;
- }
+ Q_ASSERT(thisObj);
- ScopedString s(scope, v4->newString(QStringLiteral("ThisObject")));
- ScopedObject thisObj(scope, o->get(s));
- if (!thisObj) {
- v4->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ThisObject"));
+ if (!context)
+ // if the calling context object is no longer valid, then it has been
+ // deleted explicitly (e.g., by a Loader deleting the itemContext when
+ // the source is changed). We do nothing in this case, as the evaluation
+ // cannot succeed.
return;
- }
- s = v4->newString(QStringLiteral("onreadystatechange"));
+ QV4::Scope scope(thisObj->engine());
+ ScopedString s(scope, scope.engine->newString(QStringLiteral("onreadystatechange")));
ScopedFunctionObject callback(scope, thisObj->get(s));
if (!callback) {
// not an error, but no onreadystatechange function to call.
return;
}
- s = v4->newString(QStringLiteral("ActivationObject"));
- ScopedObject activationObject(scope, o->get(s));
- if (!activationObject) {
- v4->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ActivationObject"));
- return;
- }
+ QV4::ScopedCallData callData(scope);
+ callData->thisObject = Encode::undefined();
+ callback->call(callData);
- QQmlContextData *callingContext = QmlContextWrapper::getContext(activationObject);
- if (callingContext) {
- QV4::ScopedCallData callData(scope);
- callData->thisObject = activationObject.asReturnedValue();
- callback->call(callData);
+ if (scope.engine->hasException) {
+ QQmlError error = scope.engine->catchExceptionAsQmlError();
+ QQmlEnginePrivate::warning(QQmlEnginePrivate::get(scope.engine->qmlEngine()), error);
}
-
- // if the callingContext object is no longer valid, then it has been
- // deleted explicitly (e.g., by a Loader deleting the itemContext when
- // the source is changed). We do nothing in this case, as the evaluation
- // cannot succeed.
-
}
-void QQmlXMLHttpRequest::dispatchCallback(const Value &me)
+void QQmlXMLHttpRequest::dispatchCallback()
{
- dispatchCallbackImpl(me);
- if (v4->hasException) {
- QQmlError error = v4->catchExceptionAsQmlError();
- QQmlEnginePrivate::warning(QQmlEnginePrivate::get(v4->qmlEngine()), error);
- }
+ dispatchCallback(m_thisObject.as<Object>(), m_qmlContext.contextData());
}
void QQmlXMLHttpRequest::destroyNetwork()
@@ -1585,7 +1581,7 @@ namespace QV4 {
namespace Heap {
struct QQmlXMLHttpRequestWrapper : Object {
- QQmlXMLHttpRequestWrapper(ExecutionEngine *engine, QQmlXMLHttpRequest *request);
+ QQmlXMLHttpRequestWrapper(QQmlXMLHttpRequest *request);
~QQmlXMLHttpRequestWrapper() {
delete request;
}
@@ -1595,7 +1591,7 @@ struct QQmlXMLHttpRequestWrapper : Object {
struct QQmlXMLHttpRequestCtor : FunctionObject {
QQmlXMLHttpRequestCtor(ExecutionEngine *engine);
- Object *proto;
+ Pointer<Object> proto;
};
}
@@ -1606,9 +1602,8 @@ struct QQmlXMLHttpRequestWrapper : public Object
V4_NEEDS_DESTROY
};
-Heap::QQmlXMLHttpRequestWrapper::QQmlXMLHttpRequestWrapper(ExecutionEngine *engine, QQmlXMLHttpRequest *request)
- : Heap::Object(engine)
- , request(request)
+Heap::QQmlXMLHttpRequestWrapper::QQmlXMLHttpRequestWrapper(QQmlXMLHttpRequest *request)
+ : request(request)
{
}
@@ -1621,21 +1616,21 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
c->proto->mark(e);
FunctionObject::markObjects(that, e);
}
- static ReturnedValue construct(Managed *that, QV4::CallData *)
+ static ReturnedValue construct(const Managed *that, QV4::CallData *)
{
- Scope scope(static_cast<QQmlXMLHttpRequestCtor *>(that)->engine());
+ Scope scope(static_cast<const QQmlXMLHttpRequestCtor *>(that)->engine());
Scoped<QQmlXMLHttpRequestCtor> ctor(scope, that->as<QQmlXMLHttpRequestCtor>());
if (!ctor)
return scope.engine->throwTypeError();
- QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine, scope.engine->v8Engine->networkAccessManager());
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->alloc<QQmlXMLHttpRequestWrapper>(scope.engine, r));
+ QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->v8Engine->networkAccessManager());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocObject<QQmlXMLHttpRequestWrapper>(r));
ScopedObject proto(scope, ctor->d()->proto);
w->setPrototype(proto);
return w.asReturnedValue();
}
- static ReturnedValue call(Managed *, QV4::CallData *) {
+ static ReturnedValue call(const Managed *, QV4::CallData *) {
return Primitive::undefinedValue().asReturnedValue();
}
@@ -1675,7 +1670,7 @@ Heap::QQmlXMLHttpRequestCtor::QQmlXMLHttpRequestCtor(ExecutionEngine *engine)
ctor->defineReadonlyProperty(QStringLiteral("DONE"), Primitive::fromInt32(4));
if (!ctor->d()->proto)
ctor->setupProto();
- ScopedString s(scope, engine->id_prototype);
+ ScopedString s(scope, engine->id_prototype());
ctor->defineDefaultProperty(s, ScopedObject(scope, ctor->d()->proto));
}
@@ -1735,14 +1730,15 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
method != QLatin1String("HEAD") &&
method != QLatin1String("POST") &&
method != QLatin1String("DELETE") &&
- method != QLatin1String("OPTIONS"))
+ method != QLatin1String("OPTIONS") &&
+ method != QLatin1String("PROPFIND"))
V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Unsupported HTTP method type");
// Argument 1 - URL
QUrl url = QUrl(ctx->args()[1].toQStringNoThrow());
if (url.isRelative())
- url = scope.engine->v8Engine->callingContext()->resolvedUrl(url);
+ url = scope.engine->callingQmlContext()->resolvedUrl(url);
bool async = true;
// Argument 2 - async (optional)
@@ -1764,8 +1760,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
if (!username.isNull()) url.setUserName(username);
if (!password.isNull()) url.setPassword(password);
- ScopedValue meObject(scope, constructMeObject(ctx->thisObject(), scope.engine));
- return r->open(meObject, method, url, async ? QQmlXMLHttpRequest::AsynchronousLoad : QQmlXMLHttpRequest::SynchronousLoad);
+ return r->open(w, scope.engine->callingQmlContext(), method, url, async ? QQmlXMLHttpRequest::AsynchronousLoad : QQmlXMLHttpRequest::SynchronousLoad);
}
ReturnedValue QQmlXMLHttpRequestCtor::method_setRequestHeader(CallContext *ctx)
@@ -1831,8 +1826,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_send(CallContext *ctx)
if (ctx->argc() > 0)
data = ctx->args()[0].toQStringNoThrow().toUtf8();
- ScopedValue meObject(scope, constructMeObject(ctx->thisObject(), scope.engine));
- return r->send(meObject, data);
+ return r->send(w, scope.engine->callingQmlContext(), data);
}
ReturnedValue QQmlXMLHttpRequestCtor::method_abort(CallContext *ctx)
@@ -1843,8 +1837,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_abort(CallContext *ctx)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
- ScopedValue meObject(scope, constructMeObject(ctx->thisObject(), scope.engine));
- return r->abort(meObject);
+ return r->abort(w, scope.engine->callingQmlContext());
}
ReturnedValue QQmlXMLHttpRequestCtor::method_getResponseHeader(CallContext *ctx)
@@ -1961,7 +1954,9 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseXML(CallContext *ctx)
r->readyState() != QQmlXMLHttpRequest::Done)) {
return Encode::null();
} else {
- return Document::load(scope.engine, r->rawResponseBody());
+ if (r->responseType().isEmpty())
+ r->setResponseType(QLatin1String("document"));
+ return r->xmlResponseBody(scope.engine);
}
}
@@ -1982,6 +1977,10 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_response(CallContext *ctx)
return QV4::Encode(scope.engine->newString(r->responseBody()));
} else if (responseType.compare(QLatin1String("arraybuffer"), Qt::CaseInsensitive) == 0) {
return QV4::Encode(scope.engine->newArrayBuffer(r->rawResponseBody()));
+ } else if (responseType.compare(QLatin1String("json"), Qt::CaseInsensitive) == 0) {
+ return r->jsonResponseBody(scope.engine);
+ } else if (responseType.compare(QLatin1String("document"), Qt::CaseInsensitive) == 0) {
+ return r->xmlResponseBody(scope.engine);
} else {
return QV4::Encode(scope.engine->newString(QString()));
}
@@ -2027,9 +2026,9 @@ void *qt_add_qmlxmlhttprequest(ExecutionEngine *v4)
{
Scope scope(v4);
- Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->alloc<QQmlXMLHttpRequestCtor>(v4));
+ Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->allocObject<QQmlXMLHttpRequestCtor>(v4));
ScopedString s(scope, v4->newString(QStringLiteral("XMLHttpRequest")));
- v4->globalObject()->defineReadonlyProperty(s, ctor);
+ v4->globalObject->defineReadonlyProperty(s, ctor);
QQmlXMLHttpRequestData *data = new QQmlXMLHttpRequestData;
return data;
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index f53b9a0c7d..f4e980eefb 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -41,7 +41,8 @@
#include <private/qv8engine_p.h>
#include <QFileInfo>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qqmldebugconnector_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#include <private/qqmlglobal_p.h>
#include <private/qqmlplatform_p.h>
@@ -51,6 +52,7 @@
#include <private/qv4include_p.h>
#include <private/qv4context_p.h>
#include <private/qv4stringobject_p.h>
+#include <private/qv4dateobject_p.h>
#include <private/qv4mm_p.h>
#include <private/qv4jsonobject_p.h>
#include <private/qv4objectproto_p.h>
@@ -78,10 +80,9 @@ struct StaticQtMetaObject : public QObject
{ return &staticQtMetaObject; }
};
-Heap::QtObject::QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine)
- : Heap::Object(v4)
+Heap::QtObject::QtObject(QQmlEngine *qmlEngine)
{
- Scope scope(v4);
+ Scope scope(internalClass->engine);
ScopedObject o(scope, this);
// Set all the enums from the "Qt" namespace
@@ -91,11 +92,11 @@ Heap::QtObject::QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine)
for (int ii = 0; ii < qtMetaObject->enumeratorCount(); ++ii) {
QMetaEnum enumerator = qtMetaObject->enumerator(ii);
for (int jj = 0; jj < enumerator.keyCount(); ++jj) {
- o->put((str = v4->newString(QString::fromUtf8(enumerator.key(jj)))), (v = QV4::Primitive::fromInt32(enumerator.value(jj))));
+ o->put((str = scope.engine->newString(QString::fromUtf8(enumerator.key(jj)))), (v = QV4::Primitive::fromInt32(enumerator.value(jj))));
}
}
- o->put((str = v4->newString(QStringLiteral("Asynchronous"))), (v = QV4::Primitive::fromInt32(0)));
- o->put((str = v4->newString(QStringLiteral("Synchronous"))), (v = QV4::Primitive::fromInt32(1)));
+ o->put((str = scope.engine->newString(QStringLiteral("Asynchronous"))), (v = QV4::Primitive::fromInt32(0)));
+ o->put((str = scope.engine->newString(QStringLiteral("Synchronous"))), (v = QV4::Primitive::fromInt32(1)));
o->defineDefaultProperty(QStringLiteral("include"), QV4Include::method_include);
o->defineDefaultProperty(QStringLiteral("isQtObject"), QV4::QtObject::method_isQtObject);
@@ -433,11 +434,16 @@ Returns a Matrix4x4 with the specified values.
Alternatively, the function may be called with a single argument
where that argument is a JavaScript array which contains the sixteen
matrix values.
+Finally, the function may be called with no arguments and the resulting
+matrix will be the identity matrix.
*/
ReturnedValue QtObject::method_matrix4x4(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->d()->engine;
+ if (ctx->argc() == 0)
+ return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 0, Q_NULLPTR));
+
if (ctx->argc() == 1 && ctx->args()[0].isObject()) {
bool ok = false;
QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QMatrix4x4, QQmlV4Handle(ctx->args()[0]), v4, &ok);
@@ -669,7 +675,7 @@ ReturnedValue QtObject::method_formatTime(QV4::CallContext *ctx)
QVariant argVariant = ctx->engine()->toVariant(ctx->args()[0], -1);
QTime time;
- if (ctx->args()[0].asDateObject() || (argVariant.type() == QVariant::String))
+ if (ctx->args()[0].as<DateObject>() || (argVariant.type() == QVariant::String))
time = argVariant.toDateTime().time();
else // if (argVariant.type() == QVariant::Time), or invalid.
time = argVariant.toTime();
@@ -839,21 +845,21 @@ ReturnedValue QtObject::method_openUrlExternally(QV4::CallContext *ctx)
*/
ReturnedValue QtObject::method_resolvedUrl(QV4::CallContext *ctx)
{
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
+ ExecutionEngine *v4 = ctx->engine();
- QUrl url = ctx->engine()->toVariant(ctx->args()[0], -1).toUrl();
- QQmlEngine *e = v8engine->engine();
+ QUrl url = v4->toVariant(ctx->args()[0], -1).toUrl();
+ QQmlEngine *e = v4->qmlEngine();
QQmlEnginePrivate *p = 0;
if (e) p = QQmlEnginePrivate::get(e);
if (p) {
- QQmlContextData *ctxt = v8engine->callingContext();
+ QQmlContextData *ctxt = v4->callingQmlContext();
if (ctxt)
- return ctx->d()->engine->newString(ctxt->resolvedUrl(url).toString())->asReturnedValue();
+ return v4->newString(ctxt->resolvedUrl(url).toString())->asReturnedValue();
else
- return ctx->d()->engine->newString(url.toString())->asReturnedValue();
+ return v4->newString(url.toString())->asReturnedValue();
}
- return ctx->d()->engine->newString(e->baseUrl().resolved(url).toString())->asReturnedValue();
+ return v4->newString(e->baseUrl().resolved(url).toString())->asReturnedValue();
}
/*!
@@ -983,7 +989,7 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
QV8Engine *v8engine = ctx->d()->engine->v8Engine;
QQmlEngine *engine = v8engine->engine();
- QQmlContextData *context = v8engine->callingContext();
+ QQmlContextData *context = scope.engine->callingQmlContext();
Q_ASSERT(context);
QQmlContext *effectiveContext = 0;
if (context->isPragmaLibraryContext)
@@ -1012,8 +1018,13 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
if (!parentArg)
V4THROW_ERROR("Qt.createQmlObject(): Missing parent object");
+ QQmlTypeData *typeData = QQmlEnginePrivate::get(engine)->typeLoader.getType(
+ qml.toUtf8(), url, QQmlTypeLoader::Synchronous);
+ Q_ASSERT(typeData->isCompleteOrError());
QQmlComponent component(engine);
- component.setData(qml.toUtf8(), url);
+ QQmlComponentPrivate *componentPrivate = QQmlComponentPrivate::get(&component);
+ componentPrivate->fromTypeData(typeData);
+ componentPrivate->progress = 1.0;
if (component.isError()) {
ScopedValue v(scope, Error::create(ctx->d()->engine, component.errors()));
@@ -1063,10 +1074,23 @@ If the optional \a mode parameter is set to \c Component.Asynchronous, the
component will be loaded in a background thread. The Component::status property
will be \c Component.Loading while it is loading. The status will change to
\c Component.Ready if the component loads successfully, or \c Component.Error
-if loading fails.
+if loading fails. This parameter defaults to \c Component.PreferSynchronous
+if omitted.
+
+If \a mode is set to \c Component.PreferSynchronous, Qt will attempt to load
+the component synchronously, but may end up loading it asynchronously if
+necessary. Scenarios that may cause asynchronous loading include, but are not
+limited to, the following:
+
+\list
+\li The URL refers to a network resource
+\li The component is being created as a result of another component that is
+being loaded asynchronously
+\endlist
If the optional \a parent parameter is given, it should refer to the object
-that will become the parent for the created \l Component object.
+that will become the parent for the created \l Component object. If no mode
+was passed, this can be the second argument.
Call \l {Component::createObject()}{Component.createObject()} on the returned
component to create an object instance of the component.
@@ -1090,7 +1114,7 @@ ReturnedValue QtObject::method_createComponent(CallContext *ctx)
QV8Engine *v8engine = ctx->d()->engine->v8Engine;
QQmlEngine *engine = v8engine->engine();
- QQmlContextData *context = v8engine->callingContext();
+ QQmlContextData *context = scope.engine->callingQmlContext();
Q_ASSERT(context);
QQmlContextData *effectiveContext = context;
if (context->isPragmaLibraryContext)
@@ -1178,7 +1202,7 @@ ReturnedValue QtObject::method_locale(CallContext *ctx)
return QQmlLocale::locale(ctx->engine(), code);
}
-Heap::QQmlBindingFunction::QQmlBindingFunction(QV4::FunctionObject *originalFunction)
+Heap::QQmlBindingFunction::QQmlBindingFunction(const QV4::FunctionObject *originalFunction)
: QV4::Heap::FunctionObject(originalFunction->scope(), originalFunction->name())
, originalFunction(originalFunction->d())
{
@@ -1191,10 +1215,10 @@ void QQmlBindingFunction::initBindingLocation()
d()->bindingLocation.line = frame.line;
}
-ReturnedValue QQmlBindingFunction::call(Managed *that, CallData *callData)
+ReturnedValue QQmlBindingFunction::call(const Managed *that, CallData *callData)
{
- Scope scope(static_cast<QQmlBindingFunction*>(that)->engine());
- ScopedFunctionObject function(scope, static_cast<QQmlBindingFunction*>(that)->d()->originalFunction);
+ Scope scope(static_cast<const QQmlBindingFunction*>(that)->engine());
+ ScopedFunctionObject function(scope, static_cast<const QQmlBindingFunction*>(that)->d()->originalFunction);
return function->call(callData);
}
@@ -1256,18 +1280,18 @@ ReturnedValue QtObject::method_binding(CallContext *ctx)
{
if (ctx->argc() != 1)
V4THROW_ERROR("binding() requires 1 argument");
- QV4::FunctionObject *f = ctx->args()[0].asFunctionObject();
+ const QV4::FunctionObject *f = ctx->args()[0].as<FunctionObject>();
if (!f)
V4THROW_TYPE("binding(): argument (binding expression) must be a function");
- return (ctx->d()->engine->memoryManager->alloc<QQmlBindingFunction>(f))->asReturnedValue();
+ return (ctx->d()->engine->memoryManager->allocObject<QQmlBindingFunction>(f))->asReturnedValue();
}
ReturnedValue QtObject::method_get_platform(CallContext *ctx)
{
// ### inefficient. Should be just a value based getter
- Object *o = ctx->thisObject().asObject();
+ Object *o = ctx->thisObject().as<Object>();
if (!o)
return ctx->engine()->throwTypeError();
QtObject *qt = o->as<QtObject>();
@@ -1284,7 +1308,7 @@ ReturnedValue QtObject::method_get_platform(CallContext *ctx)
ReturnedValue QtObject::method_get_application(CallContext *ctx)
{
// ### inefficient. Should be just a value based getter
- Object *o = ctx->thisObject().asObject();
+ Object *o = ctx->thisObject().as<Object>();
if (!o)
return ctx->engine()->throwTypeError();
QtObject *qt = o->as<QtObject>();
@@ -1313,10 +1337,9 @@ ReturnedValue QtObject::method_get_styleHints(CallContext *ctx)
}
-QV4::Heap::ConsoleObject::ConsoleObject(ExecutionEngine *v4)
- : Heap::Object(v4)
+QV4::Heap::ConsoleObject::ConsoleObject()
{
- QV4::Scope scope(v4);
+ QV4::Scope scope(internalClass->engine);
QV4::ScopedObject o(scope, this);
o->defineDefaultProperty(QStringLiteral("debug"), QV4::ConsoleObject::method_log);
@@ -1353,12 +1376,12 @@ static QString jsStack(QV4::ExecutionEngine *engine) {
QString stackFrame;
if (frame.column >= 0)
- stackFrame = QString::fromLatin1("%1 (%2:%3:%4)").arg(frame.function,
+ stackFrame = QStringLiteral("%1 (%2:%3:%4)").arg(frame.function,
frame.source,
QString::number(frame.line),
QString::number(frame.column));
else
- stackFrame = QString::fromLatin1("%1 (%2:%3)").arg(frame.function,
+ stackFrame = QStringLiteral("%1 (%2:%3)").arg(frame.function,
frame.source,
QString::number(frame.line));
@@ -1379,38 +1402,41 @@ static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, CallContext *c
if (i != 0)
result.append(QLatin1Char(' '));
- if (ctx->args()[i].asArrayObject())
- result.append(QStringLiteral("[") + ctx->args()[i].toQStringNoThrow() + QStringLiteral("]"));
+ if (ctx->args()[i].as<ArrayObject>())
+ result.append(QLatin1Char('[') + ctx->args()[i].toQStringNoThrow() + QLatin1Char(']'));
else
result.append(ctx->args()[i].toQStringNoThrow());
}
if (printStack) {
- result.append(QLatin1String("\n"));
+ result.append(QLatin1Char('\n'));
result.append(jsStack(v4));
}
- static QLoggingCategory loggingCategory("qml");
+ static QLoggingCategory qmlLoggingCategory("qml");
+ static QLoggingCategory jsLoggingCategory("js");
+
+ QLoggingCategory *loggingCategory = v4->qmlEngine() ? &qmlLoggingCategory : &jsLoggingCategory;
QV4::StackFrame frame = v4->currentStackFrame();
const QByteArray baSource = frame.source.toUtf8();
const QByteArray baFunction = frame.function.toUtf8();
- QMessageLogger logger(baSource.constData(), frame.line, baFunction.constData(), loggingCategory.categoryName());
+ QMessageLogger logger(baSource.constData(), frame.line, baFunction.constData(), loggingCategory->categoryName());
switch (logType) {
case Log:
- if (loggingCategory.isDebugEnabled())
+ if (loggingCategory->isDebugEnabled())
logger.debug("%s", result.toUtf8().constData());
break;
case Info:
- if (loggingCategory.isInfoEnabled())
+ if (loggingCategory->isInfoEnabled())
logger.info("%s", result.toUtf8().constData());
break;
case Warn:
- if (loggingCategory.isWarningEnabled())
+ if (loggingCategory->isWarningEnabled())
logger.warning("%s", result.toUtf8().constData());
break;
case Error:
- if (loggingCategory.isCriticalEnabled())
+ if (loggingCategory->isCriticalEnabled())
logger.critical("%s", result.toUtf8().constData());
break;
default:
@@ -1442,14 +1468,18 @@ QV4::ReturnedValue ConsoleObject::method_profile(CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->d()->engine;
+ if (!v4->qmlEngine())
+ return QV4::Encode::undefined(); // Not yet implemented for JavaScript.
+
QV4::StackFrame frame = v4->currentStackFrame();
const QByteArray baSource = frame.source.toUtf8();
const QByteArray baFunction = frame.function.toUtf8();
QMessageLogger logger(baSource.constData(), frame.line, baFunction.constData());
- if (!QQmlDebugService::isDebuggingEnabled()) {
+ QQmlProfilerService *service = QQmlDebugConnector::service<QQmlProfilerService>();
+ if (!service) {
logger.warning("Cannot start profiling because debug service is disabled. Start with -qmljsdebugger=port:XXXXX.");
} else {
- QQmlProfilerService::instance()->startProfiling(v4->qmlEngine());
+ service->startProfiling(v4->qmlEngine());
logger.debug("Profiling started.");
}
@@ -1460,15 +1490,19 @@ QV4::ReturnedValue ConsoleObject::method_profileEnd(CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->d()->engine;
+ if (!v4->qmlEngine())
+ return QV4::Encode::undefined(); // Not yet implemented for JavaScript.
+
QV4::StackFrame frame = v4->currentStackFrame();
const QByteArray baSource = frame.source.toUtf8();
const QByteArray baFunction = frame.function.toUtf8();
QMessageLogger logger(baSource.constData(), frame.line, baFunction.constData());
- if (!QQmlDebugService::isDebuggingEnabled()) {
+ QQmlProfilerService *service = QQmlDebugConnector::service<QQmlProfilerService>();
+ if (!service) {
logger.warning("Ignoring console.profileEnd(): the debug service is disabled.");
} else {
- QQmlProfilerService::instance()->stopProfiling(v4->qmlEngine());
+ service->stopProfiling(v4->qmlEngine());
logger.debug("Profiling ended.");
}
@@ -1588,31 +1622,36 @@ QV4::ReturnedValue ConsoleObject::method_exception(CallContext *ctx)
-void QV4::GlobalExtensions::init(QQmlEngine *qmlEngine, Object *globalObject)
+void QV4::GlobalExtensions::init(Object *globalObject, QJSEngine::Extensions extensions)
{
ExecutionEngine *v4 = globalObject->engine();
Scope scope(v4);
-#ifndef QT_NO_TRANSLATION
- globalObject->defineDefaultProperty(QStringLiteral("qsTranslate"), method_qsTranslate);
- globalObject->defineDefaultProperty(QStringLiteral("QT_TRANSLATE_NOOP"), method_qsTranslateNoOp);
- globalObject->defineDefaultProperty(QStringLiteral("qsTr"), method_qsTr);
- globalObject->defineDefaultProperty(QStringLiteral("QT_TR_NOOP"), method_qsTrNoOp);
- globalObject->defineDefaultProperty(QStringLiteral("qsTrId"), method_qsTrId);
- globalObject->defineDefaultProperty(QStringLiteral("QT_TRID_NOOP"), method_qsTrIdNoOp);
-#endif
+ if (extensions.testFlag(QJSEngine::TranslationExtension)) {
+ #ifndef QT_NO_TRANSLATION
+ globalObject->defineDefaultProperty(QStringLiteral("qsTranslate"), QV4::GlobalExtensions::method_qsTranslate);
+ globalObject->defineDefaultProperty(QStringLiteral("QT_TRANSLATE_NOOP"), QV4::GlobalExtensions::method_qsTranslateNoOp);
+ globalObject->defineDefaultProperty(QStringLiteral("qsTr"), QV4::GlobalExtensions::method_qsTr);
+ globalObject->defineDefaultProperty(QStringLiteral("QT_TR_NOOP"), QV4::GlobalExtensions::method_qsTrNoOp);
+ globalObject->defineDefaultProperty(QStringLiteral("qsTrId"), QV4::GlobalExtensions::method_qsTrId);
+ globalObject->defineDefaultProperty(QStringLiteral("QT_TRID_NOOP"), QV4::GlobalExtensions::method_qsTrIdNoOp);
+
+ // string prototype extension
+ scope.engine->stringPrototype()->defineDefaultProperty(QStringLiteral("arg"), QV4::GlobalExtensions::method_string_arg);
+ #endif
+ }
- globalObject->defineDefaultProperty(QStringLiteral("print"), ConsoleObject::method_log);
- globalObject->defineDefaultProperty(QStringLiteral("gc"), method_gc);
+ if (extensions.testFlag(QJSEngine::ConsoleExtension)) {
+ globalObject->defineDefaultProperty(QStringLiteral("print"), QV4::ConsoleObject::method_log);
- ScopedObject console(scope, v4->memoryManager->alloc<QV4::ConsoleObject>(v4));
- globalObject->defineDefaultProperty(QStringLiteral("console"), console);
- ScopedObject qt(scope, v4->memoryManager->alloc<QV4::QtObject>(v4, qmlEngine));
- globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt);
+ QV4::ScopedObject console(scope, globalObject->engine()->memoryManager->allocObject<QV4::ConsoleObject>());
+ globalObject->defineDefaultProperty(QStringLiteral("console"), console);
+ }
- // string prototype extension
- v4->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("arg"), method_string_arg);
+ if (extensions.testFlag(QJSEngine::GarbageCollectionExtension)) {
+ globalObject->defineDefaultProperty(QStringLiteral("gc"), QV4::GlobalExtensions::method_gc);
+ }
}
@@ -1726,18 +1765,17 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx)
V4THROW_ERROR("qsTr(): third argument (n) must be a number");
Scope scope(ctx);
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
QString context;
- if (QQmlContextData *ctxt = v8engine->callingContext()) {
+ if (QQmlContextData *ctxt = scope.engine->callingQmlContext()) {
QString path = ctxt->urlString();
int lastSlash = path.lastIndexOf(QLatin1Char('/'));
int lastDot = path.lastIndexOf(QLatin1Char('.'));
int length = lastDot - (lastSlash + 1);
context = (lastSlash > -1) ? path.mid(lastSlash + 1, (length > -1) ? length : -1) : QString();
- } else if (ctx->d()->parent) {
- ScopedContext parentCtx(scope, ctx->d()->parent);
+ } else {
+ ExecutionContext *parentCtx = scope.engine->parentContext(ctx);
// The first non-empty source URL in the call stack determines the translation context.
- while (parentCtx && context.isEmpty()) {
+ while (!!parentCtx && context.isEmpty()) {
if (QV4::CompiledData::CompilationUnit *unit = parentCtx->d()->compilationUnit) {
QString fileName = unit->fileName();
QUrl url(unit->fileName());
@@ -1750,7 +1788,7 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx)
}
context = QFileInfo(context).baseName();
}
- parentCtx = parentCtx->d()->parent;
+ parentCtx = scope.engine->parentContext(parentCtx);
}
}
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index b78375118b..d373fb6ee6 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -47,6 +47,7 @@
#include <private/qqmlglobal_p.h>
#include <private/qv4functionobject_p.h>
+#include <private/qjsengine_p.h>
QT_BEGIN_NAMESPACE
@@ -58,18 +59,18 @@ namespace QV4 {
namespace Heap {
struct QtObject : Object {
- QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine);
+ QtObject(QQmlEngine *qmlEngine);
QObject *platform;
QObject *application;
};
struct ConsoleObject : Object {
- ConsoleObject(ExecutionEngine *engine);
+ ConsoleObject();
};
struct QQmlBindingFunction : FunctionObject {
- QQmlBindingFunction(QV4::FunctionObject *originalFunction);
- FunctionObject *originalFunction;
+ QQmlBindingFunction(const QV4::FunctionObject *originalFunction);
+ Pointer<FunctionObject> originalFunction;
// Set when the binding is created later
QQmlSourceLocation bindingLocation;
};
@@ -142,7 +143,7 @@ struct ConsoleObject : Object
};
struct GlobalExtensions {
- static void init(QQmlEngine *qmlEngine, Object *globalObject);
+ static void init(Object *globalObject, QJSEngine::Extensions extensions);
#ifndef QT_NO_TRANSLATION
static ReturnedValue method_qsTranslate(CallContext *ctx);
@@ -166,7 +167,7 @@ struct QQmlBindingFunction : public QV4::FunctionObject
void initBindingLocation(); // from caller stack trace
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
diff --git a/src/qml/qml/v8/qv4domerrors.cpp b/src/qml/qml/v8/qv4domerrors.cpp
index c318e2e550..1baaa113aa 100644
--- a/src/qml/qml/v8/qv4domerrors.cpp
+++ b/src/qml/qml/v8/qv4domerrors.cpp
@@ -59,7 +59,7 @@ void qt_add_domexceptions(ExecutionEngine *e)
domexception->defineReadonlyProperty(QStringLiteral("INVALID_ACCESS_ERR"), Primitive::fromInt32(DOMEXCEPTION_INVALID_ACCESS_ERR));
domexception->defineReadonlyProperty(QStringLiteral("VALIDATION_ERR"), Primitive::fromInt32(DOMEXCEPTION_VALIDATION_ERR));
domexception->defineReadonlyProperty(QStringLiteral("TYPE_MISMATCH_ERR"), Primitive::fromInt32(DOMEXCEPTION_TYPE_MISMATCH_ERR));
- e->globalObject()->defineDefaultProperty(QStringLiteral("DOMException"), domexception);
+ e->globalObject->defineDefaultProperty(QStringLiteral("DOMException"), domexception);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/v8/qv4sqlerrors.cpp b/src/qml/qml/v8/qv4sqlerrors.cpp
index b7a5b71540..c61e57560d 100644
--- a/src/qml/qml/v8/qv4sqlerrors.cpp
+++ b/src/qml/qml/v8/qv4sqlerrors.cpp
@@ -51,7 +51,7 @@ void qt_add_sqlexceptions(QV4::ExecutionEngine *engine)
sqlexception->defineReadonlyProperty(QStringLiteral("SYNTAX_ERR"), Primitive::fromInt32(SQLEXCEPTION_SYNTAX_ERR));
sqlexception->defineReadonlyProperty(QStringLiteral("CONSTRAINT_ERR"), Primitive::fromInt32(SQLEXCEPTION_CONSTRAINT_ERR));
sqlexception->defineReadonlyProperty(QStringLiteral("TIMEOUT_ERR"), Primitive::fromInt32(SQLEXCEPTION_TIMEOUT_ERR));
- engine->globalObject()->defineDefaultProperty(QStringLiteral("SQLException"), sqlexception);
+ engine->globalObject->defineDefaultProperty(QStringLiteral("SQLException"), sqlexception);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index a7c63c9df1..dae932e705 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -61,7 +61,7 @@
#include <QtCore/qdatastream.h>
#include <private/qsimd_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4dateobject_p.h>
#include <private/qv4objectiterator_p.h>
#include <private/qv4mm_p.h>
@@ -171,15 +171,13 @@ const QSet<QString> &QV8Engine::illegalNames() const
return m_illegalNames;
}
-QQmlContextData *QV8Engine::callingContext()
-{
- return QV4::QmlContextWrapper::callingContext(m_v4Engine);
-}
-
void QV8Engine::initializeGlobal()
{
QV4::Scope scope(m_v4Engine);
- QV4::GlobalExtensions::init(m_engine, m_v4Engine->globalObject());
+ QV4::GlobalExtensions::init(m_v4Engine->globalObject, QJSEngine::AllExtensions);
+
+ QV4::ScopedObject qt(scope, m_v4Engine->memoryManager->allocObject<QV4::QtObject>(m_engine));
+ m_v4Engine->globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt);
QQmlLocale::registerStringLocaleCompare(m_v4Engine);
QQmlDateExtension::registerExtension(m_v4Engine);
@@ -191,46 +189,52 @@ void QV8Engine::initializeGlobal()
qt_add_sqlexceptions(m_v4Engine);
{
- for (uint i = 0; i < m_v4Engine->globalObject()->internalClass()->size; ++i) {
- if (m_v4Engine->globalObject()->internalClass()->nameMap.at(i))
- m_illegalNames.insert(m_v4Engine->globalObject()->internalClass()->nameMap.at(i)->string);
+ for (uint i = 0; i < m_v4Engine->globalObject->internalClass()->size; ++i) {
+ if (m_v4Engine->globalObject->internalClass()->nameMap.at(i))
+ m_illegalNames.insert(m_v4Engine->globalObject->internalClass()->nameMap.at(i)->string);
}
}
+}
- {
-#define FREEZE_SOURCE "(function freeze_recur(obj) { "\
- " if (Qt.isQtObject(obj)) return;"\
- " if (obj != Function.connect && obj != Function.disconnect && "\
- " obj instanceof Object) {"\
- " var properties = Object.getOwnPropertyNames(obj);"\
- " for (var prop in properties) { "\
- " if (prop == \"connect\" || prop == \"disconnect\") {"\
- " Object.freeze(obj[prop]); "\
- " continue;"\
- " }"\
- " freeze_recur(obj[prop]);"\
- " }"\
- " }"\
- " if (obj instanceof Object) {"\
- " Object.freeze(obj);"\
- " }"\
- "})"
-
- QV4::ScopedFunctionObject result(scope, QV4::Script::evaluate(m_v4Engine, QString::fromUtf8(FREEZE_SOURCE), 0));
- Q_ASSERT(!!result);
- m_freezeObject.set(scope.engine, result);
-#undef FREEZE_SOURCE
+static void freeze_recursive(QV4::ExecutionEngine *v4, QV4::Object *object)
+{
+ if (object->as<QV4::QObjectWrapper>())
+ return;
+
+ QV4::Scope scope(v4);
+
+ bool instanceOfObject = false;
+ QV4::ScopedObject p(scope, object->prototype());
+ while (p) {
+ if (p->d() == v4->objectPrototype()->d()) {
+ instanceOfObject = true;
+ break;
+ }
+ p = p->prototype();
+ }
+ if (!instanceOfObject)
+ return;
+
+ QV4::InternalClass *frozen = object->internalClass()->propertiesFrozen();
+ if (object->internalClass() == frozen)
+ return;
+ object->setInternalClass(frozen);
+
+ QV4::ScopedObject o(scope);
+ for (uint i = 0; i < frozen->size; ++i) {
+ if (!frozen->nameMap.at(i))
+ continue;
+ o = *object->propertyData(i);
+ if (o)
+ freeze_recursive(v4, o);
}
}
void QV8Engine::freezeObject(const QV4::Value &value)
{
QV4::Scope scope(m_v4Engine);
- QV4::ScopedFunctionObject f(scope, m_freezeObject.value());
- QV4::ScopedCallData callData(scope, 1);
- callData->args[0] = value;
- callData->thisObject = m_v4Engine->globalObject();
- f->call(callData);
+ QV4::ScopedObject o(scope, value);
+ freeze_recursive(m_v4Engine, o);
}
struct QV8EngineRegistrationData
@@ -266,9 +270,7 @@ void QV8Engine::setExtensionData(int index, Deletable *data)
void QV8Engine::initQmlGlobalObject()
{
initializeGlobal();
- QV4::Scope scope(m_v4Engine);
- QV4::ScopedValue v(scope, m_v4Engine->globalObject());
- freezeObject(v);
+ freezeObject(*m_v4Engine->globalObject);
}
void QV8Engine::setEngine(QQmlEngine *engine)
@@ -279,7 +281,7 @@ void QV8Engine::setEngine(QQmlEngine *engine)
QV4::ReturnedValue QV8Engine::global()
{
- return m_v4Engine->globalObject()->asReturnedValue();
+ return m_v4Engine->globalObject->asReturnedValue();
}
void QV8Engine::startTimer(const QString &timerName)
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index fb538772d1..552470c88c 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -60,9 +60,10 @@
#include <private/qqmlpropertycache_p.h>
#include <private/qv4qobjectwrapper_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
#include <private/qv4identifier_p.h>
+#include <private/qqmlcontextwrapper_p.h>
QT_BEGIN_NAMESPACE
@@ -101,26 +102,24 @@ namespace QV4 {
return rv; \
} \
-// Used to allow a QObject method take and return raw V8 handles without having to expose
-// v8 in the public API.
+// Used to allow a QObject method take and return raw V4 handles without having to expose
+// 48 in the public API.
// Use like this:
// class MyClass : public QObject {
// Q_OBJECT
// ...
-// Q_INVOKABLE void myMethod(QQmlV8Function*);
+// Q_INVOKABLE void myMethod(QQmlV4Function*);
// };
// The QQmlV8Function - and consequently the arguments and return value - only remains
// valid during the call. If the return value isn't set within myMethod(), the will return
// undefined.
class QV8Engine;
-// ### GC
+
class QQmlV4Function
{
public:
int length() const { return callData->argc; }
QV4::ReturnedValue operator[](int idx) { return (idx < callData->argc ? callData->args[idx].asReturnedValue() : QV4::Encode::undefined()); }
- QQmlContextData *context() { return ctx; }
- QV4::ReturnedValue qmlGlobal() { return callData->thisObject.asReturnedValue(); }
void setReturnValue(QV4::ReturnedValue rv) { *retVal = rv; }
QV4::ExecutionEngine *v4engine() const { return e; }
private:
@@ -129,16 +128,14 @@ private:
QQmlV4Function(const QQmlV4Function &);
QQmlV4Function &operator=(const QQmlV4Function &);
- QQmlV4Function(QV4::CallData *callData, QV4::Value *retVal,
- const QV4::Value &global, QQmlContextData *c, QV4::ExecutionEngine *e)
- : callData(callData), retVal(retVal), ctx(c), e(e)
+ QQmlV4Function(QV4::CallData *callData, QV4::Value *retVal, QV4::ExecutionEngine *e)
+ : callData(callData), retVal(retVal), e(e)
{
- callData->thisObject.val = global.asReturnedValue();
+ callData->thisObject = QV4::Encode::undefined();
}
QV4::CallData *callData;
QV4::Value *retVal;
- QQmlContextData *ctx;
QV4::ExecutionEngine *e;
};
@@ -163,8 +160,6 @@ class QQmlContextData;
class Q_QML_PRIVATE_EXPORT QV8Engine
{
friend class QJSEngine;
- // ### GC
- typedef QSet<QV4::Heap::Object *> V8ObjectSet;
public:
static QV8Engine* get(QJSEngine* q) { Q_ASSERT(q); return q->handle(); }
// static QJSEngine* get(QV8Engine* d) { Q_ASSERT(d); return d->q; }
@@ -192,8 +187,6 @@ public:
Deletable *listModelData() { return m_listModelData; }
void setListModelData(Deletable *d) { if (m_listModelData) delete m_listModelData; m_listModelData = d; }
- QQmlContextData *callingContext();
-
void freezeObject(const QV4::Value &value);
// Return the network access manager for this engine. By default this returns the network
@@ -224,8 +217,6 @@ protected:
QV4::ExecutionEngine *m_v4Engine;
- QV4::PersistentValue m_freezeObject;
-
void *m_xmlHttpRequestData;
QVector<Deletable *> m_extensionData;
diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp
index 7814fa6d56..45b7edd316 100644
--- a/src/qml/types/qqmlbind.cpp
+++ b/src/qml/types/qqmlbind.cpp
@@ -36,6 +36,7 @@
#include <private/qqmlnullablevalue_p.h>
#include <private/qqmlproperty_p.h>
#include <private/qqmlbinding_p.h>
+#include <private/qqmlmetatype_p.h>
#include <qqmlengine.h>
#include <qqmlcontext.h>
@@ -52,8 +53,8 @@ QT_BEGIN_NAMESPACE
class QQmlBindPrivate : public QObjectPrivate
{
public:
- QQmlBindPrivate() : componentComplete(true), obj(0), prevBind(0) {}
- ~QQmlBindPrivate() { if (prevBind) prevBind->destroy(); }
+ QQmlBindPrivate() : componentComplete(true), obj(0) {}
+ ~QQmlBindPrivate() { }
QQmlNullableValue<bool> when;
bool componentComplete;
@@ -61,74 +62,82 @@ public:
QString propName;
QQmlNullableValue<QVariant> value;
QQmlProperty prop;
- QQmlAbstractBinding *prevBind;
+ QQmlAbstractBinding::Ptr prevBind;
+
+ void validate(QObject *binding) const;
};
+void QQmlBindPrivate::validate(QObject *binding) const
+{
+ if (!obj)
+ return;
+
+ if (!prop.isValid()) {
+ qmlInfo(binding) << "Property '" << propName << "' does not exist on " << QQmlMetaType::prettyTypeName(obj) << ".";
+ return;
+ }
+
+ if (!prop.isWritable()) {
+ qmlInfo(binding) << "Property '" << propName << "' on " << QQmlMetaType::prettyTypeName(obj) << " is read-only.";
+ return;
+ }
+}
/*!
\qmltype Binding
\instantiates QQmlBind
\inqmlmodule QtQml
\ingroup qtquick-interceptors
- \brief Enables the arbitrary creation of property bindings
+ \brief Enables the arbitrary creation of property bindings.
- \section1 Binding to an Inaccessible Property
+ In QML, property bindings result in a dependency between the properties of
+ different objects.
- Sometimes it is necessary to bind to a property of an object that wasn't
- directly instantiated by QML - generally a property of a class exported
- to QML by C++. In these cases, regular property binding doesn't work. Binding
- allows you to bind any value to any property.
+ \section1 Binding to an inaccessible property
+
+ Sometimes it is necessary to bind an object's property to
+ that of another object that isn't directly instantiated by QML, such as a
+ property of a class exported to QML by C++. You can use the Binding type
+ to establish this dependency; binding any value to any object's property.
+
+ For example, in a C++ application that maps an "app.enteredText" property
+ into QML, you can use Binding to update the enteredText property.
- For example, imagine a C++ application that maps an "app.enteredText"
- property into QML. You could use Binding to update the enteredText property
- like this.
\code
TextEdit { id: myTextField; text: "Please type here..." }
Binding { target: app; property: "enteredText"; value: myTextField.text }
\endcode
- Whenever the text in the TextEdit is updated, the C++ property will be
- updated also.
- \section1 "Single-branch" conditional binding
+ When \c{text} changes, the C++ property \c{enteredText} will update
+ automatically.
- In some circumstances you may want to control the value of a property
- only when a certain condition is true (and relinquish control in all
- other circumstances). This often isn't possible to accomplish with a direct
- binding, as you need to supply values for all possible branches.
+ \section1 Conditional bindings
- \code
+ In some cases you may want to modify the value of a property when a certain
+ condition is met but leave it unmodified otherwise. Often, it's not possible
+ to do this with direct bindings, as you have to supply values for all
+ possible branches.
+
+ For example, the code snippet below results in a warning whenever you
+ release the mouse. This is because the value of the binding is undefined
+ when the mouse isn't pressed.
+
+ \qml
// produces warning: "Unable to assign [undefined] to double value"
value: if (mouse.pressed) mouse.mouseX
- \endcode
+ \endqml
- The above example will produce a warning whenever we release the mouse, as the value
- of the binding is undefined when the mouse isn't pressed. We can use the Binding
- type to rewrite the above code and avoid the warning.
+ The Binding type can prevent this warning.
- \code
+ \qml
Binding on value {
when: mouse.pressed
value: mouse.mouseX
}
- \endcode
-
- The Binding type will also restore any previously set direct bindings on
- the property. In that sense, it functions much like a simplified State.
-
- \qml
- // this is equivalent to the above Binding
- State {
- name: "pressed"
- when: mouse.pressed
- PropertyChanges {
- target: obj
- value: mouse.mouseX
- }
- }
\endqml
- If the binding target or binding property is changed, the bound value is
- immediately pushed onto the new target.
+ The Binding type restores any previously set direct bindings on the
+ property.
\sa {Qt QML}
*/
@@ -195,8 +204,10 @@ void QQmlBind::setObject(QObject *obj)
d->when = true;
}
d->obj = obj;
- if (d->componentComplete)
+ if (d->componentComplete) {
d->prop = QQmlProperty(d->obj, d->propName);
+ d->validate(this);
+ }
eval();
}
@@ -204,6 +215,23 @@ void QQmlBind::setObject(QObject *obj)
\qmlproperty string QtQml::Binding::property
The property to be updated.
+
+ This can be a group property if the expression results in accessing a
+ property of a \l {QML Basic Types}{value type}. For example:
+
+ \qml
+ Item {
+ id: item
+
+ property rect rectangle: Qt.rect(0, 0, 200, 200)
+ }
+
+ Binding {
+ target: item
+ property: "rectangle.x"
+ value: 100
+ }
+ \endqml
*/
QString QQmlBind::property() const
{
@@ -222,8 +250,10 @@ void QQmlBind::setProperty(const QString &p)
d->when = true;
}
d->propName = p;
- if (d->componentComplete)
+ if (d->componentComplete) {
d->prop = QQmlProperty(d->obj, d->propName);
+ d->validate(this);
+ }
eval();
}
@@ -262,8 +292,10 @@ void QQmlBind::componentComplete()
{
Q_D(QQmlBind);
d->componentComplete = true;
- if (!d->prop.isValid())
+ if (!d->prop.isValid()) {
d->prop = QQmlProperty(d->obj, d->propName);
+ d->validate(this);
+ }
eval();
}
@@ -277,22 +309,17 @@ void QQmlBind::eval()
if (!d->when) {
//restore any previous binding
if (d->prevBind) {
- QQmlAbstractBinding *tmp = d->prevBind;
+ QQmlAbstractBinding::Ptr p = d->prevBind;
d->prevBind = 0;
- tmp = QQmlPropertyPrivate::setBinding(d->prop, tmp);
- if (tmp) //should this ever be true?
- tmp->destroy();
+ QQmlPropertyPrivate::setBinding(p.data());
}
return;
}
//save any set binding for restoration
- QQmlAbstractBinding *tmp;
- tmp = QQmlPropertyPrivate::setBinding(d->prop, 0);
- if (tmp && d->prevBind)
- tmp->destroy();
- else if (!d->prevBind)
- d->prevBind = tmp;
+ if (!d->prevBind)
+ d->prevBind = QQmlPropertyPrivate::binding(d->prop);
+ QQmlPropertyPrivate::removeBinding(d->prop);
}
d->prop.write(d->value.value);
diff --git a/src/qml/types/qqmlbind_p.h b/src/qml/types/qqmlbind_p.h
index 6d7eea4014..ac1cb0f32f 100644
--- a/src/qml/types/qqmlbind_p.h
+++ b/src/qml/types/qqmlbind_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLBIND_H
#define QQMLBIND_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include <QtCore/qobject.h>
diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp
index 0c81855e49..6a93410ecb 100644
--- a/src/qml/types/qqmlconnections.cpp
+++ b/src/qml/types/qqmlconnections.cpp
@@ -165,7 +165,7 @@ void QQmlConnections::setTarget(QObject *obj)
foreach (QQmlBoundSignal *s, d->boundsignals) {
// It is possible that target is being changed due to one of our signal
// handlers -> use deleteLater().
- if (s->isEvaluating())
+ if (s->isNotifying())
(new QQmlBoundSignalDeleter(s))->deleteLater();
else
delete s;
diff --git a/src/qml/types/qqmlconnections_p.h b/src/qml/types/qqmlconnections_p.h
index 170f47b54f..234c5061a7 100644
--- a/src/qml/types/qqmlconnections_p.h
+++ b/src/qml/types/qqmlconnections_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLCONNECTIONS_H
#define QQMLCONNECTIONS_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include <private/qqmlcustomparser_p.h>
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index 201fd4572c..f2de911725 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -44,7 +44,7 @@
#include <private/qqmlincubator_p.h>
#include <private/qqmlcompiler_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
#include <qv4objectiterator_p.h>
@@ -64,13 +64,13 @@ struct DelegateModelGroupFunction : FunctionObject {
};
struct QQmlDelegateModelGroupChange : Object {
- QQmlDelegateModelGroupChange(QV4::ExecutionEngine *engine);
+ QQmlDelegateModelGroupChange() {}
QQmlChangeSet::Change change;
};
struct QQmlDelegateModelGroupChangeArray : Object {
- QQmlDelegateModelGroupChangeArray(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes);
+ QQmlDelegateModelGroupChangeArray(const QVector<QQmlChangeSet::Change> &changes);
QVector<QQmlChangeSet::Change> changes;
};
@@ -83,19 +83,14 @@ struct DelegateModelGroupFunction : QV4::FunctionObject
static Heap::DelegateModelGroupFunction *create(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg))
{
- return scope->engine()->memoryManager->alloc<DelegateModelGroupFunction>(scope, flag, code);
+ return scope->engine()->memoryManager->allocObject<DelegateModelGroupFunction>(scope, flag, code);
}
- static QV4::ReturnedValue construct(QV4::Managed *m, QV4::CallData *)
+ static QV4::ReturnedValue call(const QV4::Managed *that, QV4::CallData *callData)
{
- return static_cast<DelegateModelGroupFunction *>(m)->engine()->throwTypeError();
- }
-
- static QV4::ReturnedValue call(QV4::Managed *that, QV4::CallData *callData)
- {
- QV4::ExecutionEngine *v4 = static_cast<DelegateModelGroupFunction *>(that)->engine();
+ QV4::ExecutionEngine *v4 = static_cast<const DelegateModelGroupFunction *>(that)->engine();
QV4::Scope scope(v4);
- QV4::Scoped<DelegateModelGroupFunction> f(scope, static_cast<DelegateModelGroupFunction *>(that));
+ QV4::Scoped<DelegateModelGroupFunction> f(scope, static_cast<const DelegateModelGroupFunction *>(that));
QV4::Scoped<QQmlDelegateModelItemObject> o(scope, callData->thisObject);
if (!o)
return v4->throwTypeError(QStringLiteral("Not a valid VisualData object"));
@@ -1062,7 +1057,7 @@ int QQmlDelegateModel::indexOf(QObject *item, QObject *) const
return -1;
}
-void QQmlDelegateModel::setWatchedRoles(QList<QByteArray> roles)
+void QQmlDelegateModel::setWatchedRoles(const QList<QByteArray> &roles)
{
Q_D(QQmlDelegateModel);
d->m_adaptorModel.replaceWatchedRoles(d->m_watchedRoles, roles);
@@ -1637,7 +1632,7 @@ bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const
if (!object.isObject())
return false;
- QV4::ExecutionEngine *v4 = object.asObject()->engine();
+ QV4::ExecutionEngine *v4 = object.as<QV4::Object>()->engine();
QV4::Scope scope(v4);
QV4::ScopedObject o(scope, object);
if (!o)
@@ -1722,7 +1717,7 @@ void QQmlDelegateModelItemMetaType::initializePrototype()
s = v4->newString(QStringLiteral("isUnresolved"));
QV4::ScopedFunctionObject f(scope);
- QV4::ScopedContext global(scope, scope.engine->rootContext());
+ QV4::ExecutionContext *global = scope.engine->rootContext();
p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, 30, QQmlDelegateModelItem::get_member)));
p->setSetter(0);
proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
@@ -2493,7 +2488,7 @@ QQmlV4Handle QQmlDelegateModelGroup::get(int index)
QV8Engine *v8 = model->m_cacheMetaType->v8Engine;
QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8);
QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, v4->memoryManager->alloc<QQmlDelegateModelItemObject>(v4, cacheItem));
+ QV4::ScopedObject o(scope, v4->memoryManager->allocObject<QQmlDelegateModelItemObject>(cacheItem));
QV4::ScopedObject p(scope, model->m_cacheMetaType->modelItemProto.value());
o->setPrototype(p);
++cacheItem->scriptRef;
@@ -2511,7 +2506,7 @@ bool QQmlDelegateModelGroupPrivate::parseIndex(const QV4::Value &value, int *ind
if (!value.isObject())
return false;
- QV4::ExecutionEngine *v4 = value.asObject()->engine();
+ QV4::ExecutionEngine *v4 = value.as<QV4::Object>()->engine();
QV4::Scope scope(v4);
QV4::Scoped<QQmlDelegateModelItemObject> object(scope, value);
@@ -2579,9 +2574,9 @@ void QQmlDelegateModelGroup::insert(QQmlV4Function *args)
groups |= model->m_cacheMetaType->parseGroups(val);
}
- if (v->asArrayObject()) {
+ if (v->as<QV4::ArrayObject>()) {
return;
- } else if (v->asObject()) {
+ } else if (v->as<QV4::Object>()) {
model->insert(before, v, groups);
model->emitChanges();
}
@@ -2626,7 +2621,7 @@ void QQmlDelegateModelGroup::create(QQmlV4Function *args)
if (i < args->length() && index >= 0 && index <= model->m_compositor.count(group)) {
v = (*args)[i];
- if (v->asObject()) {
+ if (v->as<QV4::Object>()) {
int groups = 1 << d->group;
if (++i < args->length()) {
QV4::ScopedValue val(scope, (*args)[i]);
@@ -3190,7 +3185,7 @@ QString QQmlPartsModel::stringValue(int index, const QString &role)
return QQmlDelegateModelPrivate::get(m_model)->stringValue(m_compositorGroup, index, role);
}
-void QQmlPartsModel::setWatchedRoles(QList<QByteArray> roles)
+void QQmlPartsModel::setWatchedRoles(const QList<QByteArray> &roles)
{
QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
model->m_adaptorModel.replaceWatchedRoles(m_watchedRoles, roles);
@@ -3238,7 +3233,7 @@ struct QQmlDelegateModelGroupChange : QV4::Object
V4_OBJECT2(QQmlDelegateModelGroupChange, QV4::Object)
static QV4::Heap::QQmlDelegateModelGroupChange *create(QV4::ExecutionEngine *e) {
- return e->memoryManager->alloc<QQmlDelegateModelGroupChange>(e);
+ return e->memoryManager->allocObject<QQmlDelegateModelGroupChange>();
}
static QV4::ReturnedValue method_get_index(QV4::CallContext *ctx) {
@@ -3266,11 +3261,6 @@ struct QQmlDelegateModelGroupChange : QV4::Object
}
};
-QV4::Heap::QQmlDelegateModelGroupChange::QQmlDelegateModelGroupChange(QV4::ExecutionEngine *engine)
- : QV4::Heap::Object(engine)
-{
-}
-
DEFINE_OBJECT_VTABLE(QQmlDelegateModelGroupChange);
struct QQmlDelegateModelGroupChangeArray : public QV4::Object
@@ -3280,18 +3270,18 @@ struct QQmlDelegateModelGroupChangeArray : public QV4::Object
public:
static QV4::Heap::QQmlDelegateModelGroupChangeArray *create(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes)
{
- return engine->memoryManager->alloc<QQmlDelegateModelGroupChangeArray>(engine, changes);
+ return engine->memoryManager->allocObject<QQmlDelegateModelGroupChangeArray>(changes);
}
quint32 count() const { return d()->changes.count(); }
const QQmlChangeSet::Change &at(int index) const { return d()->changes.at(index); }
- static QV4::ReturnedValue getIndexed(QV4::Managed *m, uint index, bool *hasProperty)
+ static QV4::ReturnedValue getIndexed(const QV4::Managed *m, uint index, bool *hasProperty)
{
Q_ASSERT(m->as<QQmlDelegateModelGroupChangeArray>());
- QV4::ExecutionEngine *v4 = static_cast<QQmlDelegateModelGroupChangeArray *>(m)->engine();
+ QV4::ExecutionEngine *v4 = static_cast<const QQmlDelegateModelGroupChangeArray *>(m)->engine();
QV4::Scope scope(v4);
- QV4::Scoped<QQmlDelegateModelGroupChangeArray> array(scope, static_cast<QQmlDelegateModelGroupChangeArray *>(m));
+ QV4::Scoped<QQmlDelegateModelGroupChangeArray> array(scope, static_cast<const QQmlDelegateModelGroupChangeArray *>(m));
if (index >= array->count()) {
if (hasProperty)
@@ -3311,12 +3301,12 @@ public:
return object.asReturnedValue();
}
- static QV4::ReturnedValue get(QV4::Managed *m, QV4::String *name, bool *hasProperty)
+ static QV4::ReturnedValue get(const QV4::Managed *m, QV4::String *name, bool *hasProperty)
{
Q_ASSERT(m->as<QQmlDelegateModelGroupChangeArray>());
- QQmlDelegateModelGroupChangeArray *array = static_cast<QQmlDelegateModelGroupChangeArray *>(m);
+ const QQmlDelegateModelGroupChangeArray *array = static_cast<const QQmlDelegateModelGroupChangeArray *>(m);
- if (name->equals(array->engine()->id_length)) {
+ if (name->equals(array->engine()->id_length())) {
if (hasProperty)
*hasProperty = true;
return QV4::Encode(array->count());
@@ -3326,11 +3316,10 @@ public:
}
};
-QV4::Heap::QQmlDelegateModelGroupChangeArray::QQmlDelegateModelGroupChangeArray(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes)
- : QV4::Heap::Object(engine)
- , changes(changes)
+QV4::Heap::QQmlDelegateModelGroupChangeArray::QQmlDelegateModelGroupChangeArray(const QVector<QQmlChangeSet::Change> &changes)
+ : changes(changes)
{
- QV4::Scope scope(engine);
+ QV4::Scope scope(internalClass->engine);
QV4::ScopedObject o(scope, this);
o->setArrayType(QV4::Heap::ArrayData::Custom);
}
diff --git a/src/qml/types/qqmldelegatemodel_p.h b/src/qml/types/qqmldelegatemodel_p.h
index 5ebffd5b9d..6af052c1b4 100644
--- a/src/qml/types/qqmldelegatemodel_p.h
+++ b/src/qml/types/qqmldelegatemodel_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLDATAMODEL_P_H
#define QQMLDATAMODEL_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qtqmlglobal_p.h>
#include <private/qqmllistcompositor_p.h>
#include <private/qqmlobjectmodel_p.h>
@@ -96,7 +107,7 @@ public:
ReleaseFlags release(QObject *object);
void cancel(int index);
virtual QString stringValue(int index, const QString &role);
- virtual void setWatchedRoles(QList<QByteArray> roles);
+ virtual void setWatchedRoles(const QList<QByteArray> &roles);
int indexOf(QObject *object, QObject *objectContext) const;
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index dc289eb35e..3a19163cbd 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -154,7 +154,7 @@ protected:
namespace QV4 {
namespace Heap {
struct QQmlDelegateModelItemObject : Object {
- inline QQmlDelegateModelItemObject(QV4::ExecutionEngine *engine, QQmlDelegateModelItem *item);
+ inline QQmlDelegateModelItemObject(QQmlDelegateModelItem *item);
~QQmlDelegateModelItemObject();
QQmlDelegateModelItem *item;
};
@@ -168,9 +168,8 @@ struct QQmlDelegateModelItemObject : QV4::Object
V4_NEEDS_DESTROY
};
-QV4::Heap::QQmlDelegateModelItemObject::QQmlDelegateModelItemObject(QV4::ExecutionEngine *engine, QQmlDelegateModelItem *item)
- : QV4::Heap::Object(engine)
- , item(item)
+QV4::Heap::QQmlDelegateModelItemObject::QQmlDelegateModelItemObject(QQmlDelegateModelItem *item)
+ : item(item)
{
}
@@ -356,7 +355,7 @@ public:
ReleaseFlags release(QObject *item);
QString stringValue(int index, const QString &role);
QList<QByteArray> watchedRoles() const { return m_watchedRoles; }
- void setWatchedRoles(QList<QByteArray> roles);
+ void setWatchedRoles(const QList<QByteArray> &roles);
int indexOf(QObject *item, QObject *objectContext) const;
diff --git a/src/qml/types/qqmlinstantiator.cpp b/src/qml/types/qqmlinstantiator.cpp
index 735463a058..448a591e22 100644
--- a/src/qml/types/qqmlinstantiator.cpp
+++ b/src/qml/types/qqmlinstantiator.cpp
@@ -426,7 +426,7 @@ void QQmlInstantiator::setModel(const QVariant &v)
}
/*!
- \qmlproperty QtQml::QtObject QtQml::Instantiator::object
+ \qmlproperty QtObject QtQml::Instantiator::object
This is a reference to the first created object, intended as a convenience
for the case where only one object has been created.
@@ -440,7 +440,7 @@ QObject *QQmlInstantiator::object() const
}
/*!
- \qmlmethod QtQml::QtObject QtQml::Instantiator::objectAt
+ \qmlmethod QtObject QtQml::Instantiator::objectAt(int index)
Returns a reference to the object with the given \a index.
*/
diff --git a/src/qml/types/qqmlinstantiator_p.h b/src/qml/types/qqmlinstantiator_p.h
index aa098817cd..842a0b947b 100644
--- a/src/qml/types/qqmlinstantiator_p.h
+++ b/src/qml/types/qqmlinstantiator_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLINSTANTIATOR_P_H
#define QQMLINSTANTIATOR_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlparserstatus.h>
diff --git a/src/qml/types/qqmlitemmodels.qdoc b/src/qml/types/qqmlitemmodels.qdoc
index 4e64aaa338..6733330209 100644
--- a/src/qml/types/qqmlitemmodels.qdoc
+++ b/src/qml/types/qqmlitemmodels.qdoc
@@ -26,7 +26,8 @@
****************************************************************************/
/*!
- \chapter QModelIndex & Co. in QML
+ \page qmodelindex-and-related-classes-in-qml.html
+ \title QModelIndex and related Classes in QML
Since Qt 5.5, QModelIndex and QPersistentModelIndex are exposed in QML as
value-based types. Also exposed in a similar fashion are QModelIndexList,
@@ -34,15 +35,14 @@
be passed back and forth between QML and C++ as \c var properties or plain
JavaScript variables.
- We detail here which API all these classes get exposed in QML. Please refer
- to the C++ documentation for more information.
+ Below you will find an overview of the API exposed to QML for these classes.
+ For more information, refer to their C++ documentation.
- \note Since all these types are exposed as gadgets, there are no property
+ \note Since all these types are exposed as \l{Q_GADGET}{gadgets}, there are no property
change notification signals emitted. Therefore binding to their properties
may not give the expected results. This is especially true for QPersistentModelIndex.
- It is perfectly possible to bind to properties holding any of those types.
- \section1 \l QModelIndex and \l QPersistentModelIndex
+ \section1 QModelIndex and QPersistentModelIndex Types
\list
\li \b row : int
@@ -53,25 +53,25 @@
\li \b internalId : quint64
\endlist
- All these properties are read-only, as their C++ counterpart.
+ All these properties are read-only, as are their C++ counterparts.
\note The usual caveats apply to QModelIndex in QML. If the underlying model changes
or gets deleted, it may become dangerous to access its properties. Therefore, you
- should not store any QModelIndex. You can, however, store QPersistentModelIndexes
- in a safe way.
+ should not store any QModelIndex objects. You can, however, store QPersistentModelIndexe
+ objects in a safe way.
- \section1 QModelIndexList
+ \section1 QModelIndexList Type
\l QModelIndexList is exposed in QML as a JavaScript array. Conversions are
automatically made from and to C++. In fact, any JavaScript array can be
converted back to QModelIndexList, with non-QModelIndex objects replaced by
- invalid QModelIndexes.
+ invalid \l{QModelIndex}es.
\note QModelIndex to QPersistentModelIndex conversion happens when accessing
the array elements because any QModelIndexList property retains reference
semantics when exposed this way.
- \section1 \l QItemSelectionRange
+ \section1 \l QItemSelectionRange Type
\list
\li \b top : int
@@ -88,22 +88,22 @@
\li \b model : QAbstractItemModel
\endlist
- All these properties are read-only, as their C++ counterpart. In addition,
+ All these properties are read-only, as are their C++ counterparts. In addition,
we also expose the following functions:
\list
- \li bool \b{contains}(QModelIndex index)
- \li bool \b{contains}(int row, int column, QModelIndex parentIndex)
- \li bool \b{intersects}(QItemSelectionRange other)
- \li QItemSelectionRange \b{intersected}(QItemSelectionRange other)
+ \li bool \b{contains}(QModelIndex \e index)
+ \li bool \b{contains}(int \e row, int \e column, QModelIndex \e parentIndex)
+ \li bool \b{intersects}(QItemSelectionRange \e other)
+ \li QItemSelectionRange \b{intersected}(QItemSelectionRange \e other)
\endlist
- \section1 QItemSelection
+ \section1 QItemSelection Type
Similarly to QModelIndexList, \l QItemSelection is exposed in QML as a JavaScript
- array of QItemSelectionRanges. Conversions are automatically made from and to C++.
+ array of QItemSelectionRange objects. Conversions are automatically made from and to C++.
In fact, any JavaScript array can be converted back to QItemSelection, with
- non-QItemSelectionRange objects replaced by empty QItemSelectionRanges.
+ non-QItemSelectionRange objects replaced by empty \l {QItemSelectionRange}s.
\sa ItemSelectionModel
diff --git a/src/qml/types/qqmlitemselectionmodel.qdoc b/src/qml/types/qqmlitemselectionmodel.qdoc
index 02919b388e..c223ef614e 100644
--- a/src/qml/types/qqmlitemselectionmodel.qdoc
+++ b/src/qml/types/qqmlitemselectionmodel.qdoc
@@ -55,7 +55,7 @@
It will trigger property binding updates every time \l selectionChanged()
is emitted, even though its value hasn't changed.
- \sa selection(), selectedIndexes(), select(), selectionChanged()
+ \sa selection(), selectedIndexes, select(), selectionChanged()
*/
/*!
@@ -103,7 +103,7 @@
*/
/*!
- \qmlmethod QItemSelection selection()
+ \qmlmethod QItemSelection ItemSelectionModel::selection()
*/
/*!
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index ed97690adb..a4c0f7043f 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -88,7 +88,7 @@ const ListLayout::Role &ListLayout::getRoleOrCreate(const QString &key, Role::Da
if (node) {
const Role &r = *node->value;
if (type != r.type)
- qmlInfo(0) << QString::fromLatin1("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
+ qmlInfo(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
return r;
}
@@ -101,7 +101,7 @@ const ListLayout::Role &ListLayout::getRoleOrCreate(QV4::String *key, Role::Data
if (node) {
const Role &r = *node->value;
if (type != r.type)
- qmlInfo(0) << QString::fromLatin1("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
+ qmlInfo(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
return r;
}
@@ -150,7 +150,9 @@ const ListLayout::Role &ListLayout::createRole(const QString &key, ListLayout::R
ListLayout::ListLayout(const ListLayout *other) : currentBlock(0), currentBlockOffset(0)
{
- for (int i=0 ; i < other->roles.count() ; ++i) {
+ const int otherRolesCount = other->roles.count();
+ roles.reserve(otherRolesCount);
+ for (int i=0 ; i < otherRolesCount; ++i) {
Role *role = new Role(other->roles[i]);
roles.append(role);
roleHash.insert(role->name, role);
@@ -240,11 +242,12 @@ const ListLayout::Role *ListLayout::getExistingRole(QV4::String *key)
return r;
}
-ModelObject *ListModel::getOrCreateModelObject(QQmlListModel *model, int elementIndex)
+QObject *ListModel::getOrCreateModelObject(QQmlListModel *model, int elementIndex)
{
ListElement *e = elements[elementIndex];
if (e->m_objectCache == 0) {
- e->m_objectCache = new ModelObject(model, elementIndex);
+ e->m_objectCache = new QObject;
+ (void)new ModelNodeMetaObject(e->m_objectCache, model, elementIndex);
}
return e->m_objectCache;
}
@@ -315,8 +318,8 @@ void ListModel::sync(ListModel *src, ListModel *target, QHash<int, ListModel *>
// Update values stored in target meta objects
for (int i=0 ; i < target->elements.count() ; ++i) {
ListElement *e = target->elements[i];
- if (e->m_objectCache)
- e->m_objectCache->updateValues();
+ if (ModelNodeMetaObject *mo = e->objectCache())
+ mo->updateValues();
}
}
@@ -382,9 +385,8 @@ void ListModel::updateCacheIndices()
{
for (int i=0 ; i < elements.count() ; ++i) {
ListElement *e = elements.at(i);
- if (e->m_objectCache) {
- e->m_objectCache->m_elementIndex = i;
- }
+ if (ModelNodeMetaObject *mo = e->objectCache())
+ mo->m_elementIndex = i;
}
}
@@ -421,13 +423,13 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles)
int roleIndex = -1;
// Add the value now
- if (QV4::String *s = propertyValue->asString()) {
+ if (const QV4::String *s = propertyValue->as<QV4::String>()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::String);
roleIndex = e->setStringProperty(r, s->toQString());
} else if (propertyValue->isNumber()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Number);
roleIndex = e->setDoubleProperty(r, propertyValue->asDouble());
- } else if (QV4::ArrayObject *a = propertyValue->asArrayObject()) {
+ } else if (QV4::ArrayObject *a = propertyValue->as<QV4::ArrayObject>()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List);
ListModel *subModel = new ListModel(r.subLayout, 0, -1);
@@ -441,11 +443,11 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles)
} else if (propertyValue->isBoolean()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Bool);
roleIndex = e->setBoolProperty(r, propertyValue->booleanValue());
- } else if (QV4::DateObject *dd = propertyValue->asDateObject()) {
+ } else if (QV4::DateObject *dd = propertyValue->as<QV4::DateObject>()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime);
QDateTime dt = dd->toQDateTime();
roleIndex = e->setDateTimeProperty(r, dt);
- } else if (QV4::Object *o = propertyValue->asObject()) {
+ } else if (QV4::Object *o = propertyValue->as<QV4::Object>()) {
if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) {
QObject *o = wrapper->object();
const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::QObject);
@@ -468,9 +470,8 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles)
roles->append(roleIndex);
}
- if (e->m_objectCache) {
- e->m_objectCache->updateValues(*roles);
- }
+ if (ModelNodeMetaObject *mo = e->objectCache())
+ mo->updateValues(*roles);
}
void ListModel::set(int elementIndex, QV4::Object *object)
@@ -502,7 +503,7 @@ void ListModel::set(int elementIndex, QV4::Object *object)
if (r.type == ListLayout::Role::Number) {
e->setDoublePropertyFast(r, propertyValue->asDouble());
}
- } else if (QV4::ArrayObject *a = propertyValue->asArrayObject()) {
+ } else if (QV4::ArrayObject *a = propertyValue->as<QV4::ArrayObject>()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List);
if (r.type == ListLayout::Role::List) {
ListModel *subModel = new ListModel(r.subLayout, 0, -1);
@@ -520,13 +521,13 @@ void ListModel::set(int elementIndex, QV4::Object *object)
if (r.type == ListLayout::Role::Bool) {
e->setBoolPropertyFast(r, propertyValue->booleanValue());
}
- } else if (QV4::DateObject *date = propertyValue->asDateObject()) {
+ } else if (QV4::DateObject *date = propertyValue->as<QV4::DateObject>()) {
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime);
if (r.type == ListLayout::Role::DateTime) {
QDateTime dt = date->toQDateTime();;
e->setDateTimePropertyFast(r, dt);
}
- } else if (QV4::Object *o = propertyValue->asObject()) {
+ } else if (QV4::Object *o = propertyValue->as<QV4::Object>()) {
if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) {
QObject *o = wrapper->object();
const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::QObject);
@@ -589,10 +590,12 @@ int ListModel::setOrCreateProperty(int elementIndex, const QString &key, const Q
if (r) {
roleIndex = e->setVariantProperty(*r, data);
- if (roleIndex != -1 && e->m_objectCache) {
+ ModelNodeMetaObject *cache = e->objectCache();
+
+ if (roleIndex != -1 && cache) {
QVector<int> roles;
roles << roleIndex;
- e->m_objectCache->updateValues(roles);
+ cache->updateValues(roles);
}
}
}
@@ -631,6 +634,13 @@ inline char *ListElement::getPropertyMemory(const ListLayout::Role &role)
return mem;
}
+ModelNodeMetaObject *ListElement::objectCache()
+{
+ if (!m_objectCache)
+ return 0;
+ return ModelNodeMetaObject::get(m_objectCache);
+}
+
QString *ListElement::getStringProperty(const ListLayout::Role &role)
{
char *mem = getPropertyMemory(role);
@@ -1169,7 +1179,7 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d
roleIndex = setStringProperty(role, qstr);
} else if (d.isNumber()) {
roleIndex = setDoubleProperty(role, d.asDouble());
- } else if (d.asArrayObject()) {
+ } else if (d.as<QV4::ArrayObject>()) {
QV4::ScopedArrayObject a(scope, d);
if (role.type == ListLayout::Role::List) {
QV4::Scope scope(a->engine());
@@ -1183,11 +1193,11 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d
}
roleIndex = setListProperty(role, subModel);
} else {
- qmlInfo(0) << QString::fromLatin1("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(role.name).arg(roleTypeName(role.type)).arg(roleTypeName(ListLayout::Role::List));
+ qmlInfo(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(role.name).arg(roleTypeName(role.type)).arg(roleTypeName(ListLayout::Role::List));
}
} else if (d.isBoolean()) {
roleIndex = setBoolProperty(role, d.booleanValue());
- } else if (d.asDateObject()) {
+ } else if (d.as<QV4::DateObject>()) {
QV4::Scoped<QV4::DateObject> dd(scope, d);
QDateTime dt = dd->toQDateTime();
roleIndex = setDateTimeProperty(role, dt);
@@ -1207,15 +1217,48 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d
return roleIndex;
}
-ModelObject::ModelObject(QQmlListModel *model, int elementIndex)
-: m_model(model), m_elementIndex(elementIndex), m_meta(new ModelNodeMetaObject(this))
+ModelNodeMetaObject::ModelNodeMetaObject(QObject *object, QQmlListModel *model, int elementIndex)
+: QQmlOpenMetaObject(object), m_enabled(false), m_model(model), m_elementIndex(elementIndex), m_initialized(false)
+{}
+
+void ModelNodeMetaObject::initialize()
{
+ const int roleCount = m_model->m_listModel->roleCount();
+ QVector<QByteArray> properties;
+ properties.reserve(roleCount);
+ for (int i = 0 ; i < roleCount ; ++i) {
+ const ListLayout::Role &role = m_model->m_listModel->getExistingRole(i);
+ QByteArray name = role.name.toUtf8();
+ properties << name;
+ }
+ type()->createProperties(properties);
updateValues();
- setNodeUpdatesEnabled(true);
+ m_enabled = true;
+}
+
+ModelNodeMetaObject::~ModelNodeMetaObject()
+{
+}
+
+QAbstractDynamicMetaObject *ModelNodeMetaObject::toDynamicMetaObject(QObject *object)
+{
+ if (!m_initialized) {
+ m_initialized = true;
+ initialize();
+ }
+ return QQmlOpenMetaObject::toDynamicMetaObject(object);
+}
+
+ModelNodeMetaObject *ModelNodeMetaObject::get(QObject *obj)
+{
+ QObjectPrivate *op = QObjectPrivate::get(obj);
+ return static_cast<ModelNodeMetaObject*>(op->metaObject);
}
-void ModelObject::updateValues()
+void ModelNodeMetaObject::updateValues()
{
+ if (!m_initialized)
+ return;
int roleCount = m_model->m_listModel->roleCount();
for (int i=0 ; i < roleCount ; ++i) {
const ListLayout::Role &role = m_model->m_listModel->getExistingRole(i);
@@ -1225,8 +1268,10 @@ void ModelObject::updateValues()
}
}
-void ModelObject::updateValues(const QVector<int> &roles)
+void ModelNodeMetaObject::updateValues(const QVector<int> &roles)
{
+ if (!m_initialized)
+ return;
int roleCount = roles.count();
for (int i=0 ; i < roleCount ; ++i) {
int roleIndex = roles.at(i);
@@ -1237,15 +1282,6 @@ void ModelObject::updateValues(const QVector<int> &roles)
}
}
-ModelNodeMetaObject::ModelNodeMetaObject(ModelObject *object)
-: QQmlOpenMetaObject(object), m_enabled(false), m_obj(object)
-{
-}
-
-ModelNodeMetaObject::~ModelNodeMetaObject()
-{
-}
-
void ModelNodeMetaObject::propertyWritten(int index)
{
if (!m_enabled)
@@ -1254,17 +1290,75 @@ void ModelNodeMetaObject::propertyWritten(int index)
QString propName = QString::fromUtf8(name(index));
QVariant value = operator[](index);
- QV4::Scope scope(m_obj->m_model->engine());
+ QV4::Scope scope(m_model->engine());
QV4::ScopedValue v(scope, scope.engine->fromVariant(value));
- int roleIndex = m_obj->m_model->m_listModel->setExistingProperty(m_obj->m_elementIndex, propName, v, scope.engine);
+ int roleIndex = m_model->m_listModel->setExistingProperty(m_elementIndex, propName, v, scope.engine);
if (roleIndex != -1) {
QVector<int> roles;
roles << roleIndex;
- m_obj->m_model->emitItemsChanged(m_obj->m_elementIndex, 1, roles);
+ m_model->emitItemsChanged(m_elementIndex, 1, roles);
}
}
+namespace QV4 {
+
+void ModelObject::put(Managed *m, String *name, const Value &value)
+{
+ ModelObject *that = static_cast<ModelObject*>(m);
+
+ ExecutionEngine *eng = that->engine();
+ const int elementIndex = that->d()->m_elementIndex;
+ const QString propName = name->toQString();
+ int roleIndex = that->d()->m_model->m_listModel->setExistingProperty(elementIndex, propName, value, eng);
+ if (roleIndex != -1) {
+ QVector<int> roles;
+ roles << roleIndex;
+ that->d()->m_model->emitItemsChanged(elementIndex, 1, roles);
+ }
+
+ ModelNodeMetaObject *mo = ModelNodeMetaObject::get(that->object());
+ if (mo->initialized())
+ mo->emitPropertyNotification(name->toQString().toUtf8());
+}
+
+ReturnedValue ModelObject::get(const Managed *m, String *name, bool *hasProperty)
+{
+ const ModelObject *that = static_cast<const ModelObject*>(m);
+ const ListLayout::Role *role = that->d()->m_model->m_listModel->getExistingRole(name);
+ if (!role)
+ return QObjectWrapper::get(m, name, hasProperty);
+ if (hasProperty)
+ *hasProperty = true;
+ const int elementIndex = that->d()->m_elementIndex;
+ QVariant value = that->d()->m_model->data(elementIndex, role->index);
+ return that->engine()->fromVariant(value);
+}
+
+void ModelObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
+{
+ ModelObject *that = static_cast<ModelObject*>(m);
+ ExecutionEngine *v4 = that->engine();
+ name->setM(0);
+ *index = UINT_MAX;
+ if (it->arrayIndex < uint(that->d()->m_model->m_listModel->roleCount())) {
+ Scope scope(that->engine());
+ const ListLayout::Role &role = that->d()->m_model->m_listModel->getExistingRole(it->arrayIndex);
+ ++it->arrayIndex;
+ ScopedString roleName(scope, v4->newString(role.name));
+ name->setM(roleName->d());
+ *attributes = QV4::Attr_Data;
+ QVariant value = that->d()->m_model->data(that->d()->m_elementIndex, role.index);
+ p->value = v4->fromVariant(value);
+ return;
+ }
+ QV4::QObjectWrapper::advanceIterator(m, it, name, index, p, attributes);
+}
+
+DEFINE_OBJECT_VTABLE(ModelObject);
+
+} // namespace QV4
+
DynamicRoleModelNode::DynamicRoleModelNode(QQmlListModel *owner, int uid) : m_owner(owner), m_uid(uid), m_meta(new DynamicRoleModelNodeMetaObject(this))
{
setNodeUpdatesEnabled(true);
@@ -1330,8 +1424,8 @@ void DynamicRoleModelNode::updateValues(const QVariantMap &object, QVector<int>
QQmlListModel *subModel = QQmlListModel::createWithOwner(m_owner);
QVariantList subArray = value.toList();
- QVariantList::const_iterator subIt = subArray.begin();
- QVariantList::const_iterator subEnd = subArray.end();
+ QVariantList::const_iterator subIt = subArray.cbegin();
+ QVariantList::const_iterator subEnd = subArray.cend();
while (subIt != subEnd) {
const QVariantMap &subObject = subIt->toMap();
subModel->m_modelObjects.append(DynamicRoleModelNode::create(subObject, subModel));
@@ -1398,8 +1492,8 @@ void DynamicRoleModelNodeMetaObject::propertyWritten(int index)
QQmlListModel *subModel = QQmlListModel::createWithOwner(parentModel);
QVariantList subArray = v.toList();
- QVariantList::const_iterator subIt = subArray.begin();
- QVariantList::const_iterator subEnd = subArray.end();
+ QVariantList::const_iterator subIt = subArray.cbegin();
+ QVariantList::const_iterator subEnd = subArray.cend();
while (subIt != subEnd) {
const QVariantMap &subObject = subIt->toMap();
subModel->m_modelObjects.append(DynamicRoleModelNode::create(subObject, subModel));
@@ -1781,6 +1875,30 @@ QVariant QQmlListModel::data(const QModelIndex &index, int role) const
return data(index.row(), role);
}
+bool QQmlListModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ const int row = index.row();
+ if (row >= count() || row < 0)
+ return false;
+
+ if (m_dynamicRoles) {
+ const QByteArray property = m_roles.at(role).toUtf8();
+ if (m_modelObjects[row]->setValue(property, value)) {
+ emitItemsChanged(row, 1, QVector<int>() << role);
+ return true;
+ }
+ } else {
+ const ListLayout::Role &r = m_listModel->getExistingRole(role);
+ const int roleIndex = m_listModel->setOrCreateProperty(row, r.name, value);
+ if (roleIndex != -1) {
+ emitItemsChanged(row, 1, QVector<int>() << role);
+ return true;
+ }
+ }
+
+ return false;
+}
+
QVariant QQmlListModel::data(int index, int role) const
{
QVariant v;
@@ -2157,8 +2275,8 @@ QQmlV4Handle QQmlListModel::get(int index) const
DynamicRoleModelNode *object = m_modelObjects[index];
result = QV4::QObjectWrapper::wrap(scope.engine, object);
} else {
- ModelObject *object = m_listModel->getOrCreateModelObject(const_cast<QQmlListModel *>(this), index);
- result = QV4::QObjectWrapper::wrap(scope.engine, object);
+ QObject *object = m_listModel->getOrCreateModelObject(const_cast<QQmlListModel *>(this), index);
+ result = scope.engine->memoryManager->allocObject<QV4::ModelObject>(object, const_cast<QQmlListModel *>(this), index);
}
}
diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h
index 75373be47c..b3ae806c5e 100644
--- a/src/qml/types/qqmllistmodel_p.h
+++ b/src/qml/types/qqmllistmodel_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLLISTMODEL_H
#define QQMLLISTMODEL_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include <private/qqmlcustomparser_p.h>
@@ -54,6 +65,10 @@ class QQmlListModelWorkerAgent;
class ListModel;
class ListLayout;
+namespace QV4 {
+struct ModelObject;
+}
+
class Q_QML_PRIVATE_EXPORT QQmlListModel : public QAbstractListModel
{
Q_OBJECT
@@ -67,6 +82,7 @@ public:
QModelIndex index(int row, int column, const QModelIndex &parent) const;
int rowCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
QHash<int,QByteArray> roleNames() const;
QVariant data(int index, int role) const;
@@ -94,6 +110,7 @@ private:
friend class QQmlListModelParser;
friend class QQmlListModelWorkerAgent;
friend class ModelObject;
+ friend struct QV4::ModelObject;
friend class ModelNodeMetaObject;
friend class ListModel;
friend class ListElement;
diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h
index 4e3132b860..d7e0defaec 100644
--- a/src/qml/types/qqmllistmodel_p_p.h
+++ b/src/qml/types/qqmllistmodel_p_p.h
@@ -111,56 +111,72 @@ private:
friend class DynamicRoleModelNodeMetaObject;
};
-class ModelObject;
-
class ModelNodeMetaObject : public QQmlOpenMetaObject
{
public:
- ModelNodeMetaObject(ModelObject *object);
+ ModelNodeMetaObject(QObject *object, QQmlListModel *model, int elementIndex);
~ModelNodeMetaObject();
+ virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *object);
+
+ static ModelNodeMetaObject *get(QObject *obj);
+
bool m_enabled;
+ QQmlListModel *m_model;
+ int m_elementIndex;
+
+ void updateValues();
+ void updateValues(const QVector<int> &roles);
+
+ bool initialized() const { return m_initialized; }
protected:
void propertyWritten(int index);
private:
-
- ModelObject *m_obj;
-};
-
-class ModelObject : public QObject
-{
- Q_OBJECT
-public:
- ModelObject(QQmlListModel *model, int elementIndex);
-
+ using QQmlOpenMetaObject::setValue;
void setValue(const QByteArray &name, const QVariant &val, bool force)
{
if (force) {
- QVariant existingValue = m_meta->value(name);
+ QVariant existingValue = value(name);
if (existingValue.isValid()) {
- (*m_meta)[name] = QVariant();
+ (*this)[name] = QVariant();
}
}
- m_meta->setValue(name, val);
+ setValue(name, val);
}
- void setNodeUpdatesEnabled(bool enable)
- {
- m_meta->m_enabled = enable;
- }
+ void initialize();
+ bool m_initialized;
+};
- void updateValues();
- void updateValues(const QVector<int> &roles);
+namespace QV4 {
+
+namespace Heap {
+struct ModelObject : public QObjectWrapper {
+ ModelObject(QObject *object, QQmlListModel *model, int elementIndex)
+ : QObjectWrapper(object)
+ , m_model(model)
+ , m_elementIndex(elementIndex)
+ {}
QQmlListModel *m_model;
int m_elementIndex;
+};
-private:
- ModelNodeMetaObject *m_meta;
+}
+
+struct ModelObject : public QObjectWrapper
+{
+ static void put(Managed *m, String *name, const Value& value);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
+
+ V4_OBJECT2(ModelObject, QObjectWrapper)
};
+} // namespace QV4
+
class ListLayout
{
public:
@@ -236,7 +252,7 @@ public:
enum
{
- BLOCK_SIZE = 64 - sizeof(int) - sizeof(ListElement *) - sizeof(ModelObject *)
+ BLOCK_SIZE = 64 - sizeof(int) - sizeof(ListElement *) - sizeof(ModelNodeMetaObject *)
};
private:
@@ -278,11 +294,13 @@ private:
int getUid() const { return uid; }
+ ModelNodeMetaObject *objectCache();
+
char data[BLOCK_SIZE];
ListElement *next;
int uid;
- ModelObject *m_objectCache;
+ QObject *m_objectCache;
friend class ListModel;
};
@@ -315,6 +333,11 @@ public:
return m_layout->getExistingRole(index);
}
+ const ListLayout::Role *getExistingRole(QV4::String *key)
+ {
+ return m_layout->getExistingRole(key);
+ }
+
const ListLayout::Role &getOrCreateListRole(const QString &name)
{
return m_layout->getRoleOrCreate(name, ListLayout::Role::List);
@@ -343,7 +366,7 @@ public:
static void sync(ListModel *src, ListModel *target, QHash<int, ListModel *> *srcModelHash);
- ModelObject *getOrCreateModelObject(QQmlListModel *model, int elementIndex);
+ QObject *getOrCreateModelObject(QQmlListModel *model, int elementIndex);
private:
QPODVector<ListElement *, 4> elements;
diff --git a/src/qml/types/qqmlmodelsmodule.cpp b/src/qml/types/qqmlmodelsmodule.cpp
index 3e53efd8b9..062d30c252 100644
--- a/src/qml/types/qqmlmodelsmodule.cpp
+++ b/src/qml/types/qqmlmodelsmodule.cpp
@@ -48,6 +48,7 @@ void QQmlModelsModule::defineModule()
qmlRegisterType<QQmlDelegateModel>(uri, 2, 1, "DelegateModel");
qmlRegisterType<QQmlDelegateModelGroup>(uri, 2, 1, "DelegateModelGroup");
qmlRegisterType<QQmlObjectModel>(uri, 2, 1, "ObjectModel");
+ qmlRegisterType<QQmlObjectModel,3>(uri, 2, 3, "ObjectModel");
qmlRegisterType<QItemSelectionModel>(uri, 2, 2, "ItemSelectionModel");
}
diff --git a/src/qml/types/qqmlmodelsmodule_p.h b/src/qml/types/qqmlmodelsmodule_p.h
index 7fd02b600a..3471a16684 100644
--- a/src/qml/types/qqmlmodelsmodule_p.h
+++ b/src/qml/types/qqmlmodelsmodule_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLMODELSMODULE_H
#define QQMLMODELSMODULE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qtqmlglobal_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/types/qqmlobjectmodel.cpp b/src/qml/types/qqmlobjectmodel.cpp
index 7081e96070..4b64f24806 100644
--- a/src/qml/types/qqmlobjectmodel.cpp
+++ b/src/qml/types/qqmlobjectmodel.cpp
@@ -36,10 +36,12 @@
#include <QtCore/qcoreapplication.h>
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlinfo.h>
#include <private/qqmlchangeset_p.h>
#include <private/qqmlglobal_p.h>
#include <private/qobject_p.h>
+#include <private/qpodvector_p.h>
#include <QtCore/qhash.h>
#include <QtCore/qlist.h>
@@ -67,9 +69,8 @@ public:
QQmlObjectModelPrivate() : QObjectPrivate() {}
static void children_append(QQmlListProperty<QObject> *prop, QObject *item) {
- static_cast<QQmlObjectModelPrivate *>(prop->data)->children.append(Item(item));
- static_cast<QQmlObjectModelPrivate *>(prop->data)->itemAppended();
- static_cast<QQmlObjectModelPrivate *>(prop->data)->emitChildrenChanged();
+ int index = static_cast<QQmlObjectModelPrivate *>(prop->data)->children.count();
+ static_cast<QQmlObjectModelPrivate *>(prop->data)->insert(index, item);
}
static int children_count(QQmlListProperty<QObject> *prop) {
@@ -81,33 +82,77 @@ public:
}
static void children_clear(QQmlListProperty<QObject> *prop) {
- static_cast<QQmlObjectModelPrivate *>(prop->data)->itemCleared(static_cast<QQmlObjectModelPrivate *>(prop->data)->children);
- static_cast<QQmlObjectModelPrivate *>(prop->data)->children.clear();
- static_cast<QQmlObjectModelPrivate *>(prop->data)->emitChildrenChanged();
+ static_cast<QQmlObjectModelPrivate *>(prop->data)->clear();
}
- void itemAppended() {
+ void insert(int index, QObject *item) {
Q_Q(QQmlObjectModel);
- QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.last().item);
- attached->setIndex(children.count()-1);
+ children.insert(index, Item(item));
+ for (int i = index; i < children.count(); ++i) {
+ QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(i).item);
+ attached->setIndex(i);
+ }
QQmlChangeSet changeSet;
- changeSet.insert(children.count() - 1, 1);
+ changeSet.insert(index, 1);
emit q->modelUpdated(changeSet, false);
emit q->countChanged();
+ emit q->childrenChanged();
}
- void itemCleared(const QList<Item> &children) {
+ void move(int from, int to, int n) {
Q_Q(QQmlObjectModel);
- foreach (const Item &child, children)
- emit q->destroyingItem(child.item);
- emit q->countChanged();
+ if (from > to) {
+ // Only move forwards - flip if backwards moving
+ int tfrom = from;
+ int tto = to;
+ from = tto;
+ to = tto+n;
+ n = tfrom-tto;
+ }
+
+ QPODVector<QQmlObjectModelPrivate::Item, 4> store;
+ for (int i = 0; i < to - from; ++i)
+ store.append(children[from + n + i]);
+ for (int i = 0; i < n; ++i)
+ store.append(children[from + i]);
+
+ for (int i = 0; i < store.count(); ++i) {
+ children[from + i] = store[i];
+ QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(from + i).item);
+ attached->setIndex(from + i);
+ }
+
+ QQmlChangeSet changeSet;
+ changeSet.move(from, to, n, -1);
+ emit q->modelUpdated(changeSet, false);
+ emit q->childrenChanged();
}
- void emitChildrenChanged() {
+ void remove(int index, int n) {
Q_Q(QQmlObjectModel);
+ for (int i = index; i < index + n; ++i) {
+ QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(i).item);
+ attached->setIndex(-1);
+ }
+ children.erase(children.begin() + index, children.begin() + index + n);
+ for (int i = index; i < children.count(); ++i) {
+ QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(i).item);
+ attached->setIndex(i);
+ }
+ QQmlChangeSet changeSet;
+ changeSet.remove(index, n);
+ emit q->modelUpdated(changeSet, false);
+ emit q->countChanged();
emit q->childrenChanged();
}
+ void clear() {
+ Q_Q(QQmlObjectModel);
+ foreach (const Item &child, children)
+ emit q->destroyingItem(child.item);
+ remove(0, children.count());
+ }
+
int indexOf(QObject *item) const {
for (int i = 0; i < children.count(); ++i)
if (children.at(i).item == item)
@@ -258,4 +303,133 @@ QQmlObjectModelAttached *QQmlObjectModel::qmlAttachedProperties(QObject *obj)
return QQmlObjectModelAttached::properties(obj);
}
+/*!
+ \qmlmethod object QtQml.Models::ObjectModel::get(int index)
+ \since 5.6
+
+ Returns the item at \a index in the model. This allows the item
+ to be accessed or modified from JavaScript:
+
+ \code
+ Component.onCompleted: {
+ objectModel.append(objectComponent.createObject())
+ console.log(objectModel.get(0).objectName);
+ objectModel.get(0).objectName = "first";
+ }
+ \endcode
+
+ The \a index must be an element in the list.
+
+ \sa append()
+*/
+QObject *QQmlObjectModel::get(int index) const
+{
+ Q_D(const QQmlObjectModel);
+ if (index < 0 || index >= d->children.count())
+ return 0;
+ return d->children.at(index).item;
+}
+
+/*!
+ \qmlmethod QtQml.Models::ObjectModel::append(object item)
+ \since 5.6
+
+ Appends a new item to the end of the model.
+
+ \code
+ objectModel.append(objectComponent.createObject())
+ \endcode
+
+ \sa insert(), remove()
+*/
+void QQmlObjectModel::append(QObject *object)
+{
+ Q_D(QQmlObjectModel);
+ d->insert(count(), object);
+}
+
+/*!
+ \qmlmethod QtQml.Models::ObjectModel::insert(int index, object item)
+ \since 5.6
+
+ Inserts a new item to the model at position \a index.
+
+ \code
+ objectModel.insert(2, objectComponent.createObject())
+ \endcode
+
+ The \a index must be to an existing item in the list, or one past
+ the end of the list (equivalent to append).
+
+ \sa append(), remove()
+*/
+void QQmlObjectModel::insert(int index, QObject *object)
+{
+ Q_D(QQmlObjectModel);
+ if (index < 0 || index > count()) {
+ qmlInfo(this) << tr("insert: index %1 out of range").arg(index);
+ return;
+ }
+ d->insert(index, object);
+}
+
+/*!
+ \qmlmethod QtQml.Models::ObjectModel::move(int from, int to, int n = 1)
+ \since 5.6
+
+ Moves \a n items \a from one position \a to another.
+
+ The from and to ranges must exist; for example, to move the first 3 items
+ to the end of the model:
+
+ \code
+ objectModel.move(0, objectModel.count - 3, 3)
+ \endcode
+
+ \sa append()
+*/
+void QQmlObjectModel::move(int from, int to, int n)
+{
+ Q_D(QQmlObjectModel);
+ if (n <= 0 || from == to)
+ return;
+ if (from < 0 || to < 0 || from + n > count() || to + n > count()) {
+ qmlInfo(this) << tr("move: out of range");
+ return;
+ }
+ d->move(from, to, n);
+}
+
+/*!
+ \qmlmethod QtQml.Models::ObjectModel::remove(int index, int n = 1)
+ \since 5.6
+
+ Removes the items at \a index from the model.
+
+ \sa clear()
+*/
+void QQmlObjectModel::remove(int index, int n)
+{
+ Q_D(QQmlObjectModel);
+ if (index < 0 || n <= 0 || index + n > count()) {
+ qmlInfo(this) << tr("remove: indices [%1 - %2] out of range [0 - %3]").arg(index).arg(index+n).arg(count());
+ return;
+ }
+ d->remove(index, n);
+}
+
+/*!
+ \qmlmethod QtQml.Models::ObjectModel::clear()
+ \since 5.6
+
+ Clears all items from the model.
+
+ \sa append(), remove()
+*/
+void QQmlObjectModel::clear()
+{
+ Q_D(QQmlObjectModel);
+ d->clear();
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/types/qqmlobjectmodel_p.h b/src/qml/types/qqmlobjectmodel_p.h
index 4c37a5ac30..868f736147 100644
--- a/src/qml/types/qqmlobjectmodel_p.h
+++ b/src/qml/types/qqmlobjectmodel_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLINSTANCEMODEL_P_H
#define QQMLINSTANCEMODEL_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qtqmlglobal_p.h>
#include <QtQml/qqml.h>
#include <QtCore/qobject.h>
@@ -61,7 +72,7 @@ public:
virtual ReleaseFlags release(QObject *object) = 0;
virtual void cancel(int) {}
virtual QString stringValue(int, const QString &) = 0;
- virtual void setWatchedRoles(QList<QByteArray> roles) = 0;
+ virtual void setWatchedRoles(const QList<QByteArray> &roles) = 0;
virtual int indexOf(QObject *object, QObject *objectContext) const = 0;
@@ -99,7 +110,7 @@ public:
virtual QObject *object(int index, bool asynchronous=false);
virtual ReleaseFlags release(QObject *object);
virtual QString stringValue(int index, const QString &role);
- virtual void setWatchedRoles(QList<QByteArray>) {}
+ virtual void setWatchedRoles(const QList<QByteArray> &) {}
virtual int indexOf(QObject *object, QObject *objectContext) const;
@@ -107,6 +118,15 @@ public:
static QQmlObjectModelAttached *qmlAttachedProperties(QObject *obj);
+ Q_REVISION(3) Q_INVOKABLE QObject *get(int index) const;
+ Q_REVISION(3) Q_INVOKABLE void append(QObject *object);
+ Q_REVISION(3) Q_INVOKABLE void insert(int index, QObject *object);
+ Q_REVISION(3) Q_INVOKABLE void move(int from, int to, int n = 1);
+ Q_REVISION(3) Q_INVOKABLE void remove(int index, int n = 1);
+
+public Q_SLOTS:
+ Q_REVISION(3) void clear();
+
Q_SIGNALS:
void childrenChanged();
@@ -120,7 +140,7 @@ class QQmlObjectModelAttached : public QObject
public:
QQmlObjectModelAttached(QObject *parent)
- : QObject(parent), m_index(0) {}
+ : QObject(parent), m_index(-1) {}
~QQmlObjectModelAttached() {
attachedProperties.remove(parent());
}
diff --git a/src/qml/types/qqmltimer_p.h b/src/qml/types/qqmltimer_p.h
index 0da81b481f..2dcf827926 100644
--- a/src/qml/types/qqmltimer_p.h
+++ b/src/qml/types/qqmltimer_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLTIMER_H
#define QQMLTIMER_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include <QtCore/qobject.h>
diff --git a/src/qml/types/qquickpackage_p.h b/src/qml/types/qquickpackage_p.h
index 6398e6a4fa..1c7f255eb4 100644
--- a/src/qml/types/qquickpackage_p.h
+++ b/src/qml/types/qquickpackage_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKPACKAGE_H
#define QQUICKPACKAGE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index c2c6e5ef5c..03915ab414 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -54,7 +54,7 @@
#include <private/qv8engine_p.h>
#include <private/qv4serialize_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
#include <private/qv4scopedvalue_p.h>
@@ -165,7 +165,7 @@ public:
QUrl source;
bool initialized;
QQuickWorkerScript *owner;
- QV4::PersistentValue object;
+ QV4::PersistentValue qmlContext;
};
QHash<int, WorkerScript *> workers;
@@ -221,7 +221,7 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init()
"})"
QV4::Scope scope(m_v4Engine);
- QV4::ScopedContext globalContext(scope, scope.engine->rootContext());
+ QV4::ExecutionContext *globalContext = scope.engine->rootContext();
onmessage.set(scope.engine, QV4::Script(globalContext, QString::fromUtf8(CALL_ONMESSAGE_SCRIPT)).run()); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
Q_ASSERT(!scope.engine->hasException);
QV4::Script createsendscript(globalContext, QString::fromUtf8(SEND_MESSAGE_CREATE_SCRIPT)); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
@@ -291,7 +291,6 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::method_sendMessage(QV4::Call
return QV4::Encode::undefined();
}
-// Requires handle scope and context scope
QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *script)
{
if (!script->initialized) {
@@ -300,9 +299,7 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *scri
QV4::ExecutionEngine *v4 = QV8Engine::getV4(workerEngine);
QV4::Scope scope(v4);
- script->object.set(v4, QV4::QmlContextWrapper::urlScope(v4, script->source));
-
- QV4::Scoped<QV4::QmlContextWrapper> w(scope, script->object.value());
+ QV4::Scoped<QV4::QmlContextWrapper> w(scope, QV4::QmlContextWrapper::urlScope(v4, script->source));
Q_ASSERT(!!w);
w->setReadOnly(false);
@@ -312,9 +309,11 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *scri
w->QV4::Object::put(QV4::ScopedString(scope, v4->newString(QStringLiteral("WorkerScript"))), api);
w->setReadOnly(true);
+
+ script->qmlContext.set(v4, v4->rootContext()->newQmlContext(w));
}
- return script->object.value();
+ return script->qmlContext.value();
}
bool QQuickWorkerScriptEnginePrivate::event(QEvent *event)
@@ -354,10 +353,12 @@ void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &d
QV4::ScopedFunctionObject f(scope, workerEngine->onmessage.value());
QV4::ScopedValue value(scope, QV4::Serialize::deserialize(data, v4));
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, script->qmlContext.value());
+ Q_ASSERT(!!qmlContext);
QV4::ScopedCallData callData(scope, 2);
callData->thisObject = workerEngine->global();
- callData->args[0] = script->object.value();
+ callData->args[0] = qmlContext->d()->qml; // ###
callData->args[1] = value;
f->call(callData);
if (scope.hasException()) {
@@ -382,13 +383,12 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
return;
script->source = url;
- QV4::ScopedObject activation(scope, getWorker(script));
- if (!activation)
- return;
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, getWorker(script));
+ Q_ASSERT(!!qmlContext);
if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) {
QV4::CompiledData::CompilationUnit *jsUnit = cachedUnit->createCompilationUnit();
- program.reset(new QV4::Script(v4, activation, jsUnit));
+ program.reset(new QV4::Script(v4, qmlContext, jsUnit));
} else {
QFile f(fileName);
if (!f.open(QIODevice::ReadOnly)) {
@@ -400,7 +400,7 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
QString sourceCode = QString::fromUtf8(data);
QmlIR::Document::removeScriptPragmas(sourceCode);
- program.reset(new QV4::Script(v4, activation, sourceCode, url.toString()));
+ program.reset(new QV4::Script(v4, qmlContext, sourceCode, url.toString()));
program->parse();
}
diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp
index 356970eef0..c61144dd8f 100644
--- a/src/qml/util/qqmladaptormodel.cpp
+++ b/src/qml/util/qqmladaptormodel.cpp
@@ -38,7 +38,7 @@
#include <private/qqmlproperty_p.h>
#include <private/qv8engine_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
QT_BEGIN_NAMESPACE
@@ -159,7 +159,9 @@ public:
signalIndexes.append(propertyId + signalOffset);
}
if (roles.isEmpty()) {
- for (int propertyId = 0; propertyId < propertyRoles.count(); ++propertyId)
+ const int propertyRolesCount = propertyRoles.count();
+ signalIndexes.reserve(propertyRolesCount);
+ for (int propertyId = 0; propertyId < propertyRolesCount; ++propertyId)
signalIndexes.append(propertyId + signalOffset);
}
@@ -219,9 +221,9 @@ public:
const QByteArray &propertyName = it.key();
QV4::ScopedString name(scope, v4->newString(QString::fromUtf8(propertyName)));
- QV4::ScopedContext global(scope, v4->rootContext());
- QV4::ScopedFunctionObject g(scope, v4->memoryManager->alloc<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::get_property));
- QV4::ScopedFunctionObject s(scope, v4->memoryManager->alloc<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::set_property));
+ QV4::ExecutionContext *global = v4->rootContext();
+ QV4::ScopedFunctionObject g(scope, v4->memoryManager->allocObject<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::get_property));
+ QV4::ScopedFunctionObject s(scope, v4->memoryManager->allocObject<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::set_property));
p->setGetter(g);
p->setSetter(s);
proto->insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
@@ -426,7 +428,7 @@ public:
}
QV4::Scope scope(v4);
QV4::ScopedObject proto(scope, type->prototype.value());
- QV4::ScopedObject o(scope, proto->engine()->memoryManager->alloc<QQmlDelegateModelItemObject>(proto->engine(), this));
+ QV4::ScopedObject o(scope, proto->engine()->memoryManager->allocObject<QQmlDelegateModelItemObject>(this));
o->setPrototype(proto);
++scriptRef;
return o.asReturnedValue();
@@ -545,7 +547,7 @@ public:
metaObject = builder.toMetaObject();
*static_cast<QMetaObject *>(this) = *metaObject;
- propertyCache = new QQmlPropertyCache(engine, metaObject);
+ propertyCache = new QQmlPropertyCache(QV8Engine::getV4(engine), metaObject);
}
};
@@ -604,7 +606,7 @@ public:
{
QQmlAdaptorModelEngineData *data = engineData(v4);
QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, v4->memoryManager->alloc<QQmlDelegateModelItemObject>(v4, this));
+ QV4::ScopedObject o(scope, v4->memoryManager->allocObject<QQmlDelegateModelItemObject>(this));
QV4::ScopedObject p(scope, data->listItemProto.value());
o->setPrototype(p);
++scriptRef;
@@ -786,8 +788,11 @@ public:
m_type->release();
}
- int metaCall(QMetaObject::Call call, int id, void **arguments)
+ int metaCall(QObject *o, QMetaObject::Call call, int id, void **arguments)
{
+ Q_ASSERT(o == m_data);
+ Q_UNUSED(o);
+
static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
if (id >= m_type->propertyOffset
&& (call == QMetaObject::ReadProperty
diff --git a/src/qml/util/qqmladaptormodel_p.h b/src/qml/util/qqmladaptormodel_p.h
index b0f211a0f2..9da04462aa 100644
--- a/src/qml/util/qqmladaptormodel_p.h
+++ b/src/qml/util/qqmladaptormodel_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLADAPTORMODEL_P_H
#define QQMLADAPTORMODEL_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qabstractitemmodel.h>
#include "private/qqmllistaccessor_p.h"
diff --git a/src/qml/util/qqmllistaccessor_p.h b/src/qml/util/qqmllistaccessor_p.h
index cf0ec52be4..1d9069118a 100644
--- a/src/qml/util/qqmllistaccessor_p.h
+++ b/src/qml/util/qqmllistaccessor_p.h
@@ -34,6 +34,17 @@
#ifndef QQMLLISTACCESSOR_H
#define QQMLLISTACCESSOR_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/QVariant>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/util/qqmllistcompositor_p.h b/src/qml/util/qqmllistcompositor_p.h
index 8e10cb1546..2ddbc5d5a1 100644
--- a/src/qml/util/qqmllistcompositor_p.h
+++ b/src/qml/util/qqmllistcompositor_p.h
@@ -166,7 +166,7 @@ public:
struct Change
{
inline Change() {}
- inline Change(iterator it, int count, uint flags, int moveId = -1);
+ inline Change(const iterator &it, int count, uint flags, int moveId = -1);
int count;
uint flags;
int moveId;
@@ -188,14 +188,14 @@ public:
struct Insert : public Change
{
Insert() {}
- Insert(iterator it, int count, uint flags, int moveId = -1)
+ Insert(const iterator &it, int count, uint flags, int moveId = -1)
: Change(it, count, flags, moveId) {}
};
struct Remove : public Change
{
Remove() {}
- Remove(iterator it, int count, uint flags, int moveId = -1)
+ Remove(const iterator &it, int count, uint flags, int moveId = -1)
: Change(it, count, flags, moveId) {}
};
@@ -224,14 +224,14 @@ public:
void setFlags(iterator from, int count, Group group, uint flags, QVector<Insert> *inserts = 0);
void setFlags(Group fromGroup, int from, int count, uint flags, QVector<Insert> *inserts = 0) {
setFlags(fromGroup, from, count, fromGroup, flags, inserts); }
- void setFlags(iterator from, int count, uint flags, QVector<Insert> *inserts = 0) {
+ void setFlags(const iterator from, int count, uint flags, QVector<Insert> *inserts = 0) {
setFlags(from, count, from.group, flags, inserts); }
void clearFlags(Group fromGroup, int from, int count, Group group, uint flags, QVector<Remove> *removals = 0);
void clearFlags(iterator from, int count, Group group, uint flags, QVector<Remove> *removals = 0);
void clearFlags(Group fromGroup, int from, int count, uint flags, QVector<Remove> *removals = 0) {
clearFlags(fromGroup, from, count, fromGroup, flags, removals); }
- void clearFlags(iterator from, int count, uint flags, QVector<Remove> *removals = 0) {
+ void clearFlags(const iterator &from, int count, uint flags, QVector<Remove> *removals = 0) {
clearFlags(from, count, from.group, flags, removals); }
bool verifyMoveTo(Group fromGroup, int from, Group toGroup, int to, int count, Group group) const;
@@ -347,7 +347,7 @@ inline QQmlListCompositor::insert_iterator::insert_iterator(
Range *range, int offset, Group group, int groupCount)
: iterator(range, offset, group, groupCount) {}
-inline QQmlListCompositor::Change::Change(iterator it, int count, uint flags, int moveId)
+inline QQmlListCompositor::Change::Change(const iterator &it, int count, uint flags, int moveId)
: count(count), flags(flags), moveId(moveId)
{
for (int i = 0; i < MaximumGroupCount; ++i)
diff --git a/src/qml/util/qqmlpropertymap.cpp b/src/qml/util/qqmlpropertymap.cpp
index 2e95ab7cb5..28f3c8f215 100644
--- a/src/qml/util/qqmlpropertymap.cpp
+++ b/src/qml/util/qqmlpropertymap.cpp
@@ -172,8 +172,7 @@ int QQmlPropertyMapMetaObject::createProperty(const char *name, const char *valu
modify or clear its associated value.
\note When deriving a class from QQmlPropertyMap, use the
- \l {QQmlPropertyMap::QQmlPropertyMap(DerivedType *derived, QObject *parent)}
- {protected two-argument constructor}
+ \l {QQmlPropertyMap::QQmlPropertyMap(DerivedType *derived, QObject *parent)} {protected two-argument constructor}
which ensures that the class is correctly registered with the Qt \l {Meta-Object System}.
*/
diff --git a/src/qmldevtools/qmldevtools.pro b/src/qmldevtools/qmldevtools.pro
index df1b750282..85f21ce6f6 100644
--- a/src/qmldevtools/qmldevtools.pro
+++ b/src/qmldevtools/qmldevtools.pro
@@ -19,3 +19,4 @@ include(../3rdparty/masm/masm-defs.pri)
include(../qml/parser/parser.pri)
include(../qml/jsruntime/jsruntime.pri)
include(../qml/compiler/compiler.pri)
+include(../qml/memory/memory.pri)
diff --git a/src/qmldevtools/qtqmldevtoolsglobal_p.h b/src/qmldevtools/qtqmldevtoolsglobal_p.h
index fa8731deb6..5cbb5ece72 100644
--- a/src/qmldevtools/qtqmldevtoolsglobal_p.h
+++ b/src/qmldevtools/qtqmldevtoolsglobal_p.h
@@ -49,21 +49,8 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_STATIC
-# if defined(QT_BUILD_QML_LIB)
-# define Q_QML_EXPORT Q_DECL_EXPORT
-# else
-# define Q_QML_EXPORT Q_DECL_IMPORT
-# endif
-#else
-# define Q_QML_EXPORT
-#endif
-
-#if defined(QT_BUILD_QMLDEVTOOLS_LIB) || defined(QT_QMLDEVTOOLS_LIB)
-# define Q_QML_PRIVATE_EXPORT
-#else
-# define Q_QML_PRIVATE_EXPORT Q_QML_EXPORT
-#endif
+#define Q_QML_EXPORT
+#define Q_QML_PRIVATE_EXPORT
QT_END_NAMESPACE
#endif // QTQMLGLOBAL_P_H
diff --git a/src/qmltest/qmltest.pro b/src/qmltest/qmltest.pro
index 24b87588b8..289a0584e0 100644
--- a/src/qmltest/qmltest.pro
+++ b/src/qmltest/qmltest.pro
@@ -1,8 +1,8 @@
TARGET = QtQuickTest
DEFINES += QT_NO_URL_CAST_FROM_STRING
-QT = core
-QT_PRIVATE = testlib-private quick qml-private gui core-private
+QT = core testlib-private
+QT_PRIVATE = quick qml-private gui core-private
# Testlib is only a private dependency, which results in our users not
# inheriting testlibs's MODULE_CONFIG transitively. Make it explicit.
diff --git a/src/qmltest/qtestoptions_p.h b/src/qmltest/qtestoptions_p.h
index af6764f98b..48d1c3f473 100644
--- a/src/qmltest/qtestoptions_p.h
+++ b/src/qmltest/qtestoptions_p.h
@@ -34,6 +34,17 @@
#ifndef QTESTOPTIONS_P_H
#define QTESTOPTIONS_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtTest/qtest_global.h>
#include <QtCore/qstring.h>
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index 5e9712d202..c90308cf1a 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -315,6 +315,8 @@ int quick_test_main(int argc, char **argv, const char *name, const char *sourceD
return 1;
}
+ qputenv("QT_QTESTLIB_RUNNING", "1");
+
// Register the test object
qmlRegisterSingletonType<QTestRootObject>("Qt.test.qtestroot", 1, 0, "QTestRootObject", testRootObject);
// Scan through all of the "tst_*.qml" files and run each of them
diff --git a/src/qmltest/quicktest.h b/src/qmltest/quicktest.h
index 49bd7edfaa..b317a07db4 100644
--- a/src/qmltest/quicktest.h
+++ b/src/qmltest/quicktest.h
@@ -35,9 +35,12 @@
#define QUICKTEST_H
#include <QtQuickTest/quicktestglobal.h>
+#include <QtTest/qtest.h>
QT_BEGIN_NAMESPACE
+QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS
+
Q_QUICK_TEST_EXPORT int quick_test_main(int argc, char **argv, const char *name, const char *sourceDir);
#ifdef QUICK_TEST_SOURCE_DIR
@@ -45,12 +48,16 @@ Q_QUICK_TEST_EXPORT int quick_test_main(int argc, char **argv, const char *name,
#define QUICK_TEST_MAIN(name) \
int main(int argc, char **argv) \
{ \
+ QTEST_ADD_GPU_BLACKLIST_SUPPORT \
+ QTEST_SET_MAIN_SOURCE_PATH \
return quick_test_main(argc, argv, #name, QUICK_TEST_SOURCE_DIR); \
}
#define QUICK_TEST_OPENGL_MAIN(name) \
int main(int argc, char **argv) \
{ \
+ QTEST_ADD_GPU_BLACKLIST_SUPPORT \
+ QTEST_SET_MAIN_SOURCE_PATH \
return quick_test_main(argc, argv, #name, QUICK_TEST_SOURCE_DIR); \
}
@@ -59,12 +66,16 @@ Q_QUICK_TEST_EXPORT int quick_test_main(int argc, char **argv, const char *name,
#define QUICK_TEST_MAIN(name) \
int main(int argc, char **argv) \
{ \
+ QTEST_ADD_GPU_BLACKLIST_SUPPORT \
+ QTEST_SET_MAIN_SOURCE_PATH \
return quick_test_main(argc, argv, #name, 0); \
}
#define QUICK_TEST_OPENGL_MAIN(name) \
int main(int argc, char **argv) \
{ \
+ QTEST_ADD_GPU_BLACKLIST_SUPPORT \
+ QTEST_SET_MAIN_SOURCE_PATH \
return quick_test_main(argc, argv, #name, 0); \
}
diff --git a/src/qmltest/quicktestevent.cpp b/src/qmltest/quicktestevent.cpp
index df8de14c14..cfa80c4f19 100644
--- a/src/qmltest/quicktestevent.cpp
+++ b/src/qmltest/quicktestevent.cpp
@@ -50,7 +50,7 @@ QuickTestEvent::~QuickTestEvent()
bool QuickTestEvent::keyPress(int key, int modifiers, int delay)
{
- QWindow *window = eventWindow();
+ QWindow *window = activeWindow();
if (!window)
return false;
QTest::keyPress(window, Qt::Key(key), Qt::KeyboardModifiers(modifiers), delay);
@@ -59,7 +59,7 @@ bool QuickTestEvent::keyPress(int key, int modifiers, int delay)
bool QuickTestEvent::keyRelease(int key, int modifiers, int delay)
{
- QWindow *window = eventWindow();
+ QWindow *window = activeWindow();
if (!window)
return false;
QTest::keyRelease(window, Qt::Key(key), Qt::KeyboardModifiers(modifiers), delay);
@@ -68,7 +68,7 @@ bool QuickTestEvent::keyRelease(int key, int modifiers, int delay)
bool QuickTestEvent::keyClick(int key, int modifiers, int delay)
{
- QWindow *window = eventWindow();
+ QWindow *window = activeWindow();
if (!window)
return false;
QTest::keyClick(window, Qt::Key(key), Qt::KeyboardModifiers(modifiers), delay);
@@ -78,7 +78,7 @@ bool QuickTestEvent::keyClick(int key, int modifiers, int delay)
bool QuickTestEvent::keyPressChar(const QString &character, int modifiers, int delay)
{
QTEST_ASSERT(character.length() == 1);
- QWindow *window = eventWindow();
+ QWindow *window = activeWindow();
if (!window)
return false;
QTest::keyPress(window, character[0].toLatin1(), Qt::KeyboardModifiers(modifiers), delay);
@@ -88,7 +88,7 @@ bool QuickTestEvent::keyPressChar(const QString &character, int modifiers, int d
bool QuickTestEvent::keyReleaseChar(const QString &character, int modifiers, int delay)
{
QTEST_ASSERT(character.length() == 1);
- QWindow *window = eventWindow();
+ QWindow *window = activeWindow();
if (!window)
return false;
QTest::keyRelease(window, character[0].toLatin1(), Qt::KeyboardModifiers(modifiers), delay);
@@ -98,7 +98,7 @@ bool QuickTestEvent::keyReleaseChar(const QString &character, int modifiers, int
bool QuickTestEvent::keyClickChar(const QString &character, int modifiers, int delay)
{
QTEST_ASSERT(character.length() == 1);
- QWindow *window = eventWindow();
+ QWindow *window = activeWindow();
if (!window)
return false;
QTest::keyClick(window, character[0].toLatin1(), Qt::KeyboardModifiers(modifiers), delay);
@@ -211,7 +211,7 @@ bool QuickTestEvent::mousePress
(QObject *item, qreal x, qreal y, int button,
int modifiers, int delay)
{
- QWindow *view = eventWindow();
+ QWindow *view = eventWindow(item);
if (!view)
return false;
QtQuickTest::mouseEvent(QtQuickTest::MousePress, view, item,
@@ -226,7 +226,7 @@ bool QuickTestEvent::mouseWheel(
QObject *item, qreal x, qreal y, int buttons,
int modifiers, int xDelta, int yDelta, int delay)
{
- QWindow *view = eventWindow();
+ QWindow *view = eventWindow(item);
if (!view)
return false;
QtQuickTest::mouseWheel(view, item, Qt::MouseButtons(buttons),
@@ -240,7 +240,7 @@ bool QuickTestEvent::mouseRelease
(QObject *item, qreal x, qreal y, int button,
int modifiers, int delay)
{
- QWindow *view = eventWindow();
+ QWindow *view = eventWindow(item);
if (!view)
return false;
QtQuickTest::mouseEvent(QtQuickTest::MouseRelease, view, item,
@@ -254,7 +254,7 @@ bool QuickTestEvent::mouseClick
(QObject *item, qreal x, qreal y, int button,
int modifiers, int delay)
{
- QWindow *view = eventWindow();
+ QWindow *view = eventWindow(item);
if (!view)
return false;
QtQuickTest::mouseEvent(QtQuickTest::MouseClick, view, item,
@@ -268,7 +268,7 @@ bool QuickTestEvent::mouseDoubleClick
(QObject *item, qreal x, qreal y, int button,
int modifiers, int delay)
{
- QWindow *view = eventWindow();
+ QWindow *view = eventWindow(item);
if (!view)
return false;
QtQuickTest::mouseEvent(QtQuickTest::MouseDoubleClick, view, item,
@@ -282,7 +282,7 @@ bool QuickTestEvent::mouseDoubleClickSequence
(QObject *item, qreal x, qreal y, int button,
int modifiers, int delay)
{
- QWindow *view = eventWindow();
+ QWindow *view = eventWindow(item);
if (!view)
return false;
QtQuickTest::mouseEvent(QtQuickTest::MouseDoubleClickSequence, view, item,
@@ -295,7 +295,7 @@ bool QuickTestEvent::mouseDoubleClickSequence
bool QuickTestEvent::mouseMove
(QObject *item, qreal x, qreal y, int delay, int buttons)
{
- QWindow *view = eventWindow();
+ QWindow *view = eventWindow(item);
if (!view)
return false;
QtQuickTest::mouseEvent(QtQuickTest::MouseMove, view, item,
@@ -304,12 +304,23 @@ bool QuickTestEvent::mouseMove
return true;
}
-QWindow *QuickTestEvent::eventWindow()
+QWindow *QuickTestEvent::eventWindow(QObject *item)
{
- QQuickItem *sgitem = qobject_cast<QQuickItem *>(parent());
- if (sgitem)
- return sgitem->window();
+ QQuickItem *quickItem = qobject_cast<QQuickItem *>(item);
+ if (quickItem)
+ return quickItem->window();
+
+ QQuickItem *testParentitem = qobject_cast<QQuickItem *>(parent());
+ if (testParentitem)
+ return testParentitem->window();
return 0;
}
+QWindow *QuickTestEvent::activeWindow()
+{
+ if (QWindow *window = QGuiApplication::focusWindow())
+ return window;
+ return eventWindow();
+}
+
QT_END_NAMESPACE
diff --git a/src/qmltest/quicktestevent_p.h b/src/qmltest/quicktestevent_p.h
index b7f8f3eda2..0cba644cba 100644
--- a/src/qmltest/quicktestevent_p.h
+++ b/src/qmltest/quicktestevent_p.h
@@ -34,6 +34,17 @@
#ifndef QUICKTESTEVENT_P_H
#define QUICKTESTEVENT_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuickTest/quicktestglobal.h>
#include <QtCore/qobject.h>
#include <QtGui/QWindow>
@@ -73,7 +84,8 @@ public Q_SLOTS:
#endif
private:
- QWindow *eventWindow();
+ QWindow *eventWindow(QObject *item = 0);
+ QWindow *activeWindow();
};
QT_END_NAMESPACE
diff --git a/src/qmltest/quicktestresult.cpp b/src/qmltest/quicktestresult.cpp
index 3f91ce85a8..57ba65e588 100644
--- a/src/qmltest/quicktestresult.cpp
+++ b/src/qmltest/quicktestresult.cpp
@@ -34,6 +34,7 @@
#include "quicktestresult_p.h"
#include <QtTest/qtestcase.h>
#include <QtTest/qtestsystem.h>
+#include <QtTest/private/qtestblacklist_p.h>
#include <QtTest/private/qtestresult_p.h>
#include <QtTest/private/qtesttable_p.h>
#include <QtTest/private/qtestlog_p.h>
@@ -108,6 +109,14 @@ public Q_SLOTS:
pixel += x;
return QColor::fromRgba(*pixel);
}
+
+ bool equals(QuickTestImageObject *other) const
+ {
+ if (!other)
+ return m_image.isNull();
+
+ return m_image == other->m_image;
+ }
private:
QImage m_image;
};
@@ -205,6 +214,7 @@ void QuickTestResult::setFunctionName(const QString &name)
QString fullName = d->testCaseName + QLatin1String("::") + name;
QTestResult::setCurrentTestFunction
(d->intern(fullName).constData());
+ QTestPrivate::checkBlackLists(fullName.toUtf8().constData(), 0);
}
} else {
QTestResult::setCurrentTestFunction(0);
@@ -233,6 +243,7 @@ void QuickTestResult::setDataTag(const QString &tag)
if (!tag.isEmpty()) {
QTestData *data = &(QTest::newRow(tag.toUtf8().constData()));
QTestResult::setCurrentTestData(data);
+ QTestPrivate::checkBlackLists((testCaseName() + QStringLiteral("::") + functionName()).toUtf8().constData(), tag.toUtf8().constData());
emit dataTagChanged();
} else {
QTestResult::setCurrentTestData(0);
@@ -270,6 +281,8 @@ bool QuickTestResult::isSkipped() const
void QuickTestResult::setSkipped(bool skip)
{
QTestResult::setSkipCurrentTest(skip);
+ if (!skip)
+ QTestResult::setBlacklistCurrentTest(false);
emit skippedChanged();
}
@@ -478,8 +491,8 @@ void QuickTestResult::stringify(QQmlV4Function *args)
//Check for Object Type
if (value->isObject()
- && !value->asFunctionObject()
- && !value->asArrayObject()) {
+ && !value->as<QV4::FunctionObject>()
+ && !value->as<QV4::ArrayObject>()) {
QVariant v = scope.engine->toVariant(value, QMetaType::UnknownType);
if (v.isValid()) {
switch (v.type()) {
@@ -500,7 +513,7 @@ void QuickTestResult::stringify(QQmlV4Function *args)
if (result.isEmpty()) {
QString tmp = value->toQStringNoThrow();
- if (value->asArrayObject())
+ if (value->as<QV4::ArrayObject>())
result.append(QString::fromLatin1("[%1]").arg(tmp));
else
result.append(tmp);
@@ -707,6 +720,8 @@ void QuickTestResult::parseArgs(int argc, char *argv[])
void QuickTestResult::setProgramName(const char *name)
{
if (name) {
+ QTestPrivate::parseBlackList();
+ QTestPrivate::parseGpuBlackList();
QTestResult::reset();
} else if (!name && loggingStarted) {
QTestResult::setCurrentTestObject(globalProgramName);
diff --git a/src/qmltest/quicktestresult_p.h b/src/qmltest/quicktestresult_p.h
index 80f84bfa55..ee38c07498 100644
--- a/src/qmltest/quicktestresult_p.h
+++ b/src/qmltest/quicktestresult_p.h
@@ -34,6 +34,17 @@
#ifndef QUICKTESTRESULT_P_H
#define QUICKTESTRESULT_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuickTest/quicktestglobal.h>
#include <QtCore/qobject.h>
#include <QtCore/qstring.h>
@@ -50,7 +61,6 @@ class QuickTestResultPrivate;
class Q_QUICK_TEST_EXPORT QuickTestResult : public QObject
{
Q_OBJECT
- Q_ENUMS(RunMode)
Q_PROPERTY(QString testCaseName READ testCaseName WRITE setTestCaseName NOTIFY testCaseNameChanged)
Q_PROPERTY(QString functionName READ functionName WRITE setFunctionName NOTIFY functionNameChanged)
Q_PROPERTY(QString dataTag READ dataTag WRITE setDataTag NOTIFY dataTagChanged)
@@ -70,6 +80,7 @@ public:
RepeatUntilValidMeasurement,
RunOnce
};
+ Q_ENUM(RunMode)
QString testCaseName() const;
void setTestCaseName(const QString &name);
diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp
index 4ccfdb9142..44a2caecec 100644
--- a/src/quick/accessible/qaccessiblequickitem.cpp
+++ b/src/quick/accessible/qaccessiblequickitem.cpp
@@ -204,11 +204,12 @@ QAccessible::Role QAccessibleQuickItem::role() const
if (qobject_cast<QQuickText*>(const_cast<QQuickItem *>(item())))
return QAccessible::StaticText;
- QVariant v = QQuickAccessibleAttached::property(item(), "role");
- bool ok;
- QAccessible::Role role = (QAccessible::Role)v.toInt(&ok);
- if (!ok) // Not sure if this check is needed.
+ QAccessible::Role role = QAccessible::NoRole;
+ if (item())
+ role = QQuickItemPrivate::get(item())->accessibleRole();
+ if (role == QAccessible::NoRole)
role = QAccessible::Client;
+
return role;
}
diff --git a/src/quick/accessible/qaccessiblequickitem_p.h b/src/quick/accessible/qaccessiblequickitem_p.h
index deefb10e60..1ec569731e 100644
--- a/src/quick/accessible/qaccessiblequickitem_p.h
+++ b/src/quick/accessible/qaccessiblequickitem_p.h
@@ -34,6 +34,17 @@
#ifndef QACCESSIBLEQUICKITEM_H
#define QACCESSIBLEQUICKITEM_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuick/QQuickItem>
#include <QtQuick/QQuickView>
#include <QtGui/qaccessibleobject.h>
diff --git a/src/quick/accessible/qaccessiblequickview_p.h b/src/quick/accessible/qaccessiblequickview_p.h
index f08b78528d..049fa385ba 100644
--- a/src/quick/accessible/qaccessiblequickview_p.h
+++ b/src/quick/accessible/qaccessiblequickview_p.h
@@ -34,6 +34,17 @@
#ifndef QAccessibleQuickView_H
#define QAccessibleQuickView_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtGui/qaccessibleobject.h>
#include <QtQuick/qquickwindow.h>
diff --git a/src/quick/accessible/qquickaccessiblefactory_p.h b/src/quick/accessible/qquickaccessiblefactory_p.h
index f7936b140e..98512f9fb4 100644
--- a/src/quick/accessible/qquickaccessiblefactory_p.h
+++ b/src/quick/accessible/qquickaccessiblefactory_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKACCESSIBLEFACTORY_H
#define QQUICKACCESSIBLEFACTORY_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtGui/qaccessible.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick/designer/designer.pri b/src/quick/designer/designer.pri
index 9f3f7e8be6..eb2141134d 100644
--- a/src/quick/designer/designer.pri
+++ b/src/quick/designer/designer.pri
@@ -1,4 +1,21 @@
-HEADERS += designer/designersupport.h \
- designer/designerwindowmanager_p.h
-SOURCES += designer/designersupport.cpp \
- designer/designerwindowmanager.cpp
+HEADERS += \
+ designer/qquickdesignercustomobjectdata_p.h \
+ designer/qquickdesignersupportitems_p.h \
+ designer/qquickdesignerwindowmanager_p.h \
+ designer/qquickdesignersupportstates_p.h \
+ designer/qquickdesignersupportpropertychanges_p.h \
+ designer/qquickdesignersupportproperties_p.h \
+ designer/qquickdesignersupportmetainfo_p.h \
+ designer/qqmldesignermetaobject_p.h \
+ designer/qquickdesignersupport_p.h
+
+SOURCES += \
+ designer/qquickdesignercustomobjectdata.cpp \
+ designer/qquickdesignersupport.cpp \
+ designer/qquickdesignersupportitems.cpp \
+ designer/qquickdesignersupportmetainfo.cpp \
+ designer/qquickdesignersupportproperties.cpp \
+ designer/qquickdesignersupportpropertychanges.cpp \
+ designer/qquickdesignersupportstates.cpp \
+ designer/qquickdesignerwindowmanager.cpp \
+ designer/qqmldesignermetaobject.cpp
diff --git a/src/quick/designer/qqmldesignermetaobject.cpp b/src/quick/designer/qqmldesignermetaobject.cpp
new file mode 100644
index 0000000000..76c94b242d
--- /dev/null
+++ b/src/quick/designer/qqmldesignermetaobject.cpp
@@ -0,0 +1,340 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmldesignermetaobject_p.h"
+
+#include <QSharedPointer>
+#include <QMetaProperty>
+#include <qnumeric.h>
+#include <QDebug>
+
+#include <private/qqmlengine_p.h>
+#include <private/qqmlpropertycache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static QHash<QDynamicMetaObjectData *, bool> nodeInstanceMetaObjectList;
+static void (*notifyPropertyChangeCallBack)(QObject*, const QQuickDesignerSupport::PropertyName &propertyName) = 0;
+
+struct MetaPropertyData {
+ inline QPair<QVariant, bool> &getDataRef(int idx) {
+ while (m_data.count() <= idx)
+ m_data << QPair<QVariant, bool>(QVariant(), false);
+ return m_data[idx];
+ }
+
+ inline QVariant &getData(int idx) {
+ QPair<QVariant, bool> &prop = getDataRef(idx);
+ if (!prop.second) {
+ prop.first = QVariant();
+ prop.second = true;
+ }
+ return prop.first;
+ }
+
+ inline bool hasData(int idx) const {
+ if (idx >= m_data.count())
+ return false;
+ return m_data[idx].second;
+ }
+
+ inline int count() { return m_data.count(); }
+
+ QVector<QPair<QVariant, bool> > m_data;
+};
+
+static bool constructedMetaData(const QQmlVMEMetaData* data)
+{
+ return data->propertyCount == 0
+ && data->aliasCount == 0
+ && data->signalCount == 0
+ && data->methodCount == 0;
+}
+
+static QQmlVMEMetaData* fakeMetaData()
+{
+ QQmlVMEMetaData* data = new QQmlVMEMetaData;
+ data->propertyCount = 0;
+ data->aliasCount = 0;
+ data->signalCount = 0;
+ data->methodCount = 0;
+
+ return data;
+}
+
+static const QQmlVMEMetaData* vMEMetaDataForObject(QObject *object)
+{
+ QQmlVMEMetaObject *metaObject = QQmlVMEMetaObject::get(object);
+ if (metaObject)
+ return metaObject->metaData;
+
+ return fakeMetaData();
+}
+
+static QQmlPropertyCache *cacheForObject(QObject *object, QQmlEngine *engine)
+{
+ QQmlVMEMetaObject *metaObject = QQmlVMEMetaObject::get(object);
+ if (metaObject)
+ return metaObject->cache;
+
+ return QQmlEnginePrivate::get(engine)->cache(object);
+}
+
+QQmlDesignerMetaObject* QQmlDesignerMetaObject::getNodeInstanceMetaObject(QObject *object, QQmlEngine *engine)
+{
+ //Avoid setting up multiple MetaObjects on the same QObject
+ QObjectPrivate *op = QObjectPrivate::get(object);
+ QDynamicMetaObjectData *parent = op->metaObject;
+ if (nodeInstanceMetaObjectList.contains(parent))
+ return static_cast<QQmlDesignerMetaObject *>(parent);
+
+ // we just create one and the ownership goes automatically to the object in nodeinstance see init method
+ return new QQmlDesignerMetaObject(object, engine);
+}
+
+void QQmlDesignerMetaObject::init(QObject *object, QQmlEngine *engine)
+{
+ //Creating QQmlOpenMetaObjectType
+ m_type = new QQmlOpenMetaObjectType(metaObjectParent(), engine);
+ m_type->addref();
+ //Assigning type to this
+ copyTypeMetaObject();
+
+ //Assign this to object
+ QObjectPrivate *op = QObjectPrivate::get(object);
+ op->metaObject = this;
+
+ //create cache
+ cache = m_cache = QQmlEnginePrivate::get(engine)->cache(this);
+ cache->addref();
+
+ //If our parent is not a VMEMetaObject we just se the flag to false again
+ if (constructedMetaData(metaData))
+ QQmlData::get(object)->hasVMEMetaObject = false;
+
+ nodeInstanceMetaObjectList.insert(this, true);
+ hasAssignedMetaObjectData = true;
+}
+
+QQmlDesignerMetaObject::QQmlDesignerMetaObject(QObject *object, QQmlEngine *engine)
+ : QQmlVMEMetaObject(object, cacheForObject(object, engine), vMEMetaDataForObject(object)),
+ m_context(engine->contextForObject(object)),
+ m_data(new MetaPropertyData),
+ m_cache(0)
+{
+ init(object, engine);
+
+ QQmlData *ddata = QQmlData::get(object, false);
+
+ //Assign cache to object
+ if (ddata && ddata->propertyCache) {
+ cache->setParent(ddata->propertyCache);
+ cache->invalidate(engine, this);
+ ddata->propertyCache = m_cache;
+ }
+
+}
+
+QQmlDesignerMetaObject::~QQmlDesignerMetaObject()
+{
+ if (cache->count() > 1) // qml is crashing because the property cache is not removed from the engine
+ cache->release();
+ else
+ m_type->release();
+
+ nodeInstanceMetaObjectList.remove(this);
+}
+
+void QQmlDesignerMetaObject::createNewDynamicProperty(const QString &name)
+{
+ int id = m_type->createProperty(name.toUtf8());
+ copyTypeMetaObject();
+ setValue(id, QVariant());
+ Q_ASSERT(id >= 0);
+ Q_UNUSED(id);
+
+ //Updating cache
+ QQmlPropertyCache *oldParent = m_cache->parent();
+ QQmlEnginePrivate::get(m_context->engine())->cache(this)->invalidate(m_context->engine(), this);
+ m_cache->setParent(oldParent);
+
+ QQmlProperty property(myObject(), name, m_context);
+ Q_ASSERT(property.isValid());
+}
+
+void QQmlDesignerMetaObject::setValue(int id, const QVariant &value)
+{
+ QPair<QVariant, bool> &prop = m_data->getDataRef(id);
+ prop.first = propertyWriteValue(id, value);
+ prop.second = true;
+ QMetaObject::activate(myObject(), id + m_type->signalOffset(), 0);
+}
+
+QVariant QQmlDesignerMetaObject::propertyWriteValue(int, const QVariant &value)
+{
+ return value;
+}
+
+const QAbstractDynamicMetaObject *QQmlDesignerMetaObject::dynamicMetaObjectParent() const
+{
+ if (QQmlVMEMetaObject::parent.isT1())
+ return QQmlVMEMetaObject::parent.asT1()->toDynamicMetaObject(QQmlVMEMetaObject::object);
+ else
+ return 0;
+}
+
+const QMetaObject *QQmlDesignerMetaObject::metaObjectParent() const
+{
+ if (QQmlVMEMetaObject::parent.isT1())
+ return QQmlVMEMetaObject::parent.asT1()->toDynamicMetaObject(QQmlVMEMetaObject::object);
+
+ return QQmlVMEMetaObject::parent.asT2();
+}
+
+int QQmlDesignerMetaObject::propertyOffset() const
+{
+ return cache->propertyOffset();
+}
+
+int QQmlDesignerMetaObject::openMetaCall(QObject *o, QMetaObject::Call call, int id, void **a)
+{
+ if ((call == QMetaObject::ReadProperty || call == QMetaObject::WriteProperty)
+ && id >= m_type->propertyOffset()) {
+ int propId = id - m_type->propertyOffset();
+ if (call == QMetaObject::ReadProperty) {
+ //propertyRead(propId);
+ *reinterpret_cast<QVariant *>(a[0]) = m_data->getData(propId);
+ } else if (call == QMetaObject::WriteProperty) {
+ if (propId <= m_data->count() || m_data->m_data[propId].first != *reinterpret_cast<QVariant *>(a[0])) {
+ //propertyWrite(propId);
+ QPair<QVariant, bool> &prop = m_data->getDataRef(propId);
+ prop.first = propertyWriteValue(propId, *reinterpret_cast<QVariant *>(a[0]));
+ prop.second = true;
+ //propertyWritten(propId);
+ activate(myObject(), m_type->signalOffset() + propId, 0);
+ }
+ }
+ return -1;
+ } else {
+ QAbstractDynamicMetaObject *directParent = parent();
+ if (directParent)
+ return directParent->metaCall(o, call, id, a);
+ else
+ return myObject()->qt_metacall(call, id, a);
+ }
+}
+
+int QQmlDesignerMetaObject::metaCall(QObject *o, QMetaObject::Call call, int id, void **a)
+{
+ Q_ASSERT(myObject() == o);
+
+ int metaCallReturnValue = -1;
+
+ const QMetaProperty propertyById = QQmlVMEMetaObject::property(id);
+
+ if (call == QMetaObject::WriteProperty
+ && propertyById.userType() == QMetaType::QVariant
+ && reinterpret_cast<QVariant *>(a[0])->type() == QVariant::Double
+ && qIsNaN(reinterpret_cast<QVariant *>(a[0])->toDouble())) {
+ return -1;
+ }
+
+ if (call == QMetaObject::WriteProperty
+ && propertyById.userType() == QMetaType::Double
+ && qIsNaN(*reinterpret_cast<double*>(a[0]))) {
+ return -1;
+ }
+
+ if (call == QMetaObject::WriteProperty
+ && propertyById.userType() == QMetaType::Float
+ && qIsNaN(*reinterpret_cast<float*>(a[0]))) {
+ return -1;
+ }
+
+ QVariant oldValue;
+
+ if (call == QMetaObject::WriteProperty && !propertyById.hasNotifySignal())
+ {
+ oldValue = propertyById.read(myObject());
+ }
+
+ QAbstractDynamicMetaObject *directParent = parent();
+ if (directParent && id < directParent->propertyOffset()) {
+ metaCallReturnValue = directParent->metaCall(o, call, id, a);
+ } else {
+ openMetaCall(o, call, id, a);
+ }
+
+
+ if (call == QMetaObject::WriteProperty
+ && !propertyById.hasNotifySignal()
+ && oldValue != propertyById.read(myObject()))
+ notifyPropertyChange(id);
+
+ return metaCallReturnValue;
+}
+
+void QQmlDesignerMetaObject::notifyPropertyChange(int id)
+{
+ const QMetaProperty propertyById = property(id);
+
+ if (id < propertyOffset()) {
+ if (notifyPropertyChangeCallBack)
+ notifyPropertyChangeCallBack(myObject(), propertyById.name());
+ } else {
+ if (notifyPropertyChangeCallBack)
+ notifyPropertyChangeCallBack(myObject(), name(id - propertyOffset()));
+ }
+}
+
+int QQmlDesignerMetaObject::count() const
+{
+ return m_type->propertyCount();
+}
+
+QByteArray QQmlDesignerMetaObject::name(int idx) const
+{
+ return m_type->propertyName(idx);
+}
+
+void QQmlDesignerMetaObject::copyTypeMetaObject()
+{
+ *static_cast<QMetaObject *>(this) = *m_type->metaObject();
+}
+
+void QQmlDesignerMetaObject::registerNotifyPropertyChangeCallBack(void (*callback)(QObject *, const QQuickDesignerSupport::PropertyName &))
+{
+ notifyPropertyChangeCallBack = callback;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/designer/qqmldesignermetaobject_p.h b/src/quick/designer/qqmldesignermetaobject_p.h
new file mode 100644
index 0000000000..47f4baad2b
--- /dev/null
+++ b/src/quick/designer/qqmldesignermetaobject_p.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef NODEINSTANCEMETAOBJECT_H
+#define NODEINSTANCEMETAOBJECT_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickdesignersupport_p.h"
+
+#include <QQmlContext>
+#include <QScopedPointer>
+#include <private/qqmlopenmetaobject_p.h>
+#include <private/qqmlvmemetaobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct MetaPropertyData;
+
+class QQmlDesignerMetaObject : public QQmlVMEMetaObject
+{
+public:
+ ~QQmlDesignerMetaObject();
+
+ static void registerNotifyPropertyChangeCallBack(void (*callback)(QObject*, const QQuickDesignerSupport::PropertyName &propertyName));
+
+protected:
+ QQmlDesignerMetaObject(QObject *object, QQmlEngine *engine);
+ static QQmlDesignerMetaObject* getNodeInstanceMetaObject(QObject *object, QQmlEngine *engine);
+
+ void createNewDynamicProperty(const QString &name);
+ int openMetaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a);
+ int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a);
+ void notifyPropertyChange(int id);
+ void setValue(int id, const QVariant &value);
+ QVariant propertyWriteValue(int, const QVariant &);
+
+ QObject *myObject() const { return QQmlVMEMetaObject::object; }
+ QAbstractDynamicMetaObject *parent() const { return const_cast<QAbstractDynamicMetaObject *>(dynamicMetaObjectParent()); }
+
+ const QAbstractDynamicMetaObject *dynamicMetaObjectParent() const;
+
+ const QMetaObject *metaObjectParent() const;
+
+ int propertyOffset() const;
+
+ int count() const;
+ QByteArray name(int) const;
+
+ void copyTypeMetaObject();
+
+private:
+ void init(QObject *, QQmlEngine *engine);
+
+ QPointer<QQmlContext> m_context;
+ QQmlOpenMetaObjectType *m_type;
+ QScopedPointer<MetaPropertyData> m_data;
+ //QAbstractDynamicMetaObject *m_parent;
+ QQmlPropertyCache *m_cache;
+
+ friend class QQuickDesignerSupportProperties;
+};
+
+QT_END_NAMESPACE
+
+#endif // NODEINSTANCEMETAOBJECT_H
diff --git a/src/quick/designer/qquickdesignercustomobjectdata.cpp b/src/quick/designer/qquickdesignercustomobjectdata.cpp
new file mode 100644
index 0000000000..7f074d8341
--- /dev/null
+++ b/src/quick/designer/qquickdesignercustomobjectdata.cpp
@@ -0,0 +1,286 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickdesignersupportmetainfo_p.h"
+#include "qquickdesignersupportproperties_p.h"
+
+#include "qquickdesignercustomobjectdata_p.h"
+
+#include <QGlobalStatic>
+#include <QQmlContext>
+#include <QQmlEngine>
+
+#include <private/qqmlbinding_p.h>
+
+QT_BEGIN_NAMESPACE
+
+typedef QHash<QObject*, QQuickDesignerCustomObjectData*> CustomObjectDataHash;
+Q_GLOBAL_STATIC(CustomObjectDataHash, s_designerObjectToDataHash)
+
+struct HandleDestroyedFunctor {
+ QQuickDesignerCustomObjectData *data;
+ void operator()() { data->handleDestroyed(); }
+};
+
+QQuickDesignerCustomObjectData::QQuickDesignerCustomObjectData(QObject *object)
+ : m_object(object)
+{
+ if (object) {
+ populateResetHashes();
+ s_designerObjectToDataHash()->insert(object, this);
+
+ HandleDestroyedFunctor functor;
+ functor.data = this;
+ QObject::connect(object, &QObject::destroyed, functor);
+ }
+}
+
+void QQuickDesignerCustomObjectData::registerData(QObject *object)
+{
+ new QQuickDesignerCustomObjectData(object);
+}
+
+QQuickDesignerCustomObjectData *QQuickDesignerCustomObjectData::get(QObject *object)
+{
+ return s_designerObjectToDataHash()->value(object);
+}
+
+QVariant QQuickDesignerCustomObjectData::getResetValue(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQuickDesignerCustomObjectData* data = get(object);
+
+ if (data)
+ return data->getResetValue(propertyName);
+
+ return QVariant();
+}
+
+void QQuickDesignerCustomObjectData::doResetProperty(QObject *object, QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQuickDesignerCustomObjectData* data = get(object);
+
+ if (data)
+ data->doResetProperty(context, propertyName);
+}
+
+bool QQuickDesignerCustomObjectData::hasValidResetBinding(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQuickDesignerCustomObjectData* data = get(object);
+
+ if (data)
+ return data->hasValidResetBinding(propertyName);
+
+ return false;
+}
+
+bool QQuickDesignerCustomObjectData::hasBindingForProperty(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ bool *hasChanged)
+{
+ QQuickDesignerCustomObjectData* data = get(object);
+
+ if (data)
+ return data->hasBindingForProperty(context, propertyName, hasChanged);
+
+ return false;
+}
+
+void QQuickDesignerCustomObjectData::setPropertyBinding(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression)
+{
+ QQuickDesignerCustomObjectData* data = get(object);
+
+ if (data)
+ data->setPropertyBinding(context, propertyName, expression);
+}
+
+void QQuickDesignerCustomObjectData::keepBindingFromGettingDeleted(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQuickDesignerCustomObjectData* data = get(object);
+
+ if (data)
+ data->keepBindingFromGettingDeleted(context, propertyName);
+}
+
+void QQuickDesignerCustomObjectData::populateResetHashes()
+{
+ QQuickDesignerSupport::PropertyNameList propertyNameList =
+ QQuickDesignerSupportProperties::propertyNameListForWritableProperties(object());
+
+ Q_FOREACH (const QQuickDesignerSupport::PropertyName &propertyName, propertyNameList) {
+ QQmlProperty property(object(), QString::fromUtf8(propertyName), QQmlEngine::contextForObject(object()));
+
+ QQmlAbstractBinding::Ptr binding = QQmlAbstractBinding::Ptr(QQmlPropertyPrivate::binding(property));
+
+ if (binding) {
+ m_resetBindingHash.insert(propertyName, binding);
+ } else if (property.isWritable()) {
+ m_resetValueHash.insert(propertyName, property.read());
+ }
+ }
+}
+
+QObject *QQuickDesignerCustomObjectData::object() const
+{
+ return m_object;
+}
+
+QVariant QQuickDesignerCustomObjectData::getResetValue(const QQuickDesignerSupport::PropertyName &propertyName) const
+{
+ return m_resetValueHash.value(propertyName);
+}
+
+void QQuickDesignerCustomObjectData::doResetProperty(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQmlProperty property(object(), QString::fromUtf8(propertyName), context);
+
+ if (!property.isValid())
+ return;
+
+ QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(property);
+ if (binding && !(hasValidResetBinding(propertyName) && getResetBinding(propertyName) == binding)) {
+ binding->setEnabled(false, 0);
+ }
+
+
+ if (hasValidResetBinding(propertyName)) {
+ QQmlAbstractBinding *binding = getResetBinding(propertyName);
+
+#if defined(QT_NO_DYNAMIC_CAST)
+ QQmlBinding *qmlBinding = static_cast<QQmlBinding*>(binding);
+#else
+ QQmlBinding *qmlBinding = dynamic_cast<QQmlBinding*>(binding);
+#endif
+ if (qmlBinding)
+ qmlBinding->setTarget(property);
+ QQmlPropertyPrivate::setBinding(binding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding);
+ if (qmlBinding)
+ qmlBinding->update();
+
+ } else if (property.isResettable()) {
+ property.reset();
+ } else if (property.propertyTypeCategory() == QQmlProperty::List) {
+ QQmlListReference list = qvariant_cast<QQmlListReference>(property.read());
+
+ if (!QQuickDesignerSupportProperties::hasFullImplementedListInterface(list)) {
+ qWarning() << "Property list interface not fully implemented for Class " << property.property().typeName() << " in property " << property.name() << "!";
+ return;
+ }
+
+ list.clear();
+ } else if (property.isWritable()) {
+ if (property.read() == getResetValue(propertyName))
+ return;
+
+ property.write(getResetValue(propertyName));
+ }
+}
+
+bool QQuickDesignerCustomObjectData::hasValidResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const
+{
+ return m_resetBindingHash.contains(propertyName) && m_resetBindingHash.value(propertyName).data();
+}
+
+QQmlAbstractBinding *QQuickDesignerCustomObjectData::getResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const
+{
+ return m_resetBindingHash.value(propertyName).data();
+}
+
+bool QQuickDesignerCustomObjectData::hasBindingForProperty(QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ bool *hasChanged) const
+{
+ if (QQuickDesignerSupportProperties::isPropertyBlackListed(propertyName))
+ return false;
+
+ QQmlProperty property(object(), QString::fromUtf8(propertyName), context);
+
+ bool hasBinding = QQmlPropertyPrivate::binding(property);
+
+ if (hasChanged) {
+ *hasChanged = hasBinding != m_hasBindingHash.value(propertyName, false);
+ if (*hasChanged)
+ m_hasBindingHash.insert(propertyName, hasBinding);
+ }
+
+ return QQmlPropertyPrivate::binding(property);
+}
+
+void QQuickDesignerCustomObjectData::setPropertyBinding(QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression)
+{
+ QQmlProperty property(object(), QString::fromUtf8(propertyName), context);
+
+ if (!property.isValid())
+ return;
+
+ if (property.isProperty()) {
+ QQmlBinding *binding = new QQmlBinding(expression, object(), context);
+ binding->setTarget(property);
+ binding->setNotifyOnValueChanged(true);
+
+ QQmlPropertyPrivate::setBinding(binding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding);
+ //Refcounting is taking take care of deletion
+ binding->update();
+ if (binding->hasError()) {
+ if (property.property().userType() == QVariant::String)
+ property.write(QVariant(QLatin1Char('#') + expression + QLatin1Char('#')));
+ }
+
+ } else {
+ qWarning() << Q_FUNC_INFO << ": Cannot set binding for property" << propertyName << ": property is unknown for type";
+ }
+}
+
+void QQuickDesignerCustomObjectData::keepBindingFromGettingDeleted(QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ //Refcounting is taking care
+ Q_UNUSED(context)
+ Q_UNUSED(propertyName)
+}
+
+void QQuickDesignerCustomObjectData::handleDestroyed()
+{
+ s_designerObjectToDataHash()->remove(m_object);
+ delete this;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/quick/designer/qquickdesignercustomobjectdata_p.h b/src/quick/designer/qquickdesignercustomobjectdata_p.h
new file mode 100644
index 0000000000..6734540a54
--- /dev/null
+++ b/src/quick/designer/qquickdesignercustomobjectdata_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DESIGNERCUSTOMOBJECTDATA_H
+#define DESIGNERCUSTOMOBJECTDATA_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickdesignersupport_p.h"
+
+#include <QHash>
+#include <QObject>
+#include <QVariant>
+
+#include <private/qqmlbinding_p.h>
+
+QT_BEGIN_NAMESPACE
+class QQmlContext;
+
+class QQuickDesignerCustomObjectData
+{
+public:
+ static void registerData(QObject *object);
+ static QQuickDesignerCustomObjectData *get(QObject *object);
+ static QVariant getResetValue(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName);
+ static void doResetProperty(QObject *object, QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName);
+ static bool hasValidResetBinding(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName);
+ static bool hasBindingForProperty(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ bool *hasChanged);
+ static void setPropertyBinding(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression);
+ static void keepBindingFromGettingDeleted(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName);
+ void handleDestroyed();
+
+private:
+ QQuickDesignerCustomObjectData(QObject *object);
+ void populateResetHashes();
+ QObject *object() const;
+ QVariant getResetValue(const QQuickDesignerSupport::PropertyName &propertyName) const;
+ void doResetProperty(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName);
+ bool hasValidResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const;
+ QQmlAbstractBinding *getResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const;
+ bool hasBindingForProperty(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName, bool *hasChanged) const;
+ void setPropertyBinding(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName, const QString &expression);
+ void keepBindingFromGettingDeleted(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName);
+
+ QObject *m_object;
+ QHash<QQuickDesignerSupport::PropertyName, QVariant> m_resetValueHash;
+ QHash<QQuickDesignerSupport::PropertyName, QQmlAbstractBinding::Ptr> m_resetBindingHash;
+ mutable QHash<QQuickDesignerSupport::PropertyName, bool> m_hasBindingHash;
+};
+
+QT_END_NAMESPACE
+
+#endif // DESIGNERCUSTOMOBJECTDATA_H
diff --git a/src/quick/designer/designersupport.cpp b/src/quick/designer/qquickdesignersupport.cpp
index 56d2badb62..bc6352a677 100644
--- a/src/quick/designer/designersupport.cpp
+++ b/src/quick/designer/qquickdesignersupport.cpp
@@ -31,7 +31,7 @@
**
****************************************************************************/
-#include "designersupport.h"
+#include "qquickdesignersupport_p.h"
#include <private/qquickitem_p.h>
#include <QtQuick/private/qquickshadereffectsource_p.h>
@@ -46,16 +46,16 @@
#include <private/qqmlcomponentattached_p.h>
#include <private/qqmldata_p.h>
-#include "designerwindowmanager_p.h"
+#include "qquickdesignerwindowmanager_p.h"
QT_BEGIN_NAMESPACE
-DesignerSupport::DesignerSupport()
+QQuickDesignerSupport::QQuickDesignerSupport()
{
}
-DesignerSupport::~DesignerSupport()
+QQuickDesignerSupport::~QQuickDesignerSupport()
{
typedef QHash<QQuickItem*, QSGLayer*>::iterator ItemTextureHashIt;
@@ -67,7 +67,7 @@ DesignerSupport::~DesignerSupport()
}
}
-void DesignerSupport::refFromEffectItem(QQuickItem *referencedItem, bool hide)
+void QQuickDesignerSupport::refFromEffectItem(QQuickItem *referencedItem, bool hide)
{
if (referencedItem == 0)
return;
@@ -100,7 +100,7 @@ void DesignerSupport::refFromEffectItem(QQuickItem *referencedItem, bool hide)
}
}
-void DesignerSupport::derefFromEffectItem(QQuickItem *referencedItem, bool unhide)
+void QQuickDesignerSupport::derefFromEffectItem(QQuickItem *referencedItem, bool unhide)
{
if (referencedItem == 0)
return;
@@ -109,7 +109,7 @@ void DesignerSupport::derefFromEffectItem(QQuickItem *referencedItem, bool unhid
QQuickItemPrivate::get(referencedItem)->derefFromEffectItem(unhide);
}
-QImage DesignerSupport::renderImageForItem(QQuickItem *referencedItem, const QRectF &boundingRect, const QSize &imageSize)
+QImage QQuickDesignerSupport::renderImageForItem(QQuickItem *referencedItem, const QRectF &boundingRect, const QSize &imageSize)
{
if (referencedItem == 0 || referencedItem->parentItem() == 0) {
qDebug() << __FILE__ << __LINE__ << "Warning: Item can be rendered.";
@@ -136,7 +136,7 @@ QImage DesignerSupport::renderImageForItem(QQuickItem *referencedItem, const QRe
return renderImage;
}
-bool DesignerSupport::isDirty(QQuickItem *referencedItem, DirtyType dirtyType)
+bool QQuickDesignerSupport::isDirty(QQuickItem *referencedItem, DirtyType dirtyType)
{
if (referencedItem == 0)
return false;
@@ -144,7 +144,7 @@ bool DesignerSupport::isDirty(QQuickItem *referencedItem, DirtyType dirtyType)
return QQuickItemPrivate::get(referencedItem)->dirtyAttributes & dirtyType;
}
-void DesignerSupport::addDirty(QQuickItem *referencedItem, DesignerSupport::DirtyType dirtyType)
+void QQuickDesignerSupport::addDirty(QQuickItem *referencedItem, QQuickDesignerSupport::DirtyType dirtyType)
{
if (referencedItem == 0)
return;
@@ -152,7 +152,7 @@ void DesignerSupport::addDirty(QQuickItem *referencedItem, DesignerSupport::Dirt
QQuickItemPrivate::get(referencedItem)->dirtyAttributes |= dirtyType;
}
-void DesignerSupport::resetDirty(QQuickItem *referencedItem)
+void QQuickDesignerSupport::resetDirty(QQuickItem *referencedItem)
{
if (referencedItem == 0)
return;
@@ -161,7 +161,7 @@ void DesignerSupport::resetDirty(QQuickItem *referencedItem)
QQuickItemPrivate::get(referencedItem)->removeFromDirtyList();
}
-QTransform DesignerSupport::windowTransform(QQuickItem *referencedItem)
+QTransform QQuickDesignerSupport::windowTransform(QQuickItem *referencedItem)
{
if (referencedItem == 0)
return QTransform();
@@ -169,7 +169,7 @@ QTransform DesignerSupport::windowTransform(QQuickItem *referencedItem)
return QQuickItemPrivate::get(referencedItem)->itemToWindowTransform();
}
-QTransform DesignerSupport::parentTransform(QQuickItem *referencedItem)
+QTransform QQuickDesignerSupport::parentTransform(QQuickItem *referencedItem)
{
if (referencedItem == 0)
return QTransform();
@@ -211,12 +211,9 @@ bool isValidAnchorName(const QString &name)
return anchorNameList.contains(name);
}
-bool DesignerSupport::isAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
+bool QQuickDesignerSupport::isAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
{
-#ifndef QT_NO_DYNAMIC_CAST
- Q_ASSERT(dynamic_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(fromItem)));
-#endif
- QQuickItemPrivate *fromItemPrivate = static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(fromItem));
+ QQuickItemPrivate *fromItemPrivate = QQuickItemPrivate::get(fromItem);
QQuickAnchors *anchors = fromItemPrivate->anchors();
return anchors->fill() == toItem
|| anchors->centerIn() == toItem
@@ -229,9 +226,9 @@ bool DesignerSupport::isAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
|| anchors->baseline().item == toItem;
}
-bool DesignerSupport::areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
+bool QQuickDesignerSupport::areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
{
- foreach (QQuickItem *childItem, fromItem->childItems()) {
+ Q_FOREACH (QQuickItem *childItem, fromItem->childItems()) {
if (childItem) {
if (isAnchoredTo(childItem, toItem))
return true;
@@ -246,7 +243,7 @@ bool DesignerSupport::areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *to
QQuickAnchors *anchors(QQuickItem *item)
{
- QQuickItemPrivate *itemPrivate = static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item));
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
return itemPrivate->anchors();
}
@@ -278,7 +275,7 @@ QQuickAnchors::Anchor anchorLineFlagForName(const QString &name)
return QQuickAnchors::LeftAnchor;
}
-bool DesignerSupport::hasAnchor(QQuickItem *item, const QString &name)
+bool QQuickDesignerSupport::hasAnchor(QQuickItem *item, const QString &name)
{
if (!isValidAnchorName(name))
return false;
@@ -313,19 +310,19 @@ bool DesignerSupport::hasAnchor(QQuickItem *item, const QString &name)
return anchors(item)->usedAnchors().testFlag(anchorLineFlagForName(name));
}
-QQuickItem *DesignerSupport::anchorFillTargetItem(QQuickItem *item)
+QQuickItem *QQuickDesignerSupport::anchorFillTargetItem(QQuickItem *item)
{
return anchors(item)->fill();
}
-QQuickItem *DesignerSupport::anchorCenterInTargetItem(QQuickItem *item)
+QQuickItem *QQuickDesignerSupport::anchorCenterInTargetItem(QQuickItem *item)
{
return anchors(item)->centerIn();
}
-QPair<QString, QObject*> DesignerSupport::anchorLineTarget(QQuickItem *item, const QString &name, QQmlContext *context)
+QPair<QString, QObject*> QQuickDesignerSupport::anchorLineTarget(QQuickItem *item, const QString &name, QQmlContext *context)
{
QObject *targetObject = 0;
QString targetName;
@@ -350,7 +347,7 @@ QPair<QString, QObject*> DesignerSupport::anchorLineTarget(QQuickItem *item, con
return QPair<QString, QObject*>(targetName, targetObject);
}
-void DesignerSupport::resetAnchor(QQuickItem *item, const QString &name)
+void QQuickDesignerSupport::resetAnchor(QQuickItem *item, const QString &name)
{
if (name == QLatin1String("anchors.fill")) {
anchors(item)->resetFill();
@@ -373,7 +370,7 @@ void DesignerSupport::resetAnchor(QQuickItem *item, const QString &name)
}
}
-void DesignerSupport::emitComponentCompleteSignalForAttachedProperty(QQuickItem *item)
+void QQuickDesignerSupport::emitComponentCompleteSignalForAttachedProperty(QQuickItem *item)
{
QQmlData *data = QQmlData::get(item);
if (data && data->context) {
@@ -384,24 +381,24 @@ void DesignerSupport::emitComponentCompleteSignalForAttachedProperty(QQuickItem
}
}
-QList<QObject*> DesignerSupport::statesForItem(QQuickItem *item)
+QList<QObject*> QQuickDesignerSupport::statesForItem(QQuickItem *item)
{
QList<QObject*> objectList;
QList<QQuickState *> stateList = QQuickItemPrivate::get(item)->_states()->states();
objectList.reserve(stateList.size());
- foreach (QQuickState* state, stateList)
+ Q_FOREACH (QQuickState* state, stateList)
objectList.append(state);
return objectList;
}
-bool DesignerSupport::isComponentComplete(QQuickItem *item)
+bool QQuickDesignerSupport::isComponentComplete(QQuickItem *item)
{
- return static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item))->componentComplete;
+ return QQuickItemPrivate::get(item)->componentComplete;
}
-int DesignerSupport::borderWidth(QQuickItem *item)
+int QQuickDesignerSupport::borderWidth(QQuickItem *item)
{
QQuickRectangle *rectangle = qobject_cast<QQuickRectangle*>(item);
if (rectangle)
@@ -410,60 +407,71 @@ int DesignerSupport::borderWidth(QQuickItem *item)
return 0;
}
-void DesignerSupport::refreshExpressions(QQmlContext *context)
+void QQuickDesignerSupport::refreshExpressions(QQmlContext *context)
{
QQmlContextPrivate::get(context)->data->refreshExpressions();
}
-void DesignerSupport::setRootItem(QQuickView *view, QQuickItem *item)
+void QQuickDesignerSupport::setRootItem(QQuickView *view, QQuickItem *item)
{
QQuickViewPrivate::get(view)->setRootObject(item);
}
-bool DesignerSupport::isValidWidth(QQuickItem *item)
+bool QQuickDesignerSupport::isValidWidth(QQuickItem *item)
{
return QQuickItemPrivate::get(item)->heightValid;
}
-bool DesignerSupport::isValidHeight(QQuickItem *item)
+bool QQuickDesignerSupport::isValidHeight(QQuickItem *item)
{
return QQuickItemPrivate::get(item)->widthValid;
}
-void DesignerSupport::updateDirtyNode(QQuickItem *item)
+void QQuickDesignerSupport::updateDirtyNode(QQuickItem *item)
{
if (item->window())
QQuickWindowPrivate::get(item->window())->updateDirtyNode(item);
}
-void DesignerSupport::activateDesignerWindowManager()
+void QQuickDesignerSupport::activateDesignerWindowManager()
{
- QSGRenderLoop::setInstance(new DesignerWindowManager);
+ QSGRenderLoop::setInstance(new QQuickDesignerWindowManager);
}
-void DesignerSupport::activateDesignerMode()
+void QQuickDesignerSupport::activateDesignerMode()
{
QQmlEnginePrivate::activateDesignerMode();
}
-void DesignerSupport::disableComponentComplete()
+void QQuickDesignerSupport::disableComponentComplete()
{
QQmlVME::disableComponentComplete();
}
-void DesignerSupport::enableComponentComplete()
+void QQuickDesignerSupport::enableComponentComplete()
{
QQmlVME::enableComponentComplete();
}
-void DesignerSupport::createOpenGLContext(QQuickWindow *window)
+void QQuickDesignerSupport::createOpenGLContext(QQuickWindow *window)
{
- DesignerWindowManager::createOpenGLContext(window);
+ QQuickDesignerWindowManager::createOpenGLContext(window);
}
-void DesignerSupport::polishItems(QQuickWindow *window)
+void QQuickDesignerSupport::polishItems(QQuickWindow *window)
{
QQuickWindowPrivate::get(window)->polishItems();
}
+ComponentCompleteDisabler::ComponentCompleteDisabler()
+{
+ QQuickDesignerSupport::disableComponentComplete();
+}
+
+ComponentCompleteDisabler::~ComponentCompleteDisabler()
+{
+ QQuickDesignerSupport::enableComponentComplete();
+}
+
+
QT_END_NAMESPACE
diff --git a/src/quick/designer/designersupport.h b/src/quick/designer/qquickdesignersupport_p.h
index 51fcef4512..e15c109f7b 100644
--- a/src/quick/designer/designersupport.h
+++ b/src/quick/designer/qquickdesignersupport_p.h
@@ -45,7 +45,6 @@
// We mean it.
//
-
#include <QtQuick/qtquickglobal.h>
#include <QtCore/QtGlobal>
#include <QtCore/QHash>
@@ -62,9 +61,13 @@ class QQuickView;
class QObject;
class QQuickWindow;
-class Q_QUICK_EXPORT DesignerSupport
+class Q_QUICK_EXPORT QQuickDesignerSupport
{
public:
+ typedef QByteArray PropertyName;
+ typedef QList<PropertyName> PropertyNameList;
+ typedef QByteArray TypeName;
+
enum DirtyType {
TransformOrigin = 0x00000001,
Transform = 0x00000002,
@@ -95,8 +98,8 @@ public:
};
- DesignerSupport();
- ~DesignerSupport();
+ QQuickDesignerSupport();
+ ~QQuickDesignerSupport();
void refFromEffectItem(QQuickItem *referencedItem, bool hide = true);
void derefFromEffectItem(QQuickItem *referencedItem, bool unhide = true);
@@ -119,7 +122,6 @@ public:
static void resetAnchor(QQuickItem *item, const QString &name);
static void emitComponentCompleteSignalForAttachedProperty(QQuickItem *item);
-
static QList<QObject*> statesForItem(QQuickItem *item);
static bool isComponentComplete(QQuickItem *item);
@@ -149,6 +151,16 @@ private:
QHash<QQuickItem*, QSGLayer*> m_itemTextureHash;
};
+class Q_QUICK_EXPORT ComponentCompleteDisabler
+{
+public:
+ ComponentCompleteDisabler();
+
+ ~ComponentCompleteDisabler();
+};
+
+typedef QQuickDesignerSupport DesignerSupport;
+
QT_END_NAMESPACE
#endif // DESIGNERSUPPORT_H
diff --git a/src/quick/designer/qquickdesignersupportitems.cpp b/src/quick/designer/qquickdesignersupportitems.cpp
new file mode 100644
index 0000000000..4f23fe6630
--- /dev/null
+++ b/src/quick/designer/qquickdesignersupportitems.cpp
@@ -0,0 +1,320 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickdesignersupportitems_p.h"
+#include "qquickdesignersupportproperties_p.h"
+
+#include <private/qabstractanimation_p.h>
+#include <private/qobject_p.h>
+#include <private/qquickbehavior_p.h>
+#include <private/qquicktext_p.h>
+#include <private/qquicktextinput_p.h>
+#include <private/qquicktextedit_p.h>
+#include <private/qquicktransition_p.h>
+
+#include <private/qquickanimation_p.h>
+#include <private/qqmlmetatype_p.h>
+#include <private/qqmltimer_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static void (*fixResourcePathsForObjectCallBack)(QObject*) = 0;
+
+static void stopAnimation(QObject *object)
+{
+ if (object == 0)
+ return;
+
+ QQuickTransition *transition = qobject_cast<QQuickTransition*>(object);
+ QQuickAbstractAnimation *animation = qobject_cast<QQuickAbstractAnimation*>(object);
+ QQmlTimer *timer = qobject_cast<QQmlTimer*>(object);
+ if (transition) {
+ transition->setFromState(QString());
+ transition->setToState(QString());
+ } else if (animation) {
+// QQuickScriptAction *scriptAimation = qobject_cast<QQuickScriptAction*>(animation);
+// if (scriptAimation) FIXME
+// scriptAimation->setScript(QQmlScriptString());
+ animation->setLoops(1);
+ animation->complete();
+ animation->setDisableUserControl();
+ } else if (timer) {
+ timer->blockSignals(true);
+ }
+}
+
+static void allSubObjects(QObject *object, QObjectList &objectList)
+{
+ // don't add null pointer and stop if the object is already in the list
+ if (!object || objectList.contains(object))
+ return;
+
+ objectList.append(object);
+
+ for (int index = QObject::staticMetaObject.propertyOffset();
+ index < object->metaObject()->propertyCount();
+ index++) {
+ QMetaProperty metaProperty = object->metaObject()->property(index);
+
+ // search recursive in property objects
+ if (metaProperty.isReadable()
+ && metaProperty.isWritable()
+ && QQmlMetaType::isQObject(metaProperty.userType())) {
+ if (qstrcmp(metaProperty.name(), "parent")) {
+ QObject *propertyObject = QQmlMetaType::toQObject(metaProperty.read(object));
+ allSubObjects(propertyObject, objectList);
+ }
+
+ }
+
+ // search recursive in property object lists
+ if (metaProperty.isReadable()
+ && QQmlMetaType::isList(metaProperty.userType())) {
+ QQmlListReference list(object, metaProperty.name());
+ if (list.canCount() && list.canAt()) {
+ for (int i = 0; i < list.count(); i++) {
+ QObject *propertyObject = list.at(i);
+ allSubObjects(propertyObject, objectList);
+
+ }
+ }
+ }
+ }
+
+ // search recursive in object children list
+ Q_FOREACH (QObject *childObject, object->children()) {
+ allSubObjects(childObject, objectList);
+ }
+
+ // search recursive in quick item childItems list
+ QQuickItem *quickItem = qobject_cast<QQuickItem*>(object);
+ if (quickItem) {
+ Q_FOREACH (QQuickItem *childItem, quickItem->childItems()) {
+ allSubObjects(childItem, objectList);
+ }
+ }
+}
+
+void QQuickDesignerSupportItems::tweakObjects(QObject *object)
+{
+ QObjectList objectList;
+ allSubObjects(object, objectList);
+ Q_FOREACH (QObject* childObject, objectList) {
+ stopAnimation(childObject);
+ if (fixResourcePathsForObjectCallBack)
+ fixResourcePathsForObjectCallBack(childObject);
+ }
+}
+
+static QObject *createDummyWindow(QQmlEngine *engine)
+{
+ QQmlComponent component(engine, QUrl(QStringLiteral("qrc:/qtquickplugin/mockfiles/Window.qml")));
+ return component.create();
+}
+
+static bool isWindowMetaObject(const QMetaObject *metaObject)
+{
+ if (metaObject) {
+ if (metaObject->className() == QByteArrayLiteral("QWindow"))
+ return true;
+
+ return isWindowMetaObject(metaObject->superClass());
+ }
+
+ return false;
+}
+
+static bool isWindow(QObject *object) {
+ if (object)
+ return isWindowMetaObject(object->metaObject());
+
+ return false;
+}
+
+static QQmlType *getQmlType(const QString &typeName, int majorNumber, int minorNumber)
+{
+ return QQmlMetaType::qmlType(typeName, majorNumber, minorNumber);
+}
+
+static bool isCrashingType(QQmlType *type)
+{
+ if (type) {
+ if (type->qmlTypeName() == QStringLiteral("QtMultimedia/MediaPlayer"))
+ return true;
+
+ if (type->qmlTypeName() == QStringLiteral("QtMultimedia/Audio"))
+ return true;
+
+ if (type->qmlTypeName() == QStringLiteral("QtQuick.Controls/MenuItem"))
+ return true;
+
+ if (type->qmlTypeName() == QStringLiteral("QtQuick.Controls/Menu"))
+ return true;
+
+ if (type->qmlTypeName() == QStringLiteral("QtQuick/Timer"))
+ return true;
+ }
+
+ return false;
+}
+
+QObject *QQuickDesignerSupportItems::createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context)
+{
+ ComponentCompleteDisabler disableComponentComplete;
+
+ Q_UNUSED(disableComponentComplete)
+
+ QObject *object = 0;
+ QQmlType *type = getQmlType(typeName, majorNumber, minorNumber);
+
+ if (isCrashingType(type)) {
+ object = new QObject;
+ } else if (type) {
+ if ( type->isComposite()) {
+ object = createComponent(type->sourceUrl(), context);
+ } else
+ {
+ if (type->typeName() == "QQmlComponent") {
+ object = new QQmlComponent(context->engine(), 0);
+ } else {
+ object = type->create();
+ }
+ }
+
+ if (isWindow(object)) {
+ delete object;
+ object = createDummyWindow(context->engine());
+ }
+
+ }
+
+ if (!object) {
+ qWarning() << "QuickDesigner: Cannot create an object of type"
+ << QString::fromLatin1("%1 %2,%3").arg(typeName).arg(majorNumber).arg(minorNumber)
+ << "- type isn't known to declarative meta type system";
+ }
+
+ tweakObjects(object);
+
+ if (object && QQmlEngine::contextForObject(object) == 0)
+ QQmlEngine::setContextForObject(object, context);
+
+ QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
+
+ return object;
+}
+
+QObject *QQuickDesignerSupportItems::createComponent(const QUrl &componentUrl, QQmlContext *context)
+{
+ ComponentCompleteDisabler disableComponentComplete;
+ Q_UNUSED(disableComponentComplete)
+
+ QQmlComponent component(context->engine(), componentUrl);
+
+ QObject *object = component.beginCreate(context);
+ tweakObjects(object);
+ component.completeCreate();
+ QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
+
+ if (component.isError()) {
+ qWarning() << "Error in:" << Q_FUNC_INFO << componentUrl;
+ Q_FOREACH (const QQmlError &error, component.errors())
+ qWarning() << error;
+ }
+ return object;
+}
+
+bool QQuickDesignerSupportItems::objectWasDeleted(QObject *object)
+{
+ return QObjectPrivate::get(object)->wasDeleted;
+}
+
+void QQuickDesignerSupportItems::disableNativeTextRendering(QQuickItem *item)
+{
+ QQuickText *text = qobject_cast<QQuickText*>(item);
+ if (text)
+ text->setRenderType(QQuickText::QtRendering);
+
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(item);
+ if (textInput)
+ textInput->setRenderType(QQuickTextInput::QtRendering);
+
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(item);
+ if (textEdit)
+ textEdit->setRenderType(QQuickTextEdit::QtRendering);
+}
+
+void QQuickDesignerSupportItems::disableTextCursor(QQuickItem *item)
+{
+ Q_FOREACH (QQuickItem *childItem, item->childItems())
+ disableTextCursor(childItem);
+
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(item);
+ if (textInput)
+ textInput->setCursorVisible(false);
+
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(item);
+ if (textEdit)
+ textEdit->setCursorVisible(false);
+}
+
+void QQuickDesignerSupportItems::disableTransition(QObject *object)
+{
+ QQuickTransition *transition = qobject_cast<QQuickTransition*>(object);
+ Q_ASSERT(transition);
+ const QString invalidState = QLatin1String("invalidState");
+ transition->setToState(invalidState);
+ transition->setFromState(invalidState);
+}
+
+void QQuickDesignerSupportItems::disableBehaivour(QObject *object)
+{
+ QQuickBehavior* behavior = qobject_cast<QQuickBehavior*>(object);
+ Q_ASSERT(behavior);
+ behavior->setEnabled(false);
+}
+
+void QQuickDesignerSupportItems::stopUnifiedTimer()
+{
+ QUnifiedTimer::instance()->setSlowdownFactor(0.00001);
+ QUnifiedTimer::instance()->setSlowModeEnabled(true);
+}
+
+void QQuickDesignerSupportItems::registerFixResourcePathsForObjectCallBack(void (*callback)(QObject *))
+{
+ fixResourcePathsForObjectCallBack = callback;
+}
+
+QT_END_NAMESPACE
+
+
diff --git a/src/qml/debugger/qqmlconfigurabledebugservice_p.h b/src/quick/designer/qquickdesignersupportitems_p.h
index cf69c3a1f6..c15d651b33 100644
--- a/src/qml/debugger/qqmlconfigurabledebugservice_p.h
+++ b/src/quick/designer/qquickdesignersupportitems_p.h
@@ -3,7 +3,7 @@
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
@@ -31,9 +31,8 @@
**
****************************************************************************/
-
-#ifndef QQMLCONFIGURABLEDEBUGSEVICE_H
-#define QQMLCONFIGURABLEDEBUGSEVICE_H
+#ifndef DESIGNERSUPPORTITEM_H
+#define DESIGNERSUPPORTITEM_H
//
// W A R N I N G
@@ -46,34 +45,33 @@
// We mean it.
//
-#include "qqmldebugservice_p.h"
+#include "qquickdesignersupport_p.h"
+
+#include <QObject>
+#include <QString>
+#include <QVariant>
+#include <QList>
+#include <QByteArray>
+#include <QQmlContext>
+#include <QQmlListReference>
QT_BEGIN_NAMESPACE
-class QMutex;
-class QQmlConfigurableDebugServicePrivate;
-class QQmlConfigurableDebugService : public QQmlDebugService
+class Q_QUICK_EXPORT QQuickDesignerSupportItems
{
- Q_OBJECT
public:
- QQmlConfigurableDebugService(const QString &name, float version, QObject *parent = 0);
-
-protected:
- QQmlConfigurableDebugService(QQmlDebugServicePrivate &dd, const QString &name, float version, QObject *parent = 0);
-
- QMutex *configMutex();
- void stopWaiting();
- void init();
-
- void stateChanged(State);
- void engineAboutToBeAdded(QQmlEngine *);
-
- virtual ~QQmlConfigurableDebugService() {}
-private:
- Q_DISABLE_COPY(QQmlConfigurableDebugService)
- Q_DECLARE_PRIVATE(QQmlConfigurableDebugService)
+ static QObject *createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context);
+ static QObject *createComponent(const QUrl &componentUrl, QQmlContext *context);
+ static void tweakObjects(QObject *object);
+ static bool objectWasDeleted(QObject *object);
+ static void disableNativeTextRendering(QQuickItem *item);
+ static void disableTextCursor(QQuickItem *item);
+ static void disableTransition(QObject *object);
+ static void disableBehaivour(QObject *object);
+ static void stopUnifiedTimer();
+ static void registerFixResourcePathsForObjectCallBack(void (*callback)(QObject *));
};
QT_END_NAMESPACE
-#endif // QQMLCONFIGURABLEDEBUGSEVICE_H
+#endif // DESIGNERSUPPORTITEM_H
diff --git a/src/qml/qml/ftw/qqmlpool.cpp b/src/quick/designer/qquickdesignersupportmetainfo.cpp
index b86dcba107..c6c7ed38b9 100644
--- a/src/qml/qml/ftw/qqmlpool.cpp
+++ b/src/quick/designer/qquickdesignersupportmetainfo.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
@@ -31,59 +31,38 @@
**
****************************************************************************/
-#include "qqmlpool_p.h"
-#include <stdlib.h>
+#include "qquickdesignersupportmetainfo_p.h"
+#include "qqmldesignermetaobject_p.h"
-#ifdef Q_OS_QNX
-#include <malloc.h>
-#endif
-
-// #define POOL_DEBUG
+#include <private/qqmlmetatype_p.h>
QT_BEGIN_NAMESPACE
-void QQmlPool::newpage()
+bool QQuickDesignerSupportMetaInfo::isSubclassOf(QObject *object, const QByteArray &superTypeName)
{
-#ifdef POOL_DEBUG
- qWarning("QQmlPool: Allocating page");
-#endif
-
- Page *page = (Page *)malloc(sizeof(Page));
- page->header.next = _page;
- page->header.free = page->memory;
- _page = page;
-}
+ if (object == 0)
+ return false;
-void QQmlPool::clear()
-{
-#ifdef POOL_DEBUG
- int count = 0;
-#endif
+ const QMetaObject *metaObject = object->metaObject();
- Class *c = _classList;
- while (c) {
- Class *n = c->_next;
- c->_destroy(c);
-#ifdef POOL_DEBUG
- ++count;
-#endif
- c = n;
- }
+ while (metaObject) {
+ QQmlType *qmlType = QQmlMetaType::qmlType(metaObject);
+ if (qmlType && qmlType->qmlTypeName() == QLatin1String(superTypeName)) // ignore version numbers
+ return true;
-#ifdef POOL_DEBUG
- qWarning("QQmlPool: Destroyed %d objects", count);
-#endif
+ if (metaObject->className() == superTypeName)
+ return true;
- Page *p = _page;
- while (p) {
- Page *n = p->header.next;
- free(p);
- p = n;
+ metaObject = metaObject->superClass();
}
- _classList = 0;
- _page = 0;
+ return false;
}
+void QQuickDesignerSupportMetaInfo::registerNotifyPropertyChangeCallBack(void (*callback)(QObject *, const QQuickDesignerSupport::PropertyName &))
+{
+ QQmlDesignerMetaObject::registerNotifyPropertyChangeCallBack(callback);
+}
QT_END_NAMESPACE
+
diff --git a/src/quick/designer/qquickdesignersupportmetainfo_p.h b/src/quick/designer/qquickdesignersupportmetainfo_p.h
new file mode 100644
index 0000000000..52bf8e3ac0
--- /dev/null
+++ b/src/quick/designer/qquickdesignersupportmetainfo_p.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DESIGNERSUPPORTMETAINFO_H
+#define DESIGNERSUPPORTMETAINFO_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickdesignersupport_p.h"
+
+#include <QObject>
+#include <QByteArray>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QQuickDesignerSupportMetaInfo
+{
+public:
+ static bool isSubclassOf(QObject *object, const QByteArray &superTypeName);
+ static void registerNotifyPropertyChangeCallBack(void (*callback)(QObject *, const QQuickDesignerSupport::PropertyName &));
+};
+
+QT_END_NAMESPACE
+
+#endif // DESIGNERSUPPORTMETAINFO_H
diff --git a/src/quick/designer/qquickdesignersupportproperties.cpp b/src/quick/designer/qquickdesignersupportproperties.cpp
new file mode 100644
index 0000000000..96f09ada48
--- /dev/null
+++ b/src/quick/designer/qquickdesignersupportproperties.cpp
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickdesignersupportproperties_p.h"
+
+#include "qqmldesignermetaobject_p.h"
+#include "qquickdesignercustomobjectdata_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static void addToPropertyNameListIfNotBlackListed(QQuickDesignerSupport::PropertyNameList *propertyNameList,
+ const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ if (!QQuickDesignerSupportProperties::isPropertyBlackListed(propertyName))
+ propertyNameList->append(propertyName);
+}
+
+void QQuickDesignerSupportProperties::createNewDynamicProperty(QObject *object, QQmlEngine *engine, const QString &name)
+{
+ QQmlDesignerMetaObject::getNodeInstanceMetaObject(object, engine)->createNewDynamicProperty(name);
+}
+
+void QQuickDesignerSupportProperties::registerNodeInstanceMetaObject(QObject *object, QQmlEngine *engine)
+{
+ // we just create one and the ownership goes automatically to the object in nodeinstance see init method
+ QQmlDesignerMetaObject::getNodeInstanceMetaObject(object, engine);
+}
+
+bool QQuickDesignerSupportProperties::hasFullImplementedListInterface(const QQmlListReference &list)
+{
+ return list.isValid() && list.canCount() && list.canAt() && list.canAppend() && list.canClear();
+}
+
+void QQuickDesignerSupportProperties::registerCustomData(QObject *object)
+{
+ QQuickDesignerCustomObjectData::registerData(object);
+}
+
+QVariant QQuickDesignerSupportProperties::getResetValue(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ return QQuickDesignerCustomObjectData::getResetValue(object, propertyName);
+}
+
+void QQuickDesignerSupportProperties::doResetProperty(QObject *object, QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQuickDesignerCustomObjectData::doResetProperty(object, context, propertyName);
+}
+
+bool QQuickDesignerSupportProperties::hasValidResetBinding(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ return QQuickDesignerCustomObjectData::hasValidResetBinding(object, propertyName);
+}
+
+bool QQuickDesignerSupportProperties::hasBindingForProperty(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ bool *hasChanged)
+{
+ return QQuickDesignerCustomObjectData::hasBindingForProperty(object, context, propertyName, hasChanged);
+}
+
+void QQuickDesignerSupportProperties::setPropertyBinding(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression)
+{
+ QQuickDesignerCustomObjectData::setPropertyBinding(object, context, propertyName, expression);
+}
+
+void QQuickDesignerSupportProperties::keepBindingFromGettingDeleted(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQuickDesignerCustomObjectData::keepBindingFromGettingDeleted(object, context, propertyName);
+}
+
+bool QQuickDesignerSupportProperties::isPropertyQObject(const QMetaProperty &metaProperty)
+{
+ return QQmlMetaType::isQObject(metaProperty.userType());
+}
+
+
+QObject *QQuickDesignerSupportProperties::readQObjectProperty(const QMetaProperty &metaProperty, QObject *object)
+{
+ return QQmlMetaType::toQObject(metaProperty.read(object));
+}
+
+void QQuickDesignerSupportProperties::getPropertyCache(QObject *object, QQmlEngine *engine)
+{
+ QQmlEnginePrivate::get(engine)->cache(object->metaObject());
+}
+
+QQuickDesignerSupport::PropertyNameList QQuickDesignerSupportProperties::propertyNameListForWritableProperties(QObject *object,
+ const QQuickDesignerSupport::PropertyName &baseName,
+ QObjectList *inspectedObjects)
+{
+ QQuickDesignerSupport::PropertyNameList propertyNameList;
+
+ QObjectList localObjectList;
+
+ if (inspectedObjects == 0)
+ inspectedObjects = &localObjectList;
+
+
+ if (inspectedObjects->contains(object))
+ return propertyNameList;
+
+ inspectedObjects->append(object);
+
+ const QMetaObject *metaObject = object->metaObject();
+ for (int index = 0; index < metaObject->propertyCount(); ++index) {
+ QMetaProperty metaProperty = metaObject->property(index);
+ QQmlProperty declarativeProperty(object, QString::fromUtf8(metaProperty.name()));
+ if (declarativeProperty.isValid() && !declarativeProperty.isWritable() && declarativeProperty.propertyTypeCategory() == QQmlProperty::Object) {
+ if (declarativeProperty.name() != QLatin1String("parent")) {
+ QObject *childObject = QQmlMetaType::toQObject(declarativeProperty.read());
+ if (childObject)
+ propertyNameList.append(propertyNameListForWritableProperties(childObject,
+ baseName + QQuickDesignerSupport::PropertyName(metaProperty.name())
+ + '.', inspectedObjects));
+ }
+ } else if (QQmlValueTypeFactory::valueType(metaProperty.userType())) {
+ QQmlValueType *valueType = QQmlValueTypeFactory::valueType(metaProperty.userType());
+ valueType->setValue(metaProperty.read(object));
+ propertyNameList.append(propertyNameListForWritableProperties(valueType,
+ baseName + QQuickDesignerSupport::PropertyName(metaProperty.name())
+ + '.', inspectedObjects));
+ }
+
+ if (metaProperty.isReadable() && metaProperty.isWritable()) {
+ addToPropertyNameListIfNotBlackListed(&propertyNameList,
+ baseName + QQuickDesignerSupport::PropertyName(metaProperty.name()));
+ }
+ }
+
+ return propertyNameList;
+}
+
+bool QQuickDesignerSupportProperties::isPropertyBlackListed(const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ if (propertyName.contains(".") && propertyName.contains("__"))
+ return true;
+
+ if (propertyName.count(".") > 1)
+ return true;
+
+ return false;
+}
+
+QQuickDesignerSupport::PropertyNameList QQuickDesignerSupportProperties::allPropertyNames(QObject *object,
+ const QQuickDesignerSupport::PropertyName &baseName,
+ QObjectList *inspectedObjects)
+{
+ QQuickDesignerSupport::PropertyNameList propertyNameList;
+
+ QObjectList localObjectList;
+
+ if (inspectedObjects == 0)
+ inspectedObjects = &localObjectList;
+
+
+ if (inspectedObjects->contains(object))
+ return propertyNameList;
+
+ inspectedObjects->append(object);
+
+
+ const QMetaObject *metaObject = object->metaObject();
+ for (int index = 0; index < metaObject->propertyCount(); ++index) {
+ QMetaProperty metaProperty = metaObject->property(index);
+ QQmlProperty declarativeProperty(object, QString::fromUtf8(metaProperty.name()));
+ if (declarativeProperty.isValid() && declarativeProperty.propertyTypeCategory() == QQmlProperty::Object) {
+ if (declarativeProperty.name() != QLatin1String("parent")) {
+ QObject *childObject = QQmlMetaType::toQObject(declarativeProperty.read());
+ if (childObject)
+ propertyNameList.append(allPropertyNames(childObject,
+ baseName
+ + QQuickDesignerSupport::PropertyName(metaProperty.name())
+ + '.', inspectedObjects));
+ }
+ } else if (QQmlValueTypeFactory::valueType(metaProperty.userType())) {
+ QQmlValueType *valueType = QQmlValueTypeFactory::valueType(metaProperty.userType());
+ valueType->setValue(metaProperty.read(object));
+ propertyNameList.append(baseName + QQuickDesignerSupport::PropertyName(metaProperty.name()));
+ propertyNameList.append(allPropertyNames(valueType,
+ baseName
+ + QQuickDesignerSupport::PropertyName(metaProperty.name())
+ + '.', inspectedObjects));
+ } else {
+ addToPropertyNameListIfNotBlackListed(&propertyNameList,
+ baseName + QQuickDesignerSupport::PropertyName(metaProperty.name()));
+ }
+ }
+
+ return propertyNameList;
+}
+
+
+QT_END_NAMESPACE
+
+
+
+
diff --git a/src/quick/designer/qquickdesignersupportproperties_p.h b/src/quick/designer/qquickdesignersupportproperties_p.h
new file mode 100644
index 0000000000..187bc6e2a6
--- /dev/null
+++ b/src/quick/designer/qquickdesignersupportproperties_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DESIGNERSUPPORTPROPERTIES_H
+#define DESIGNERSUPPORTPROPERTIES_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickdesignersupport_p.h"
+
+#include <QObject>
+#include <QString>
+#include <QVariant>
+#include <QList>
+#include <QByteArray>
+#include <QQmlContext>
+#include <QQmlListReference>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QQuickDesignerSupportProperties
+{
+public:
+ static void createNewDynamicProperty(QObject *object, QQmlEngine *engine, const QString &name);
+ static void registerNodeInstanceMetaObject(QObject *object, QQmlEngine *engine);
+ static void registerCustomData(QObject *object);
+ static QVariant getResetValue(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName);
+ static void doResetProperty(QObject *object, QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName);
+ static bool hasValidResetBinding(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName);
+
+ static bool hasBindingForProperty(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ bool *hasChanged);
+ static void setPropertyBinding(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression);
+ static void keepBindingFromGettingDeleted(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName);
+
+ static bool isPropertyQObject(const QMetaProperty &metaProperty);
+ static QObject *readQObjectProperty(const QMetaProperty &metaProperty, QObject *object);
+
+ static void getPropertyCache(QObject *object, QQmlEngine *engine);
+ static bool isPropertyBlackListed(const QQuickDesignerSupport::PropertyName &propertyName);
+ static QQuickDesignerSupport::PropertyNameList propertyNameListForWritableProperties(QObject *object,
+ const QQuickDesignerSupport::PropertyName &baseName = QQuickDesignerSupport::PropertyName(),
+ QObjectList *inspectedObjects = 0);
+ static QQuickDesignerSupport::PropertyNameList allPropertyNames(QObject *object,
+ const QQuickDesignerSupport::PropertyName &baseName = QQuickDesignerSupport::PropertyName(),
+ QObjectList *inspectedObjects = 0);
+ static bool hasFullImplementedListInterface(const QQmlListReference &list);
+};
+
+QT_END_NAMESPACE
+
+#endif // DESIGNERSUPPORTPROPERTIES_H
diff --git a/src/quick/designer/qquickdesignersupportpropertychanges.cpp b/src/quick/designer/qquickdesignersupportpropertychanges.cpp
new file mode 100644
index 0000000000..92fa637b54
--- /dev/null
+++ b/src/quick/designer/qquickdesignersupportpropertychanges.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickdesignersupportpropertychanges_p.h"
+
+#include <private/qquickpropertychanges_p.h>
+#include <private/qquickstateoperations_p.h>
+
+QT_BEGIN_NAMESPACE
+
+void QQuickDesignerSupportPropertyChanges::attachToState(QObject *propertyChanges)
+{
+ QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges);
+
+ if (!propertyChange)
+ return;
+
+ propertyChange->attachToState();
+}
+
+QObject *QQuickDesignerSupportPropertyChanges::targetObject(QObject *propertyChanges)
+{
+ QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges);
+
+ if (!propertyChange)
+ return 0;
+
+ return propertyChange->object();
+}
+
+void QQuickDesignerSupportPropertyChanges::removeProperty(QObject *propertyChanges, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges);
+
+ if (!propertyChange)
+ return;
+
+ propertyChange->removeProperty(QString::fromUtf8(propertyName));
+}
+
+QVariant QQuickDesignerSupportPropertyChanges::getProperty(QObject *propertyChanges,
+ const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges);
+
+ if (!propertyChange)
+ return QVariant();
+
+ return propertyChange->property(QString::fromUtf8(propertyName));
+}
+
+void QQuickDesignerSupportPropertyChanges::changeValue(QObject *propertyChanges,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QVariant &value)
+{
+ QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges);
+
+ if (!propertyChange)
+ return;
+
+ propertyChange->changeValue(QString::fromUtf8(propertyName), value);
+}
+
+void QQuickDesignerSupportPropertyChanges::changeExpression(QObject *propertyChanges,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression)
+{
+ QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges);
+
+ if (!propertyChange)
+ return;
+
+ propertyChange->changeExpression(QString::fromUtf8(propertyName), expression);
+}
+
+QObject *QQuickDesignerSupportPropertyChanges::stateObject(QObject *propertyChanges)
+{
+ QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges);
+
+ if (!propertyChange)
+ return 0;
+
+ return propertyChange->state();
+}
+
+bool QQuickDesignerSupportPropertyChanges::isNormalProperty(const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QMetaObject metaObject = QQuickPropertyChanges::staticMetaObject;
+
+ return (metaObject.indexOfProperty(propertyName) > 0); // 'restoreEntryValues', 'explicit'
+}
+
+void QQuickDesignerSupportPropertyChanges::detachFromState(QObject *propertyChanges)
+{
+ QQuickPropertyChanges *propertyChange = qobject_cast<QQuickPropertyChanges*>(propertyChanges);
+
+ if (!propertyChange)
+ return;
+
+ propertyChange->detachFromState();
+}
+
+QT_END_NAMESPACE
+
+
diff --git a/src/quick/designer/qquickdesignersupportpropertychanges_p.h b/src/quick/designer/qquickdesignersupportpropertychanges_p.h
new file mode 100644
index 0000000000..432383d5b4
--- /dev/null
+++ b/src/quick/designer/qquickdesignersupportpropertychanges_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DESIGNERSUPPORTPROPERTYCHANGES_H
+#define DESIGNERSUPPORTPROPERTYCHANGES_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickdesignersupport_p.h"
+
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QQuickDesignerSupportPropertyChanges
+{
+public:
+ static void detachFromState(QObject *propertyChanges);
+ static void attachToState(QObject *propertyChanges);
+ static QObject *targetObject(QObject *propertyChanges);
+ static void removeProperty(QObject *propertyChanges, const QQuickDesignerSupport::PropertyName &propertyName);
+ static QVariant getProperty(QObject *propertyChanges, const QQuickDesignerSupport::PropertyName &propertyName);
+ static void changeValue(QObject *propertyChanges, const QQuickDesignerSupport::PropertyName &propertyName, const QVariant &value);
+ static void changeExpression(QObject *propertyChanges, const QQuickDesignerSupport::PropertyName &propertyName, const QString &expression);
+ static QObject *stateObject(QObject *propertyChanges);
+ static bool isNormalProperty(const QQuickDesignerSupport::PropertyName &propertyName);
+};
+
+QT_END_NAMESPACE
+
+#endif // DESIGNERSUPPORTPROPERTYCHANGES_H
diff --git a/src/quick/designer/qquickdesignersupportstates.cpp b/src/quick/designer/qquickdesignersupportstates.cpp
new file mode 100644
index 0000000000..b75ec7115a
--- /dev/null
+++ b/src/quick/designer/qquickdesignersupportstates.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickdesignersupportstates_p.h"
+
+#include <private/qquickstategroup_p.h>
+#include <private/qquickpropertychanges_p.h>
+
+QT_BEGIN_NAMESPACE
+
+bool QQuickDesignerSupportStates::isStateActive(QObject *object, QQmlContext *context)
+{
+ QQuickState *stateObject = qobject_cast<QQuickState*>(object);
+
+ if (!stateObject)
+ return false;
+
+ QQuickStateGroup *stateGroup = stateObject->stateGroup();
+
+ QQmlProperty property(object, QLatin1String("name"), context);
+
+ return stateObject && stateGroup && stateGroup->state() == property.read();
+}
+
+void QQuickDesignerSupportStates::activateState(QObject *object, QQmlContext *context)
+{
+ QQuickState *stateObject = qobject_cast<QQuickState*>(object);
+
+ if (!stateObject)
+ return;
+
+ QQuickStateGroup *stateGroup = stateObject->stateGroup();
+
+ QQmlProperty property(object, QLatin1String("name"), context);
+
+ stateGroup->setState(property.read().toString());
+}
+
+void QQuickDesignerSupportStates::deactivateState(QObject *object)
+{
+ QQuickState *stateObject = qobject_cast<QQuickState*>(object);
+
+ if (!stateObject)
+ return;
+
+ QQuickStateGroup *stateGroup = stateObject->stateGroup();
+
+ if (stateGroup)
+ stateGroup->setState(QString());
+}
+
+bool QQuickDesignerSupportStates::changeValueInRevertList(QObject *state, QObject *target,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QVariant &value)
+{
+ QQuickState *stateObject = qobject_cast<QQuickState*>(state);
+
+ if (!stateObject)
+ return false;
+
+ return stateObject->changeValueInRevertList(target, QString::fromUtf8(propertyName), value);
+}
+
+bool QQuickDesignerSupportStates::updateStateBinding(QObject *state, QObject *target,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression)
+{
+ QQuickState *stateObject = qobject_cast<QQuickState*>(state);
+
+ if (!stateObject)
+ return false;
+
+ return stateObject->changeValueInRevertList(target, QString::fromUtf8(propertyName), expression);
+}
+
+bool QQuickDesignerSupportStates::resetStateProperty(QObject *state, QObject *target,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QVariant & /* resetValue */)
+{
+ QQuickState *stateObject = qobject_cast<QQuickState*>(state);
+
+ if (!stateObject)
+ return false;
+
+ return stateObject->removeEntryFromRevertList(target, QString::fromUtf8(propertyName));
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/quick/designer/qquickdesignersupportstates_p.h b/src/quick/designer/qquickdesignersupportstates_p.h
new file mode 100644
index 0000000000..daa5a2ff01
--- /dev/null
+++ b/src/quick/designer/qquickdesignersupportstates_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DESIGNERSUPPORTSTATES_H
+#define DESIGNERSUPPORTSTATES_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickdesignersupport_p.h"
+
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QQuickDesignerSupportStates
+{
+public:
+ static bool isStateActive(QObject *object, QQmlContext *context);
+ static void activateState(QObject *object, QQmlContext *context);
+ static void deactivateState(QObject *object);
+ static bool changeValueInRevertList(QObject *state,
+ QObject *target,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QVariant &value);
+
+ static bool updateStateBinding(QObject *state, QObject *target,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression);
+
+ static bool resetStateProperty(QObject *state, QObject *target,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QVariant &);
+};
+
+QT_END_NAMESPACE
+
+#endif // DESIGNERSUPPORTSTATES_H
diff --git a/src/quick/designer/designerwindowmanager.cpp b/src/quick/designer/qquickdesignerwindowmanager.cpp
index f37d6a2180..b1ad42ddb4 100644
--- a/src/quick/designer/designerwindowmanager.cpp
+++ b/src/quick/designer/qquickdesignerwindowmanager.cpp
@@ -31,35 +31,34 @@
**
****************************************************************************/
-#include "designerwindowmanager_p.h"
+#include "qquickdesignerwindowmanager_p.h"
#include "private/qquickwindow_p.h"
#include <QtGui/QOpenGLContext>
#include <QtQuick/QQuickWindow>
-
QT_BEGIN_NAMESPACE
-DesignerWindowManager::DesignerWindowManager()
+QQuickDesignerWindowManager::QQuickDesignerWindowManager()
: m_sgContext(QSGContext::createDefaultContext())
{
m_renderContext.reset(new QSGRenderContext(m_sgContext.data()));
}
-void DesignerWindowManager::show(QQuickWindow *window)
+void QQuickDesignerWindowManager::show(QQuickWindow *window)
{
makeOpenGLContext(window);
}
-void DesignerWindowManager::hide(QQuickWindow *)
+void QQuickDesignerWindowManager::hide(QQuickWindow *)
{
}
-void DesignerWindowManager::windowDestroyed(QQuickWindow *)
+void QQuickDesignerWindowManager::windowDestroyed(QQuickWindow *)
{
}
-void DesignerWindowManager::makeOpenGLContext(QQuickWindow *window)
+void QQuickDesignerWindowManager::makeOpenGLContext(QQuickWindow *window)
{
if (!m_openGlContext) {
m_openGlContext.reset(new QOpenGLContext());
@@ -73,31 +72,31 @@ void DesignerWindowManager::makeOpenGLContext(QQuickWindow *window)
}
}
-void DesignerWindowManager::exposureChanged(QQuickWindow *)
+void QQuickDesignerWindowManager::exposureChanged(QQuickWindow *)
{
}
-QImage DesignerWindowManager::grab(QQuickWindow *)
+QImage QQuickDesignerWindowManager::grab(QQuickWindow *)
{
return QImage();
}
-void DesignerWindowManager::maybeUpdate(QQuickWindow *)
+void QQuickDesignerWindowManager::maybeUpdate(QQuickWindow *)
{
}
-QSGContext *DesignerWindowManager::sceneGraphContext() const
+QSGContext *QQuickDesignerWindowManager::sceneGraphContext() const
{
return m_sgContext.data();
}
-void DesignerWindowManager::createOpenGLContext(QQuickWindow *window)
+void QQuickDesignerWindowManager::createOpenGLContext(QQuickWindow *window)
{
window->create();
window->update();
}
-void DesignerWindowManager::update(QQuickWindow *window)
+void QQuickDesignerWindowManager::update(QQuickWindow *window)
{
makeOpenGLContext(window);
}
diff --git a/src/quick/designer/designerwindowmanager_p.h b/src/quick/designer/qquickdesignerwindowmanager_p.h
index e7a7314c20..6d98e25347 100644
--- a/src/quick/designer/designerwindowmanager_p.h
+++ b/src/quick/designer/qquickdesignerwindowmanager_p.h
@@ -60,11 +60,11 @@ class QSGRenderContext;
class QAnimationDriver;
class QOpenGLContext;
-class DesignerWindowManager : public QSGRenderLoop
+class QQuickDesignerWindowManager : public QSGRenderLoop
{
Q_OBJECT
public:
- DesignerWindowManager();
+ QQuickDesignerWindowManager();
void show(QQuickWindow *window);
void hide(QQuickWindow *window);
diff --git a/src/quick/doc/qtquick.qdocconf b/src/quick/doc/qtquick.qdocconf
index 7f43dc2c31..044c1696ff 100644
--- a/src/quick/doc/qtquick.qdocconf
+++ b/src/quick/doc/qtquick.qdocconf
@@ -4,7 +4,7 @@ project = QtQuick
description = Qt Quick Reference Documentation
version = $QT_VERSION
-examplesinstallpath = quick
+examplesinstallpath = qtdeclarative/quick
qhp.projects = QtQuick
diff --git a/src/quick/doc/src/concepts/effects/sprites.qdoc b/src/quick/doc/src/concepts/effects/sprites.qdoc
index edad89b1e5..62d9ea0811 100644
--- a/src/quick/doc/src/concepts/effects/sprites.qdoc
+++ b/src/quick/doc/src/concepts/effects/sprites.qdoc
@@ -26,13 +26,10 @@
****************************************************************************/
/*!
-\ingroup qtquick-images-sprites
\page qtquick-effects-sprites.html
\title Sprite Animations
\brief Sprite-based animations with flexible transitioning
-\generatelist{related}
-
\section1 Sprite Engine
The \l {Qt Quick} sprite engine is a stochastic state machine combined with the ability
@@ -167,9 +164,9 @@ Additionally, \l ImageParticle can use \l Sprite types to define sprites for eac
sprite engine per type. This works similarly to SpriteSequence, but it also has the parametrized variability provided
by the \l ImageParticle type.
-\section1 AnimatedSprite
+\section1 AnimatedSprite Type
-For use-cases which do not need to transition between animations, consider the \l AnimatedSprite type.
+For use-cases which do not need to transition between animations, consider the AnimatedSprite type.
This type displays sprite animations with the same input format, but only one at a time. It also provides more fine-grained
manual control, as there is no sprite engine managing the timing and transitions behind the scenes.
diff --git a/src/quick/doc/src/concepts/effects/transformations.qdoc b/src/quick/doc/src/concepts/effects/transformations.qdoc
index a5c7b9c208..cfe9d420fa 100644
--- a/src/quick/doc/src/concepts/effects/transformations.qdoc
+++ b/src/quick/doc/src/concepts/effects/transformations.qdoc
@@ -31,8 +31,6 @@
\title Qt Quick Transformation Types
\brief Types for applying transformations to visual types
-\generatelist{related}
-
Transformations are applied to child hierarchies and also will also transform
mouse and touch input so coordinates in event handlers behave as expected.
diff --git a/src/quick/doc/src/concepts/input/textinput.qdoc b/src/quick/doc/src/concepts/input/textinput.qdoc
index 3965c246da..41508caad6 100644
--- a/src/quick/doc/src/concepts/input/textinput.qdoc
+++ b/src/quick/doc/src/concepts/input/textinput.qdoc
@@ -26,7 +26,6 @@
****************************************************************************/
/*!
-\ingroup qtquick-text
\page qtquick-input-textinput.html
\title Qt Quick Text Input Handling and Validators
\brief Text input and validation
@@ -38,8 +37,6 @@ type will display formatted text onto the screen, the \l TextEdit type
will place a multiline line edit onto the screen, and the \l TextInput will
place a single editable line field onto the screen.
-\generatelist{related}
-
To learn more about their specific features and properties, visit their
respective documentation.
@@ -63,11 +60,11 @@ Note that QML parses JavaScript regular expressions, while Qt's
*/
/*!
+\page qtquick-text-validator.html
\ingroup qtquick-text-validator
\title Qt Quick Text Validators
\brief Types that validate text input
-The \l{qtquick-concepts-input-text.html}
-{Qt Quick Text Input Handling and Validators} page has information about
+The \l {Qt Quick Text Input Handling and Validators} page has information about
validating user text input.
*/
diff --git a/src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc b/src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc
index e03b3a9bf8..324fc9750f 100644
--- a/src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc
+++ b/src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc
@@ -57,7 +57,7 @@ To visualize data, bind the view's \c model property to a model and the
Views are containers for collections of items. They are feature-rich and can be
customizable to meet style or behavior requirements.
- \keyword qtquick-views
+ \target qtquick-views
A set of standard views are provided in the basic set of Qt Quick
graphical types:
@@ -124,7 +124,7 @@ To visualize data, bind the view's \c model property to a model and the
\snippet qml/listview-sections.qml section
\image listview-section.png
-\keyword qml-view-delegate
+\target qml-view-delegate
\section1 View Delegates
Views need a \e delegate to visually represent an item in a list. A view will
@@ -154,7 +154,7 @@ To visualize data, bind the view's \c model property to a model and the
\snippet qml/models/views-models-delegates.qml rectangle
-\keyword qml-data-models
+\target qml-data-models
\section1 Models
Data is provided to the delegate via named data roles which the delegate may
@@ -320,7 +320,7 @@ To visualize data, bind the view's \c model property to a model and the
}
\endqml
- \keyword qml-c++-models
+ \target qml-c++-models
\section2 C++ Data Models
Models can be defined in C++ and then made available to QML. This mechanism
@@ -371,13 +371,12 @@ or removed from a positioner.
Transitions for adding items apply to items that are created as part of a
positioner, as well as those that are reparented to become children of a
positioner.
+
Transitions for removing items apply to items within a positioner that are
deleted, as well as those that are removed from a positioner and given new
parents in a document.
-Additionally, changing the opacity of items to zero will cause them to
-disappear using the remove transition, and making the opacity non-zero will
-cause them to appear using the add transition.
-
-
+\note Changing the opacity of items to zero will not cause them to
+disappear from the positioner. They can be removed and re-added by changing
+the visible property.
*/
diff --git a/src/quick/doc/src/concepts/positioning/anchors.qdoc b/src/quick/doc/src/concepts/positioning/anchors.qdoc
index 71af38b587..259dcbe671 100644
--- a/src/quick/doc/src/concepts/positioning/anchors.qdoc
+++ b/src/quick/doc/src/concepts/positioning/anchors.qdoc
@@ -30,7 +30,7 @@
\title Positioning with Anchors
\brief placing items with anchor properties
-\target anchor-layout
+\keyword anchor-layout
In addition to the more traditional \l Grid, \l Row, and \l Column,
Qt Quick also provides a way to layout items using the concept of \e anchors.
Each item can be thought of as having a set of 7 invisible "anchor lines":
diff --git a/src/quick/doc/src/concepts/positioning/layouts.qdoc b/src/quick/doc/src/concepts/positioning/layouts.qdoc
index de47af6db8..47ed2563f8 100644
--- a/src/quick/doc/src/concepts/positioning/layouts.qdoc
+++ b/src/quick/doc/src/concepts/positioning/layouts.qdoc
@@ -26,7 +26,6 @@
****************************************************************************/
/*!
-\ingroup qtquick-positioners
\page qtquick-positioning-layouts.html
\title Item Positioners
@@ -47,7 +46,7 @@ and are well suited for resizable user interfaces.
A set of standard positioners are provided in the basic set of Qt Quick
graphical types:
-\generatelist{related}
+\annotatedlist qtquick-positioners
\section2 Column
diff --git a/src/quick/doc/src/concepts/statesanimations/animations.qdoc b/src/quick/doc/src/concepts/statesanimations/animations.qdoc
index 4e336afa36..1a2cff43f4 100644
--- a/src/quick/doc/src/concepts/statesanimations/animations.qdoc
+++ b/src/quick/doc/src/concepts/statesanimations/animations.qdoc
@@ -138,7 +138,7 @@ are also automatically applied to this property and do not need to specify
values.
-\keyword qml-transition-animations
+\target qml-transition-animations
\section2 Transitions during State Changes
\l{State}{Qt Quick States} are property configurations where a property may have different values to reflect different states. State changes introduce
@@ -210,7 +210,7 @@ The \l SequentialAnimation type is also useful for playing
\l{qml-transition-animations}{transition animations} because animations are
played in parallel inside transitions.
-\keyword qml-controlling-animations
+\target qml-controlling-animations
\section1 Controlling Animations
There are different methods to control animations.
@@ -222,7 +222,7 @@ essential properties and methods for animation types. Animation types have
\c{start()}, \c{stop()}, \c{resume()}, \c{pause()}, \c {restart()}, and
\c{complete()} -- all of these methods control the execution of animations.
-\keyword qml-easing-animation
+\target qml-easing-animation
\section2 Easing
Easing curves define how the animation will interpolate between the start value
@@ -295,27 +295,3 @@ Rectangle {
\endqml
*/
-
-/*!
-\ingroup qtquick-animation-properties
-\title Qt Quick Property Animation
-\brief Animate property changes
-
-\generatelist{related}
-*/
-
-/*!
-\ingroup qtquick-animation-control
-\title Qt Quick Animation Controls
-\brief Control animation sequences
-
-\generatelist{related}
-*/
-
-/*!
-\ingroup qtquick-animation-modifiers
-\title Qt Quick Animation Modifiers
-\brief Modify animation sequences
-
-\generatelist{related}
-*/
diff --git a/src/quick/doc/src/concepts/statesanimations/states.qdoc b/src/quick/doc/src/concepts/statesanimations/states.qdoc
index d107369e44..b48a051379 100644
--- a/src/quick/doc/src/concepts/statesanimations/states.qdoc
+++ b/src/quick/doc/src/concepts/statesanimations/states.qdoc
@@ -26,13 +26,12 @@
****************************************************************************/
/*!
-\ingroup qtquick-states
\page qtquick-statesanimations-states.html
\title Qt Quick States
\brief Creating and setting states
\section1 Related Types
-\generatelist{related}
+\annotatedlist qtquick-states
Many user interface designs are \e{state driven}; interfaces have configurations
that differ depending on the current state. For example, a traffic signal will
diff --git a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
index 287bdc892e..443d189f58 100644
--- a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
+++ b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
@@ -164,9 +164,9 @@ a rectangular geometry with a texture material.
\section1 Scene Graph and Rendering
The rendering of the scene graph happens internally in the
-QQuickWindow class, and there is no public API to access it. There are
+QQuickWindow class, and there is no public API to access it. There are,
however, a few places in the rendering pipeline where the user can
-attach application code. This can be to add custom scene graph
+attach application code. This can be used to add custom scene graph
content or render raw OpenGL content. The integration points are
defined by the render loop.
@@ -585,7 +585,7 @@ with multiple windows.
\section1 Batch Roots
- In addition to mergin compatible primitives into batches, the
+ In addition to merging compatible primitives into batches, the
default renderer also tries to minimize the amount of data that
needs to be sent to the GPU for every frame. The default renderer
identifies subtrees which belong together and tries to put these
diff --git a/src/quick/doc/src/examples.qdoc b/src/quick/doc/src/examples.qdoc
index dd21270673..e69c2f6551 100644
--- a/src/quick/doc/src/examples.qdoc
+++ b/src/quick/doc/src/examples.qdoc
@@ -32,7 +32,7 @@
\brief Building UIs with QML
\ingroup all-examples
\ingroup qtquick
-\target qtquick-samples
+\keyword qtquick-samples
Qt includes several examples to demonstrate a particular usage. The examples
run as applications or as non-GUI examples in Qt Creator. Qt tutorials show
diff --git a/src/quick/items/context2d/qquickcanvascontext_p.h b/src/quick/items/context2d/qquickcanvascontext_p.h
index b7a7f6db71..0010862044 100644
--- a/src/quick/items/context2d/qquickcanvascontext_p.h
+++ b/src/quick/items/context2d/qquickcanvascontext_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKCANVASCONTEXT_P_H
#define QQUICKCANVASCONTEXT_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuick/qquickitem.h>
#include <private/qv8engine_p.h>
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index f0a56867f1..9fb49f9c9e 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -46,7 +46,7 @@
#include <QtCore/QBuffer>
#include <QtCore/qdatetime.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4scopedvalue_p.h>
@@ -264,19 +264,6 @@ QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate()
The default render target is Canvas.Image and the default renderStrategy is
Canvas.Immediate.
- \section1 Tiled Canvas
- The Canvas item supports tiled rendering by setting \l canvasSize, \l tileSize
- and \l canvasWindow properties.
-
- Tiling allows efficient display of a very large virtual canvas via a smaller
- canvas window. The actual memory consumption is in relation to the canvas
- window size. The painting code can draw within the virtual canvas without
- handling coordinate system transformations.
-
- The tiles overlapping with the canvas window may be cached eliminating the
- need to redraw, which can lead to significantly improved performance in
- some situations.
-
\section1 Pixel Operations
All HTML5 2D context pixel operations are supported. In order to ensure
improved pixel reading/writing performance the \a Canvas.Image render
@@ -439,6 +426,8 @@ void QQuickCanvasItem::setCanvasSize(const QSizeF & size)
By default the tileSize is the same as the canvasSize.
+ \obsolete This feature is incomplete. For details, see QTBUG-33129.
+
\sa canvasSize, canvasWindow
*/
QSize QQuickCanvasItem::tileSize() const
@@ -472,6 +461,8 @@ void QQuickCanvasItem::setTileSize(const QSize & size)
can display different visible areas by changing the canvas windowSize
and/or position.
+ \obsolete This feature is incomplete. For details, see QTBUG-33129
+
\sa canvasSize, tileSize
*/
QRectF QQuickCanvasItem::canvasWindow() const
@@ -1008,7 +999,7 @@ void QQuickCanvasItem::loadImage(const QUrl& url)
if (!d->pixmaps.contains(fullPathUrl)) {
QQuickPixmap* pix = new QQuickPixmap();
QQmlRefPointer<QQuickCanvasPixmap> canvasPix;
- canvasPix.take(new QQuickCanvasPixmap(pix));
+ canvasPix.adopt(new QQuickCanvasPixmap(pix));
d->pixmaps.insert(fullPathUrl, canvasPix);
pix->load(qmlEngine(this)
diff --git a/src/quick/items/context2d/qquickcanvasitem_p.h b/src/quick/items/context2d/qquickcanvasitem_p.h
index bcd7072903..a32ce5389d 100644
--- a/src/quick/items/context2d/qquickcanvasitem_p.h
+++ b/src/quick/items/context2d/qquickcanvasitem_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKCANVASITEM_P_H
#define QQUICKCANVASITEM_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuick/qquickitem.h>
#include <private/qv8engine_p.h>
#include <QtCore/QThread>
@@ -68,8 +79,6 @@ private:
class QQuickCanvasItem : public QQuickItem
{
Q_OBJECT
- Q_ENUMS(RenderTarget)
- Q_ENUMS(RenderStrategy)
Q_PROPERTY(bool available READ isAvailable NOTIFY availableChanged)
Q_PROPERTY(QString contextType READ contextType WRITE setContextType NOTIFY contextTypeChanged)
@@ -85,12 +94,14 @@ public:
Image,
FramebufferObject
};
+ Q_ENUM(RenderTarget)
enum RenderStrategy {
Immediate,
Threaded,
Cooperative
};
+ Q_ENUM(RenderStrategy)
QQuickCanvasItem(QQuickItem *parent = 0);
~QQuickCanvasItem();
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index c71a354e0c..1c021e7dc6 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -53,7 +53,7 @@
#include <private/qv4object_p.h>
#include <private/qquickwindow_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4objectproto_p.h>
#include <private/qv4scopedvalue_p.h>
@@ -300,7 +300,7 @@ static QStringList qExtractFontFamiliesFromString(const QString &fontFamiliesStr
*/
static bool qSetFontFamilyFromTokens(QFont &font, const QStringList &fontFamilyTokens)
{
- foreach (QString fontFamilyToken, fontFamilyTokens) {
+ foreach (const QString &fontFamilyToken, fontFamilyTokens) {
QFontDatabase fontDatabase;
if (fontDatabase.hasFamily(fontFamilyToken)) {
font.setFamily(fontFamilyToken);
@@ -411,7 +411,7 @@ static QFont qt_font_from_string(const QString& fontString, const QFont &current
int usedTokens = NoTokens;
// Optional properties can be in any order, but font-size and font-family must be last.
- foreach (const QString token, tokens) {
+ foreach (const QString &token, tokens) {
if (token.compare(QLatin1String("normal")) == 0) {
if (!(usedTokens & FontStyle) || !(usedTokens & FontVariant) || !(usedTokens & FontWeight)) {
// Could be font-style, font-variant or font-weight.
@@ -475,17 +475,20 @@ namespace QV4 {
namespace Heap {
struct QQuickJSContext2D : Object {
- QQuickJSContext2D(QV4::ExecutionEngine *engine);
+ QQuickJSContext2D() {}
QQuickContext2D* context;
};
struct QQuickJSContext2DPrototype : Object {
- QQuickJSContext2DPrototype(ExecutionEngine *e)
- : Object(e) {}
+ QQuickJSContext2DPrototype() {}
};
struct QQuickContext2DStyle : Object {
- QQuickContext2DStyle(QV4::ExecutionEngine *e);
+ QQuickContext2DStyle()
+ {
+ patternRepeatX = false;
+ patternRepeatY = false;
+ }
QBrush brush;
bool patternRepeatX:1;
@@ -493,13 +496,13 @@ struct QQuickContext2DStyle : Object {
};
struct QQuickJSContext2DPixelData : Object {
- QQuickJSContext2DPixelData(QV4::ExecutionEngine *engine);
+ QQuickJSContext2DPixelData();
QImage image;
};
struct QQuickJSContext2DImageData : Object {
- QQuickJSContext2DImageData(QV4::ExecutionEngine *engine);
+ QQuickJSContext2DImageData();
QV4::Value pixelData;
};
@@ -552,11 +555,6 @@ struct QQuickJSContext2D : public QV4::Object
static QV4::ReturnedValue method_set_textBaseline(QV4::CallContext *ctx);
};
-QV4::Heap::QQuickJSContext2D::QQuickJSContext2D(QV4::ExecutionEngine *engine)
- : QV4::Heap::Object(engine)
-{
-}
-
DEFINE_OBJECT_VTABLE(QQuickJSContext2D);
@@ -567,7 +565,7 @@ public:
static QV4::Heap::QQuickJSContext2DPrototype *create(QV4::ExecutionEngine *engine)
{
QV4::Scope scope(engine);
- QV4::Scoped<QQuickJSContext2DPrototype> o(scope, engine->memoryManager->alloc<QQuickJSContext2DPrototype>(engine));
+ QV4::Scoped<QQuickJSContext2DPrototype> o(scope, engine->memoryManager->allocObject<QQuickJSContext2DPrototype>());
o->defineDefaultProperty(QStringLiteral("quadraticCurveTo"), method_quadraticCurveTo, 0);
o->defineDefaultProperty(QStringLiteral("restore"), method_restore, 0);
@@ -675,12 +673,7 @@ struct QQuickContext2DStyle : public QV4::Object
static QV4::ReturnedValue gradient_proto_addColorStop(QV4::CallContext *ctx);
};
-QV4::Heap::QQuickContext2DStyle::QQuickContext2DStyle(QV4::ExecutionEngine *e)
- : QV4::Heap::Object(e)
-{
- patternRepeatX = false;
- patternRepeatY = false;
-}
+
DEFINE_OBJECT_VTABLE(QQuickContext2DStyle);
@@ -884,16 +877,15 @@ struct QQuickJSContext2DPixelData : public QV4::Object
V4_OBJECT2(QQuickJSContext2DPixelData, QV4::Object)
V4_NEEDS_DESTROY
- static QV4::ReturnedValue getIndexed(QV4::Managed *m, uint index, bool *hasProperty);
+ static QV4::ReturnedValue getIndexed(const QV4::Managed *m, uint index, bool *hasProperty);
static void putIndexed(QV4::Managed *m, uint index, const QV4::Value &value);
static QV4::ReturnedValue proto_get_length(QV4::CallContext *ctx);
};
-QV4::Heap::QQuickJSContext2DPixelData::QQuickJSContext2DPixelData(QV4::ExecutionEngine *engine)
- : QV4::Heap::Object(engine)
+QV4::Heap::QQuickJSContext2DPixelData::QQuickJSContext2DPixelData()
{
- QV4::Scope scope(engine);
+ QV4::Scope scope(internalClass->engine);
QV4::ScopedObject o(scope, this);
o->setArrayType(QV4::Heap::ArrayData::Custom);
}
@@ -914,12 +906,11 @@ struct QQuickJSContext2DImageData : public QV4::Object
}
};
-QV4::Heap::QQuickJSContext2DImageData::QQuickJSContext2DImageData(QV4::ExecutionEngine *engine)
- : QV4::Heap::Object(engine)
+QV4::Heap::QQuickJSContext2DImageData::QQuickJSContext2DImageData()
{
pixelData = QV4::Primitive::undefinedValue();
- QV4::Scope scope(engine);
+ QV4::Scope scope(internalClass->engine);
QV4::ScopedObject o(scope, this);
o->defineAccessorProperty(QStringLiteral("width"), ::QQuickJSContext2DImageData::method_get_width, 0);
@@ -933,7 +924,7 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionE
{
QV4::Scope scope(v4);
QQuickContext2DEngineData *ed = engineData(scope.engine);
- QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, scope.engine->memoryManager->alloc<QQuickJSContext2DPixelData>(v4));
+ QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, scope.engine->memoryManager->allocObject<QQuickJSContext2DPixelData>());
QV4::ScopedObject p(scope, ed->pixelArrayProto.value());
pixelData->setPrototype(p);
@@ -945,7 +936,7 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionE
pixelData->d()->image = image.format() == QImage::Format_ARGB32 ? image : image.convertToFormat(QImage::Format_ARGB32);
}
- QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, scope.engine->memoryManager->alloc<QQuickJSContext2DImageData>(v4));
+ QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, scope.engine->memoryManager->allocObject<QQuickJSContext2DImageData>());
imageData->d()->pixelData = pixelData.asReturnedValue();
return imageData.asReturnedValue();
}
@@ -1379,7 +1370,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::CallContext *ctx
QV4::ScopedValue value(scope, ctx->argument(0));
- if (value->asObject()) {
+ if (value->as<Object>()) {
QColor color = scope.engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>();
if (color.isValid()) {
r->d()->context->state.fillStyle = color;
@@ -1488,7 +1479,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::CallContext *c
QV4::ScopedValue value(scope, ctx->argument(0));
- if (value->asObject()) {
+ if (value->as<Object>()) {
QColor color = scope.engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>();
if (color.isValid()) {
r->d()->context->state.fillStyle = color;
@@ -1553,7 +1544,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4::
}
QQuickContext2DEngineData *ed = engineData(scope.engine);
- QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->alloc<QQuickContext2DStyle>(scope.engine));
+ QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>());
QV4::ScopedObject p(scope, ed->gradientProto.value());
gradient->setPrototype(p);
gradient->d()->brush = QLinearGradient(x0, y0, x1, y1);
@@ -1604,7 +1595,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4::
QQuickContext2DEngineData *ed = engineData(scope.engine);
- QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->alloc<QQuickContext2DStyle>(scope.engine));
+ QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>());
QV4::ScopedObject p(scope, ed->gradientProto.value());
gradient->setPrototype(p);
gradient->d()->brush = QRadialGradient(QPointF(x1, y1), r0+r1, QPointF(x0, y0));
@@ -1647,7 +1638,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4:
QQuickContext2DEngineData *ed = engineData(scope.engine);
- QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->alloc<QQuickContext2DStyle>(scope.engine));
+ QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>());
QV4::ScopedObject p(scope, ed->gradientProto.value());
gradient->setPrototype(p);
gradient->d()->brush = QConicalGradient(x, y, angle);
@@ -1706,7 +1697,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::CallCon
CHECK_CONTEXT(r)
if (ctx->argc() >= 2) {
- QV4::Scoped<QQuickContext2DStyle> pattern(scope, scope.engine->memoryManager->alloc<QQuickContext2DStyle>(scope.engine));
+ QV4::Scoped<QQuickContext2DStyle> pattern(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>());
QColor color = scope.engine->toVariant(ctx->args()[0], qMetaTypeId<QColor>()).value<QColor>();
if (color.isValid()) {
@@ -1719,7 +1710,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::CallCon
} else {
QImage patternTexture;
- if (QV4::Object *o = ctx->args()[0].asObject()) {
+ if (const QV4::Object *o = ctx->args()[0].as<Object>()) {
QV4::ScopedString s(scope, scope.engine->newString(QStringLiteral("data")));
QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, o->get(s));
if (!!pixelData) {
@@ -2912,7 +2903,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext
} else if (QQuickCanvasItem *canvas = qobject_cast<QQuickCanvasItem*>(qobjectWrapper->object())) {
QImage img = canvas->toImage();
if (!img.isNull())
- pixmap.take(new QQuickCanvasPixmap(img));
+ pixmap.adopt(new QQuickCanvasPixmap(img));
} else {
V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
}
@@ -2921,7 +2912,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext
if (!!imageData) {
QV4::Scoped<QQuickJSContext2DPixelData> pix(scope, imageData->d()->pixelData.as<QQuickJSContext2DPixelData>());
if (pix && !pix->d()->image.isNull()) {
- pixmap.take(new QQuickCanvasPixmap(pix->d()->image));
+ pixmap.adopt(new QQuickCanvasPixmap(pix->d()->image));
} else {
V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
}
@@ -3089,12 +3080,12 @@ QV4::ReturnedValue QQuickJSContext2DPixelData::proto_get_length(QV4::CallContext
return QV4::Encode(r->d()->image.width() * r->d()->image.height() * 4);
}
-QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(QV4::Managed *m, uint index, bool *hasProperty)
+QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(const QV4::Managed *m, uint index, bool *hasProperty)
{
Q_ASSERT(m->as<QQuickJSContext2DPixelData>());
- QV4::ExecutionEngine *v4 = static_cast<QQuickJSContext2DPixelData *>(m)->engine();
+ QV4::ExecutionEngine *v4 = static_cast<const QQuickJSContext2DPixelData *>(m)->engine();
QV4::Scope scope(v4);
- QV4::Scoped<QQuickJSContext2DPixelData> r(scope, static_cast<QQuickJSContext2DPixelData *>(m));
+ QV4::Scoped<QQuickJSContext2DPixelData> r(scope, static_cast<const QQuickJSContext2DPixelData *>(m));
if (index < static_cast<quint32>(r->d()->image.width() * r->d()->image.height() * 4)) {
if (hasProperty)
@@ -3357,7 +3348,7 @@ QV4::ReturnedValue QQuickContext2DStyle::gradient_proto_addColorStop(QV4::CallCo
qreal pos = ctx->args()[0].toNumber();
QColor color;
- if (ctx->args()[1].asObject()) {
+ if (ctx->args()[1].as<Object>()) {
color = scope.engine->toVariant(ctx->args()[1], qMetaTypeId<QColor>()).value<QColor>();
} else {
color = qt_color_from_string(ctx->args()[1]);
@@ -4235,7 +4226,7 @@ QQuickContext2DEngineData::QQuickContext2DEngineData(QV4::ExecutionEngine *v4)
gradientProto = proto;
proto = scope.engine->newObject();
- proto->defineAccessorProperty(scope.engine->id_length, QQuickJSContext2DPixelData::proto_get_length, 0);
+ proto->defineAccessorProperty(scope.engine->id_length(), QQuickJSContext2DPixelData::proto_get_length, 0);
pixelArrayProto = proto;
}
@@ -4324,7 +4315,7 @@ void QQuickContext2D::setV4Engine(QV4::ExecutionEngine *engine)
QQuickContext2DEngineData *ed = engineData(engine);
QV4::Scope scope(engine);
- QV4::Scoped<QQuickJSContext2D> wrapper(scope, engine->memoryManager->alloc<QQuickJSContext2D>(engine));
+ QV4::Scoped<QQuickJSContext2D> wrapper(scope, engine->memoryManager->allocObject<QQuickJSContext2D>());
QV4::ScopedObject p(scope, ed->contextPrototype.value());
wrapper->setPrototype(p);
wrapper->d()->context = this;
diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h
index 67d3a2e4fb..94762fe7a2 100644
--- a/src/quick/items/context2d/qquickcontext2d_p.h
+++ b/src/quick/items/context2d/qquickcontext2d_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKCONTEXT2D_P_H
#define QQUICKCONTEXT2D_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuick/qtquickglobal.h>
#include <QtQml/qqml.h>
#include <QtQml/qqmlcomponent.h>
@@ -48,7 +59,7 @@
#include <private/qv8engine_p.h>
#include <QtCore/QWaitCondition>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
//#define QQUICKCONTEXT2D_DEBUG //enable this for just DEBUG purpose!
diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
index 54bf209c79..48cf21ad71 100644
--- a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
+++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKCONTEXT2DCOMMANDBUFFER_P_H
#define QQUICKCONTEXT2DCOMMANDBUFFER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qmutex.h>
#include "qquickcontext2d_p.h"
diff --git a/src/quick/items/context2d/qquickcontext2dtexture_p.h b/src/quick/items/context2d/qquickcontext2dtexture_p.h
index 88d7b6858f..50ce95e19b 100644
--- a/src/quick/items/context2d/qquickcontext2dtexture_p.h
+++ b/src/quick/items/context2d/qquickcontext2dtexture_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKCONTEXT2DTEXTURE_P_H
#define QQUICKCONTEXT2DTEXTURE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuick/qsgtexture.h>
#include "qquickcanvasitem_p.h"
#include "qquickcontext2d_p.h"
diff --git a/src/quick/items/context2d/qquickcontext2dtile_p.h b/src/quick/items/context2d/qquickcontext2dtile_p.h
index d923313a28..781261c8d2 100644
--- a/src/quick/items/context2d/qquickcontext2dtile_p.h
+++ b/src/quick/items/context2d/qquickcontext2dtile_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKCONTEXT2DTILE_P_H
#define QQUICKCONTEXT2DTILE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickcontext2d_p.h"
#include <QOpenGLFramebufferObject>
diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri
index 0b98782566..ab966b6ccc 100644
--- a/src/quick/items/items.pri
+++ b/src/quick/items/items.pri
@@ -23,6 +23,7 @@ HEADERS += \
$$PWD/qquicktextcontrol_p.h \
$$PWD/qquicktextcontrol_p_p.h \
$$PWD/qquicktextdocument.h \
+ $$PWD/qquicktextdocument_p.h \
$$PWD/qquicktextedit_p.h \
$$PWD/qquicktextedit_p_p.h \
$$PWD/qquicktextutil_p.h \
diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h
index be78e74b19..617b5aa886 100644
--- a/src/quick/items/qquickaccessibleattached_p.h
+++ b/src/quick/items/qquickaccessibleattached_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKACCESSIBLEATTACHED_H
#define QQUICKACCESSIBLEATTACHED_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuick/qquickitem.h>
#include <QtCore/qobject.h>
diff --git a/src/quick/items/qquickanchors.cpp b/src/quick/items/qquickanchors.cpp
index f559f166bf..606d4c45da 100644
--- a/src/quick/items/qquickanchors.cpp
+++ b/src/quick/items/qquickanchors.cpp
@@ -414,13 +414,27 @@ void QQuickAnchorsPrivate::updateMe()
void QQuickAnchorsPrivate::updateOnComplete()
{
//optimization to only set initial dependencies once, at completion time
- QSet<QQuickItem *> dependencies;
- dependencies << fill << centerIn
- << left.item << right.item << hCenter.item
- << top.item << bottom.item << vCenter.item << baseline.item;
-
- foreach (QQuickItem *dependency, dependencies)
- addDepend(dependency);
+ QQuickItem *dependencies[9];
+ dependencies[0] = fill;
+ dependencies[1] = centerIn;
+ dependencies[2] = left.item;
+ dependencies[3] = right.item;
+ dependencies[4] = hCenter.item;
+ dependencies[5] = top.item;
+ dependencies[6] = bottom.item;
+ dependencies[7] = vCenter.item;
+ dependencies[8] = baseline.item;
+
+ std::sort(dependencies, dependencies + 9);
+
+ QQuickItem *lastDependency = 0;
+ for (int i = 0; i < 9; ++i) {
+ QQuickItem *dependency = dependencies[i];
+ if (lastDependency != dependency) {
+ addDepend(dependency);
+ lastDependency = dependency;
+ }
+ }
update();
}
diff --git a/src/quick/items/qquickanchors_p.h b/src/quick/items/qquickanchors_p.h
index a2328162e5..4157e4bf6d 100644
--- a/src/quick/items/qquickanchors_p.h
+++ b/src/quick/items/qquickanchors_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKANCHORS_P_H
#define QQUICKANCHORS_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include <QtCore/QObject>
diff --git a/src/quick/items/qquickanimatedimage_p.h b/src/quick/items/qquickanimatedimage_p.h
index 409933817f..42f2d4cb64 100644
--- a/src/quick/items/qquickanimatedimage_p.h
+++ b/src/quick/items/qquickanimatedimage_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKANIMATEDIMAGE_P_H
#define QQUICKANIMATEDIMAGE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickimage_p.h"
#ifndef QT_NO_MOVIE
diff --git a/src/quick/items/qquickanimatedsprite_p.h b/src/quick/items/qquickanimatedsprite_p.h
index e535f1b077..87d489a60a 100644
--- a/src/quick/items/qquickanimatedsprite_p.h
+++ b/src/quick/items/qquickanimatedsprite_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKANIMATEDSPRITE_P_H
#define QQUICKANIMATEDSPRITE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuick/QQuickItem>
#include <private/qquicksprite_p.h>
#include <QTime>
@@ -70,12 +81,12 @@ class Q_AUTOTEST_EXPORT QQuickAnimatedSprite : public QQuickItem
Q_PROPERTY(bool paused READ paused WRITE setPaused NOTIFY pausedChanged)
Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY currentFrameChanged)
- Q_ENUMS(LoopParameters)
public:
explicit QQuickAnimatedSprite(QQuickItem *parent = 0);
enum LoopParameters {
Infinite = -1
};
+ Q_ENUM(LoopParameters)
bool running() const
{
diff --git a/src/quick/items/qquickborderimage_p.h b/src/quick/items/qquickborderimage_p.h
index f2a172fad3..02e01dedd5 100644
--- a/src/quick/items/qquickborderimage_p.h
+++ b/src/quick/items/qquickborderimage_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKBORDERIMAGE_P_H
#define QQUICKBORDERIMAGE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickimagebase_p.h"
QT_BEGIN_NAMESPACE
@@ -44,7 +55,6 @@ class QQuickBorderImagePrivate;
class Q_AUTOTEST_EXPORT QQuickBorderImage : public QQuickImageBase
{
Q_OBJECT
- Q_ENUMS(TileMode)
Q_PROPERTY(QQuickScaleGrid *border READ border CONSTANT)
Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY horizontalTileModeChanged)
@@ -59,6 +69,7 @@ public:
QQuickScaleGrid *border();
enum TileMode { Stretch = Qt::StretchTile, Repeat = Qt::RepeatTile, Round = Qt::RoundTile };
+ Q_ENUM(TileMode)
TileMode horizontalTileMode() const;
void setHorizontalTileMode(TileMode);
diff --git a/src/quick/items/qquickclipnode_p.h b/src/quick/items/qquickclipnode_p.h
index 2e7fa1f495..70dbf149b2 100644
--- a/src/quick/items/qquickclipnode_p.h
+++ b/src/quick/items/qquickclipnode_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKCLIPNODE_P_H
#define QQUICKCLIPNODE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qtquickglobal_p.h>
#include <QtQuick/qsgnode.h>
diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp
index 2612b855bd..279f5e5299 100644
--- a/src/quick/items/qquickdrag.cpp
+++ b/src/quick/items/qquickdrag.cpp
@@ -135,6 +135,7 @@ public:
\l {supportedActions}{drop action} chosen by the recipient of the event,
otherwise it will return Qt.IgnoreAction.
+ \sa {Qt Quick Examples - Drag and Drop}, {Qt Quick Examples - externaldraganddrop}
*/
void QQuickDragAttachedPrivate::itemGeometryChanged(QQuickItem *, const QRectF &newGeometry, const QRectF &oldGeometry)
diff --git a/src/quick/items/qquickdrag_p.h b/src/quick/items/qquickdrag_p.h
index 4bd4cfc6fd..5599831b6f 100644
--- a/src/quick/items/qquickdrag_p.h
+++ b/src/quick/items/qquickdrag_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKDRAG_P_H
#define QQUICKDRAG_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuick/qquickitem.h>
#include <private/qv8engine_p.h>
@@ -140,7 +151,6 @@ class Q_AUTOTEST_EXPORT QQuickDrag : public QObject
{
Q_OBJECT
- Q_ENUMS(Axis DragType)
Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged RESET resetTarget)
Q_PROPERTY(Axis axis READ axis WRITE setAxis NOTIFY axisChanged)
Q_PROPERTY(qreal minimumX READ xmin WRITE setXmin NOTIFY minimumXChanged)
@@ -160,12 +170,14 @@ public:
~QQuickDrag();
enum DragType { None, Automatic, Internal };
+ Q_ENUM(DragType)
QQuickItem *target() const;
void setTarget(QQuickItem *target);
void resetTarget();
enum Axis { XAxis=0x01, YAxis=0x02, XAndYAxis=0x03, XandYAxis=XAndYAxis };
+ Q_ENUM(Axis)
Axis axis() const;
void setAxis(Axis);
diff --git a/src/quick/items/qquickdroparea.cpp b/src/quick/items/qquickdroparea.cpp
index e46d546a16..e1b33b4660 100644
--- a/src/quick/items/qquickdroparea.cpp
+++ b/src/quick/items/qquickdroparea.cpp
@@ -34,10 +34,8 @@
#include "qquickdroparea_p.h"
#include "qquickdrag_p.h"
#include "qquickitem_p.h"
-#include "qquickwindow.h"
#include <private/qv4arraybuffer_p.h>
-#include <private/qqmlengine_p.h>
#ifndef QT_NO_DRAGANDDROP
@@ -102,6 +100,8 @@ QQuickDropAreaPrivate::~QQuickDropAreaPrivate()
The \l drag.source property is communicated to the source of a drag event as
the recipient of a drop on the drag target.
+
+ \sa {Qt Quick Examples - Drag and Drop}, {Qt Quick Examples - externaldraganddrop}
*/
QQuickDropArea::QQuickDropArea(QQuickItem *parent)
diff --git a/src/quick/items/qquickdroparea_p.h b/src/quick/items/qquickdroparea_p.h
index 3223f4203b..a1a58af7fc 100644
--- a/src/quick/items/qquickdroparea_p.h
+++ b/src/quick/items/qquickdroparea_p.h
@@ -34,10 +34,18 @@
#ifndef QQUICKDROPAREA_P_H
#define QQUICKDROPAREA_P_H
-#include "qquickitem.h"
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
-#include <private/qqmlguard_p.h>
-#include <private/qv8engine_p.h>
+#include "qquickitem.h"
#include <QtGui/qevent.h>
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp
index 520b9d46bb..88deefbd9a 100644
--- a/src/quick/items/qquickevents.cpp
+++ b/src/quick/items/qquickevents.cpp
@@ -352,10 +352,7 @@ Item {
MouseArea {
onWheel: {
if (wheel.modifiers & Qt.ControlModifier) {
- if (wheel.angleDelta.y > 0)
- zoomIn();
- else
- zoomOut();
+ adjustZoom(wheel.angleDelta.y / 120);
}
}
}
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index 19fb66c19c..43405db40d 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -218,7 +218,7 @@ QQuickFlickablePrivate::QQuickFlickablePrivate()
, hMoved(false), vMoved(false)
, stealMouse(false), pressed(false)
, scrollingPhase(false), interactive(true), calcVelocity(false)
- , pixelAligned(false), replayingPressEvent(false)
+ , pixelAligned(false)
, lastPosTime(-1)
, lastPressTime(0)
, deceleration(QML_FLICK_DEFAULTDECELERATION)
@@ -344,10 +344,12 @@ bool QQuickFlickablePrivate::flick(AxisData &data, qreal minExtent, qreal maxExt
accel = v2 / (2.0f * qAbs(dist));
resetTimeline(data);
- if (boundsBehavior & QQuickFlickable::OvershootBounds)
- timeline.accel(data.move, v, accel);
- else
- timeline.accel(data.move, v, accel, maxDistance);
+ if (!data.inOvershoot) {
+ if (boundsBehavior & QQuickFlickable::OvershootBounds)
+ timeline.accel(data.move, v, accel);
+ else
+ timeline.accel(data.move, v, accel, maxDistance);
+ }
timeline.callback(QQuickTimeLineCallback(&data.move, fixupCallback, this));
if (&data == &hData)
@@ -433,12 +435,12 @@ void QQuickFlickablePrivate::clearTimeline()
void QQuickFlickablePrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
{
- if (data.move.value() > minExtent || maxExtent > minExtent) {
+ if (data.move.value() >= minExtent || maxExtent > minExtent) {
resetTimeline(data);
if (data.move.value() != minExtent) {
adjustContentPos(data, minExtent);
}
- } else if (data.move.value() < maxExtent) {
+ } else if (data.move.value() <= maxExtent) {
resetTimeline(data);
adjustContentPos(data, maxExtent);
} else if (-qRound(-data.move.value()) != data.move.value()) {
@@ -619,7 +621,7 @@ is finished.
\qmlsignal QtQuick::Flickable::movementStarted()
This signal is emitted when the view begins moving due to user
- interaction.
+ interaction or a generated flick().
The corresponding handler is \c onMovementStarted.
*/
@@ -628,9 +630,9 @@ is finished.
\qmlsignal QtQuick::Flickable::movementEnded()
This signal is emitted when the view stops moving due to user
- interaction. If a flick was generated, this signal will
+ interaction or a generated flick(). If a flick was active, this signal will
be emitted once the flick stops. If a flick was not
- generated, this signal will be emitted when the
+ active, this signal will be emitted when the
user stops dragging - i.e. a mouse or touch release.
The corresponding handler is \c onMovementEnded.
@@ -1347,7 +1349,7 @@ void QQuickFlickable::mouseReleaseEvent(QMouseEvent *event)
if (window() && window()->mouseGrabberItem()) {
QPointF localPos = window()->mouseGrabberItem()->mapFromScene(event->windowPos());
QScopedPointer<QMouseEvent> mouseEvent(QQuickWindowPrivate::cloneMouseEvent(event, &localPos));
- window()->sendEvent(window()->mouseGrabberItem(), mouseEvent.data());
+ QCoreApplication::sendEvent(window(), mouseEvent.data());
}
// And the event has been consumed
@@ -1451,6 +1453,7 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event)
d->lastPosTime = currentTimestamp;
d->accumulatedWheelPixelDelta += QVector2D(event->pixelDelta());
d->drag(currentTimestamp, event->type(), event->posF(), d->accumulatedWheelPixelDelta, true, !d->scrollingPhase, true, velocity);
+ event->accept();
}
if (!event->isAccepted())
@@ -1639,10 +1642,8 @@ void QQuickFlickable::geometryChanged(const QRectF &newGeometry,
bool changed = false;
if (newGeometry.width() != oldGeometry.width()) {
changed = true; // we must update visualArea.widthRatio
- if (d->hData.viewSize < 0) {
+ if (d->hData.viewSize < 0)
d->contentItem->setWidth(width());
- emit contentWidthChanged();
- }
// Make sure that we're entirely in view.
if (!d->pressed && !d->hData.moving && !d->vData.moving) {
d->fixupMode = QQuickFlickablePrivate::Immediate;
@@ -1651,10 +1652,8 @@ void QQuickFlickable::geometryChanged(const QRectF &newGeometry,
}
if (newGeometry.height() != oldGeometry.height()) {
changed = true; // we must update visualArea.heightRatio
- if (d->vData.viewSize < 0) {
+ if (d->vData.viewSize < 0)
d->contentItem->setHeight(height());
- emit contentHeightChanged();
- }
// Make sure that we're entirely in view.
if (!d->pressed && !d->hData.moving && !d->vData.moving) {
d->fixupMode = QQuickFlickablePrivate::Immediate;
@@ -1670,6 +1669,9 @@ void QQuickFlickable::geometryChanged(const QRectF &newGeometry,
\qmlmethod QtQuick::Flickable::flick(qreal xVelocity, qreal yVelocity)
Flicks the content with \a xVelocity horizontally and \a yVelocity vertically in pixels/sec.
+
+ Calling this method will update the corresponding moving and flicking properties and signals,
+ just like a real flick.
*/
void QQuickFlickable::flick(qreal xVelocity, qreal yVelocity)
@@ -1679,8 +1681,15 @@ void QQuickFlickable::flick(qreal xVelocity, qreal yVelocity)
d->vData.reset();
d->hData.velocity = xVelocity;
d->vData.velocity = yVelocity;
+
bool flickedX = d->flickX(xVelocity);
bool flickedY = d->flickY(yVelocity);
+
+ if (flickedX)
+ d->hMoved = true;
+ if (flickedY)
+ d->vMoved = true;
+ movementStarting();
d->flickingStarted(flickedX, flickedY);
}
@@ -2195,10 +2204,6 @@ bool QQuickFlickable::sendMouseEvent(QQuickItem *item, QMouseEvent *event)
d->handleMouseMoveEvent(mouseEvent.data());
break;
case QEvent::MouseButtonPress:
- // Don't process a replayed event during replay
- if (d->replayingPressEvent)
- return false;
-
d->handleMousePressEvent(mouseEvent.data());
d->captureDelayedPress(item, event);
stealThisEvent = d->stealMouse; // Update stealThisEvent in case changed by function call above
diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h
index 3c3cd362dd..ac072f0e50 100644
--- a/src/quick/items/qquickflickable_p.h
+++ b/src/quick/items/qquickflickable_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKFLICKABLE_P_H
#define QQUICKFLICKABLE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickitem.h"
#include <private/qtquickglobal_p.h>
@@ -93,7 +104,6 @@ class Q_QUICK_PRIVATE_EXPORT QQuickFlickable : public QQuickItem
Q_PROPERTY(QQmlListProperty<QQuickItem> flickableChildren READ flickableChildren)
Q_CLASSINFO("DefaultProperty", "flickableData")
- Q_ENUMS(FlickableDirection)
Q_FLAGS(BoundsBehavior)
public:
@@ -177,6 +187,7 @@ public:
QQuickItem *contentItem();
enum FlickableDirection { AutoFlickDirection=0x00, HorizontalFlick=0x01, VerticalFlick=0x02, HorizontalAndVerticalFlick=0x03 };
+ Q_ENUM(FlickableDirection)
FlickableDirection flickableDirection() const;
void setFlickableDirection(FlickableDirection);
diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h
index 65bb3e802d..9d75533c8a 100644
--- a/src/quick/items/qquickflickable_p_p.h
+++ b/src/quick/items/qquickflickable_p_p.h
@@ -211,7 +211,6 @@ public:
bool interactive : 1;
bool calcVelocity : 1;
bool pixelAligned : 1;
- bool replayingPressEvent : 1;
QElapsedTimer timer;
qint64 lastPosTime;
qint64 lastPressTime;
diff --git a/src/quick/items/qquickflickablebehavior_p.h b/src/quick/items/qquickflickablebehavior_p.h
index a79297894c..69fca4d0fb 100644
--- a/src/quick/items/qquickflickablebehavior_p.h
+++ b/src/quick/items/qquickflickablebehavior_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKFLICKABLEBEHAVIOR_H
#define QQUICKFLICKABLEBEHAVIOR_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
/* ### Platform specific flickable mechanics are defined either here, or in
mkspec files. Long-term (QtQuick 3) Flickable needs to allow such
mechanic details to be controlled via QML so that platforms can easily
diff --git a/src/quick/items/qquickflipable.cpp b/src/quick/items/qquickflipable.cpp
index 4fd146f0e4..b0bacf0eb6 100644
--- a/src/quick/items/qquickflipable.cpp
+++ b/src/quick/items/qquickflipable.cpp
@@ -152,8 +152,10 @@ void QQuickFlipable::setFront(QQuickItem *front)
}
d->front = front;
d->front->setParentItem(this);
- if (Back == d->current)
+ if (Back == d->current) {
d->front->setOpacity(0.);
+ d->front->setEnabled(false);
+ }
emit frontChanged();
}
@@ -178,8 +180,11 @@ void QQuickFlipable::setBack(QQuickItem *back)
d->backTransform = new QQuickLocalTransform(d->back);
d->backTransform->prependToItem(d->back);
- if (Front == d->current)
+ if (Front == d->current) {
d->back->setOpacity(0.);
+ d->back->setEnabled(false);
+ }
+
connect(back, SIGNAL(widthChanged()),
this, SLOT(retransformBack()));
connect(back, SIGNAL(heightChanged()),
@@ -271,10 +276,14 @@ void QQuickFlipablePrivate::updateSide()
current = newSide;
if (current == QQuickFlipable::Back && back)
setBackTransform();
- if (front)
+ if (front) {
front->setOpacity((current==QQuickFlipable::Front)?1.:0.);
- if (back)
+ front->setEnabled((current==QQuickFlipable::Front)?true:false);
+ }
+ if (back) {
back->setOpacity((current==QQuickFlipable::Back)?1.:0.);
+ back->setEnabled((current==QQuickFlipable::Back)?true:false);
+ }
emit q->sideChanged();
}
}
diff --git a/src/quick/items/qquickflipable_p.h b/src/quick/items/qquickflipable_p.h
index bd2efe0676..93610031f6 100644
--- a/src/quick/items/qquickflipable_p.h
+++ b/src/quick/items/qquickflipable_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKFLIPABLE_P_H
#define QQUICKFLIPABLE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickitem.h"
#include <QtGui/qtransform.h>
@@ -47,7 +58,6 @@ class Q_AUTOTEST_EXPORT QQuickFlipable : public QQuickItem
{
Q_OBJECT
- Q_ENUMS(Side)
Q_PROPERTY(QQuickItem *front READ front WRITE setFront NOTIFY frontChanged)
Q_PROPERTY(QQuickItem *back READ back WRITE setBack NOTIFY backChanged)
Q_PROPERTY(Side side READ side NOTIFY sideChanged)
@@ -64,6 +74,7 @@ public:
void setBack(QQuickItem *);
enum Side { Front, Back };
+ Q_ENUM(Side)
Side side() const;
Q_SIGNALS:
diff --git a/src/quick/items/qquickfocusscope_p.h b/src/quick/items/qquickfocusscope_p.h
index b0e92cb312..eb42cf83b5 100644
--- a/src/quick/items/qquickfocusscope_p.h
+++ b/src/quick/items/qquickfocusscope_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKFOCUSSCOPE_P_H
#define QQUICKFOCUSSCOPE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickitem.h"
QT_BEGIN_NAMESPACE
diff --git a/src/quick/items/qquickframebufferobject.cpp b/src/quick/items/qquickframebufferobject.cpp
index 4638bbbdf3..5ce3ae57f7 100644
--- a/src/quick/items/qquickframebufferobject.cpp
+++ b/src/quick/items/qquickframebufferobject.cpp
@@ -47,11 +47,13 @@ class QQuickFramebufferObjectPrivate : public QQuickItemPrivate
public:
QQuickFramebufferObjectPrivate()
: followsItemSize(true)
+ , mirrorVertically(false)
, node(0)
{
}
bool followsItemSize;
+ bool mirrorVertically;
mutable QSGFramebufferObjectNode *node;
};
@@ -138,6 +140,34 @@ bool QQuickFramebufferObject::textureFollowsItemSize() const
}
/*!
+ * \property QQuickFramebufferObject::mirrorVertically
+ *
+ * This property controls if the size of the FBO's contents should be mirrored
+ * vertically when drawing. This allows easy integration of third-party
+ * rendering code that does not follow the standard expectations.
+ *
+ * The default value is \c {false}.
+ *
+ * \since 5.6
+ */
+
+void QQuickFramebufferObject::setMirrorVertically(bool enable)
+{
+ Q_D(QQuickFramebufferObject);
+ if (d->mirrorVertically == enable)
+ return;
+ d->mirrorVertically = enable;
+ emit mirrorVerticallyChanged(d->mirrorVertically);
+ update();
+}
+
+bool QQuickFramebufferObject::mirrorVertically() const
+{
+ Q_D(const QQuickFramebufferObject);
+ return d->mirrorVertically;
+}
+
+/*!
* \internal
*/
void QQuickFramebufferObject::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
@@ -290,6 +320,7 @@ QSGNode *QQuickFramebufferObject::updatePaintNode(QSGNode *node, UpdatePaintNode
QQuickWindow::TextureHasAlphaChannel));
}
+ n->setTextureCoordinatesTransform(d->mirrorVertically ? QSGSimpleTextureNode::MirrorVertically : QSGSimpleTextureNode::NoTransform);
n->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
n->setRect(0, 0, width(), height());
diff --git a/src/quick/items/qquickframebufferobject.h b/src/quick/items/qquickframebufferobject.h
index 4a0248c082..7fb7262222 100644
--- a/src/quick/items/qquickframebufferobject.h
+++ b/src/quick/items/qquickframebufferobject.h
@@ -49,6 +49,7 @@ class Q_QUICK_EXPORT QQuickFramebufferObject : public QQuickItem
Q_DECLARE_PRIVATE(QQuickFramebufferObject)
Q_PROPERTY(bool textureFollowsItemSize READ textureFollowsItemSize WRITE setTextureFollowsItemSize NOTIFY textureFollowsItemSizeChanged)
+ Q_PROPERTY(bool mirrorVertically READ mirrorVertically WRITE setMirrorVertically NOTIFY mirrorVerticallyChanged)
public:
@@ -73,6 +74,9 @@ public:
bool textureFollowsItemSize() const;
void setTextureFollowsItemSize(bool follows);
+ bool mirrorVertically() const;
+ void setMirrorVertically(bool enable);
+
virtual Renderer *createRenderer() const = 0;
bool isTextureProvider() const Q_DECL_OVERRIDE;
@@ -87,6 +91,7 @@ protected:
Q_SIGNALS:
void textureFollowsItemSizeChanged(bool);
+ void mirrorVerticallyChanged(bool);
private Q_SLOTS:
void invalidateSceneGraph();
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index 99c77488f4..65d7362e84 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -267,9 +267,13 @@ qreal QQuickGridViewPrivate::originPosition() const
qreal QQuickGridViewPrivate::lastPosition() const
{
qreal pos = 0;
- if (model && model->count()) {
- // get end position of last item
- pos = (rowPosAt(model->count() - 1) + rowSize());
+ if (model && (model->count() || !visibleItems.isEmpty())) {
+ qreal lastRowPos = model->count() ? rowPosAt(model->count() - 1) : 0;
+ if (!visibleItems.isEmpty()) {
+ // If there are items in delayRemove state, they may be after any items linked to the model
+ lastRowPos = qMax(lastRowPos, static_cast<FxGridItemSG*>(visibleItems.last())->rowPos());
+ }
+ pos = lastRowPos + rowSize();
}
return pos;
}
@@ -918,13 +922,13 @@ void QQuickGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte
tempPosition -= bias;
}
FxViewItem *topItem = snapItemAt(tempPosition+highlightRangeStart);
- if (!topItem && strictHighlightRange && currentItem) {
+ if (strictHighlightRange && currentItem && (!topItem || topItem->index != currentIndex)) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
topItem = currentItem;
}
FxViewItem *bottomItem = snapItemAt(tempPosition+highlightRangeEnd);
- if (!bottomItem && strictHighlightRange && currentItem) {
+ if (strictHighlightRange && currentItem && (!bottomItem || bottomItem->index != currentIndex)) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
bottomItem = currentItem;
diff --git a/src/quick/items/qquickgridview_p.h b/src/quick/items/qquickgridview_p.h
index 7e1ace01dd..8c93f4ce97 100644
--- a/src/quick/items/qquickgridview_p.h
+++ b/src/quick/items/qquickgridview_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKGRIDVIEW_P_H
#define QQUICKGRIDVIEW_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickitemview_p.h"
@@ -52,8 +63,6 @@ class Q_AUTOTEST_EXPORT QQuickGridView : public QQuickItemView
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
- Q_ENUMS(SnapMode)
- Q_ENUMS(Flow)
Q_CLASSINFO("DefaultProperty", "data")
public:
@@ -61,6 +70,7 @@ public:
FlowLeftToRight = LeftToRight,
FlowTopToBottom = TopToBottom
};
+ Q_ENUM(Flow)
QQuickGridView(QQuickItem *parent=0);
~QQuickGridView();
@@ -78,6 +88,7 @@ public:
void setCellHeight(qreal);
enum SnapMode { NoSnap, SnapToRow, SnapOneRow };
+ Q_ENUM(SnapMode)
SnapMode snapMode() const;
void setSnapMode(SnapMode mode);
diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp
index 483d86c97d..20f4551af9 100644
--- a/src/quick/items/qquickimage.cpp
+++ b/src/quick/items/qquickimage.cpp
@@ -196,7 +196,6 @@ void QQuickImagePrivate::setPixmap(const QQuickPixmap &pixmap)
Set this property to define what happens when the source image has a different size
than the item.
-
\list
\li Image.Stretch - the image is scaled to fit
\li Image.PreserveAspectFit - the image is scaled uniformly to fit without cropping
@@ -309,8 +308,8 @@ void QQuickImage::setFillMode(FillMode mode)
\qmlproperty real QtQuick::Image::paintedHeight
These properties hold the size of the image that is actually painted.
- In most cases it is the same as \c width and \c height, but when using a
- \c fillMode \c PreserveAspectFit or \c fillMode \c PreserveAspectCrop
+ In most cases it is the same as \c width and \c height, but when using an
+ \l {fillMode}{Image.PreserveAspectFit} or an \l {fillMode}{Image.PreserveAspectCrop}
\c paintedWidth or \c paintedHeight can be smaller or larger than
\c width and \c height of the Image item.
*/
diff --git a/src/quick/items/qquickimage_p.h b/src/quick/items/qquickimage_p.h
index be514ae2f5..82bd005463 100644
--- a/src/quick/items/qquickimage_p.h
+++ b/src/quick/items/qquickimage_p.h
@@ -34,18 +34,26 @@
#ifndef QQUICKIMAGE_P_H
#define QQUICKIMAGE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickimagebase_p.h"
#include <QtQuick/qsgtextureprovider.h>
QT_BEGIN_NAMESPACE
class QQuickImagePrivate;
-class Q_AUTOTEST_EXPORT QQuickImage : public QQuickImageBase
+class Q_QUICK_PRIVATE_EXPORT QQuickImage : public QQuickImageBase
{
Q_OBJECT
- Q_ENUMS(FillMode)
- Q_ENUMS(HAlignment)
- Q_ENUMS(VAlignment)
Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged)
Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedGeometryChanged)
@@ -62,11 +70,14 @@ public:
enum HAlignment { AlignLeft = Qt::AlignLeft,
AlignRight = Qt::AlignRight,
AlignHCenter = Qt::AlignHCenter };
+ Q_ENUM(HAlignment)
enum VAlignment { AlignTop = Qt::AlignTop,
AlignBottom = Qt::AlignBottom,
AlignVCenter = Qt::AlignVCenter };
+ Q_ENUM(VAlignment)
enum FillMode { Stretch, PreserveAspectFit, PreserveAspectCrop, Tile, TileVertically, TileHorizontally, Pad };
+ Q_ENUM(FillMode)
FillMode fillMode() const;
void setFillMode(FillMode);
diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp
index 72325243df..47952d86bd 100644
--- a/src/quick/items/qquickimagebase.cpp
+++ b/src/quick/items/qquickimagebase.cpp
@@ -36,6 +36,7 @@
#include <QtGui/qguiapplication.h>
#include <QtGui/qscreen.h>
+#include <QtGui/qicon.h>
#include <QtQml/qqmlinfo.h>
#include <QtQml/qqmlfile.h>
@@ -213,15 +214,27 @@ void QQuickImageBase::load()
d->devicePixelRatio = 1.0;
QUrl loadUrl = d->url;
- if (d->url.scheme() == QStringLiteral("image")
- || d->url.toString().endsWith(QLatin1String(".svg"))
- || d->url.toString().endsWith(QLatin1String(".svgz"))) {
- // QQuickImageProvider and SVG can generate a high resolution image when
- // sourceSize is set. If sourceSize is not set then the provider default size
- // will be used, as usual.
- if (!d->sourcesize.isEmpty())
+
+ // QQuickImageProvider and SVG can generate a high resolution image when
+ // sourceSize is set. If sourceSize is not set then the provider default size
+ // will be used, as usual.
+ bool setDevicePixelRatio = false;
+ if (!d->sourcesize.isValid()) {
+ if (loadUrl.scheme() == QStringLiteral("image")) {
+ setDevicePixelRatio = true;
+ } else {
+ QString stringUrl = loadUrl.path(QUrl::PrettyDecoded);
+ if (stringUrl.endsWith(QLatin1String("svg")) ||
+ stringUrl.endsWith(QLatin1String("svgz"))) {
+ setDevicePixelRatio = true;
+ }
+ }
+
+ if (setDevicePixelRatio)
d->devicePixelRatio = targetDevicePixelRatio;
- } else {
+ }
+
+ if (!setDevicePixelRatio) {
// (possible) local file: loadUrl and d->devicePixelRatio will be modified if
// an "@2x" file is found.
resolve2xLocalFile(d->url, targetDevicePixelRatio, &loadUrl, &d->devicePixelRatio);
@@ -326,27 +339,13 @@ void QQuickImageBase::pixmapChange()
setImplicitSize(d->pix.width() / d->devicePixelRatio, d->pix.height() / d->devicePixelRatio);
}
-// /path/to/foo.png -> path/too/foo@2x.png
-static QString image2xPath(const QString &path)
-{
- const int dotIndex = path.lastIndexOf(QLatin1Char('.'));
- if (dotIndex == -1)
- return path + QLatin1String("@2x");
- if (path.contains(QLatin1String("@2x.")))
- return path;
-
- QString retinaPath = path;
- retinaPath.insert(dotIndex, QStringLiteral("@2x"));
- return retinaPath;
-}
-
void QQuickImageBase::resolve2xLocalFile(const QUrl &url, qreal targetDevicePixelRatio, QUrl *sourceUrl, qreal *sourceDevicePixelRatio)
{
Q_ASSERT(sourceUrl);
Q_ASSERT(sourceDevicePixelRatio);
// Bail out if "@2x" image loading is disabled, don't change the source url or devicePixelRatio.
- static bool disable2xImageLoading = !qgetenv("QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING").isEmpty();
+ static const bool disable2xImageLoading = !qEnvironmentVariableIsEmpty("QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING");
if (disable2xImageLoading)
return;
@@ -357,23 +356,20 @@ void QQuickImageBase::resolve2xLocalFile(const QUrl &url, qreal targetDevicePixe
return;
// Special case: the url in the QML source refers directly to an "@2x" file.
- if (localFile.contains(QLatin1String("@2x"))) {
- *sourceDevicePixelRatio = qreal(2.0);
- return;
+ int atLocation = localFile.lastIndexOf(QLatin1Char('@'));
+ if (atLocation > 0 && atLocation + 3 < localFile.size()) {
+ if (localFile[atLocation + 1].isDigit()
+ && localFile[atLocation + 2] == QLatin1Char('x')
+ && localFile[atLocation + 3] == QLatin1Char('.')) {
+ *sourceDevicePixelRatio = localFile[atLocation + 1].digitValue();
+ return;
+ }
}
- // Don't load @2x files non normal-dpi displays.
- if (!(targetDevicePixelRatio > qreal(1.0)))
- return;
-
// Look for an @2x version
- QString localFile2x = image2xPath(localFile);
- if (!QFile(localFile2x).exists())
- return;
-
- // @2x file found found: Change url and devicePixelRatio
- *sourceUrl = QUrl::fromLocalFile(localFile2x);
- *sourceDevicePixelRatio = qreal(2.0);
+ QString localFileX = qt_findAtNxFile(localFile, targetDevicePixelRatio, sourceDevicePixelRatio);
+ if (localFileX != localFile)
+ *sourceUrl = QUrl::fromLocalFile(localFileX);
}
bool QQuickImageBase::autoTransform() const
diff --git a/src/quick/items/qquickimagebase_p.h b/src/quick/items/qquickimagebase_p.h
index 4fcfaecd7d..b6d592c826 100644
--- a/src/quick/items/qquickimagebase_p.h
+++ b/src/quick/items/qquickimagebase_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKIMAGEBASE_P_H
#define QQUICKIMAGEBASE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickimplicitsizeitem_p.h"
#include <private/qtquickglobal_p.h>
@@ -43,7 +54,6 @@ class QQuickImageBasePrivate;
class Q_QUICK_PRIVATE_EXPORT QQuickImageBase : public QQuickImplicitSizeItem
{
Q_OBJECT
- Q_ENUMS(Status)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
@@ -57,6 +67,7 @@ public:
QQuickImageBase(QQuickItem *parent=0);
~QQuickImageBase();
enum Status { Null, Ready, Loading, Error };
+ Q_ENUM(Status)
Status status() const;
qreal progress() const;
diff --git a/src/quick/items/qquickimplicitsizeitem_p.h b/src/quick/items/qquickimplicitsizeitem_p.h
index 3499cf22c5..1acbb7791d 100644
--- a/src/quick/items/qquickimplicitsizeitem_p.h
+++ b/src/quick/items/qquickimplicitsizeitem_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKIMPLICITSIZEITEM_H
#define QQUICKIMPLICITSIZEITEM_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickpainteditem.h"
#include <private/qtquickglobal_p.h>
diff --git a/src/quick/items/qquickimplicitsizeitem_p_p.h b/src/quick/items/qquickimplicitsizeitem_p_p.h
index f2e502af15..d606474e9d 100644
--- a/src/quick/items/qquickimplicitsizeitem_p_p.h
+++ b/src/quick/items/qquickimplicitsizeitem_p_p.h
@@ -51,7 +51,7 @@
QT_BEGIN_NAMESPACE
-class QQuickImplicitSizeItemPrivate : public QQuickItemPrivate
+class Q_QUICK_PRIVATE_EXPORT QQuickImplicitSizeItemPrivate : public QQuickItemPrivate
{
Q_DECLARE_PUBLIC(QQuickImplicitSizeItem)
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index fbea3a0ee1..224decefec 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -72,14 +72,14 @@
#endif
#include <algorithm>
-#include <float.h>
+#include <limits>
// XXX todo Check that elements that create items handle memory correctly after visual ownership change
QT_BEGIN_NAMESPACE
#ifndef QT_NO_DEBUG
-static bool qsg_leak_check = !qgetenv("QML_LEAK_CHECK").isEmpty();
+static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK");
#endif
void debugFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1)
@@ -217,8 +217,8 @@ bool QQuickContents::calcHeight(QQuickItem *changed)
m_y = top;
m_height = bottom - top;
} else {
- qreal top = FLT_MAX;
- qreal bottom = 0;
+ qreal top = std::numeric_limits<qreal>::max();
+ qreal bottom = -std::numeric_limits<qreal>::max();
QList<QQuickItem *> children = m_item->childItems();
for (int i = 0; i < children.count(); ++i) {
QQuickItem *child = children.at(i);
@@ -252,8 +252,8 @@ bool QQuickContents::calcWidth(QQuickItem *changed)
m_x = left;
m_width = right - left;
} else {
- qreal left = FLT_MAX;
- qreal right = 0;
+ qreal left = std::numeric_limits<qreal>::max();
+ qreal right = -std::numeric_limits<qreal>::max();
QList<QQuickItem *> children = m_item->childItems();
for (int i = 0; i < children.count(); ++i) {
QQuickItem *child = children.at(i);
@@ -622,7 +622,7 @@ void QQuickKeyNavigationAttached::keyPressed(QKeyEvent *event, bool post)
mirror = QQuickItemPrivate::get(parentItem)->effectiveLayoutMirror;
QQuickItem* leftItem = mirror ? d->right : d->left;
if (leftItem) {
- setFocusNavigation(leftItem, mirror ? "right" : "left");
+ setFocusNavigation(leftItem, mirror ? "right" : "left", mirror ? Qt::TabFocusReason : Qt::BacktabFocusReason);
event->accept();
}
break;
@@ -632,20 +632,20 @@ void QQuickKeyNavigationAttached::keyPressed(QKeyEvent *event, bool post)
mirror = QQuickItemPrivate::get(parentItem)->effectiveLayoutMirror;
QQuickItem* rightItem = mirror ? d->left : d->right;
if (rightItem) {
- setFocusNavigation(rightItem, mirror ? "left" : "right");
+ setFocusNavigation(rightItem, mirror ? "left" : "right", mirror ? Qt::BacktabFocusReason : Qt::TabFocusReason);
event->accept();
}
break;
}
case Qt::Key_Up:
if (d->up) {
- setFocusNavigation(d->up, "up");
+ setFocusNavigation(d->up, "up", Qt::BacktabFocusReason);
event->accept();
}
break;
case Qt::Key_Down:
if (d->down) {
- setFocusNavigation(d->down, "down");
+ setFocusNavigation(d->down, "down", Qt::TabFocusReason);
event->accept();
}
break;
@@ -1306,8 +1306,8 @@ void QQuickKeysAttached::setPriority(Priority order)
void QQuickKeysAttached::componentComplete()
{
- Q_D(QQuickKeysAttached);
#ifndef QT_NO_IM
+ Q_D(QQuickKeysAttached);
if (d->item) {
for (int ii = 0; ii < d->targets.count(); ++ii) {
QQuickItem *targetItem = d->targets.at(ii);
@@ -1610,6 +1610,85 @@ void QQuickItemPrivate::setLayoutMirror(bool mirror)
}
}
+/*!
+ \qmltype EnterKey
+ \instantiates QQuickEnterKeyAttached
+ \inqmlmodule QtQuick
+ \ingroup qtquick-input
+ \since 5.6
+ \brief Provides a property to manipulate the appearance of Enter key on
+ an on-screen keyboard.
+
+ The EnterKey attached property is used to manipulate the appearance and
+ behavior of the Enter key on an on-screen keyboard.
+*/
+
+/*!
+ \qmlproperty enumeration QtQuick::EnterKey::type
+
+ Holds the type of the Enter key.
+
+ \note Not all of these values are supported on all platforms. For
+ unsupported values the default key is used instead.
+
+ \value Qt.EnterKeyDefault The default Enter key. This can be either a
+ button to accept the input and close the
+ keyboard, or a \e Return button to enter a
+ newline in case of a multi-line input field.
+
+ \value Qt.EnterKeyReturn Show a \e Return button that inserts a
+ newline.
+
+ \value Qt.EnterKeyDone Show a \e {"Done"} button. Typically, the
+ keyboard is expected to close when the button
+ is pressed.
+
+ \value Qt.EnterKeyGo Show a \e {"Go"} button. Typically used in an
+ address bar when entering a URL.
+
+ \value Qt.EnterKeySend Show a \e {"Send"} button.
+
+ \value Qt.EnterKeySearch Show a \e {"Search"} button.
+
+ \value Qt.EnterKeyNext Show a \e {"Next"} button. Typically used in a
+ form to allow navigating to the next input
+ field without the keyboard closing.
+
+ \value Qt.EnterKeyPrevious Show a \e {"Previous"} button.
+*/
+
+QQuickEnterKeyAttached::QQuickEnterKeyAttached(QObject *parent)
+ : QObject(parent), itemPrivate(0), keyType(Qt::EnterKeyDefault)
+{
+ if (QQuickItem *item = qobject_cast<QQuickItem*>(parent)) {
+ itemPrivate = QQuickItemPrivate::get(item);
+ itemPrivate->extra.value().enterKeyAttached = this;
+ } else
+ qmlInfo(parent) << tr("EnterKey attached property only works with Items");
+}
+
+QQuickEnterKeyAttached *QQuickEnterKeyAttached::qmlAttachedProperties(QObject *object)
+{
+ return new QQuickEnterKeyAttached(object);
+}
+
+Qt::EnterKeyType QQuickEnterKeyAttached::type() const
+{
+ return keyType;
+}
+
+void QQuickEnterKeyAttached::setType(Qt::EnterKeyType type)
+{
+ if (keyType != type) {
+ keyType = type;
+#ifndef QT_NO_IM
+ if (itemPrivate && itemPrivate->activeFocus)
+ QGuiApplication::inputMethod()->update(Qt::ImEnterKeyType);
+#endif
+ typeChanged();
+ }
+}
+
void QQuickItemPrivate::setAccessible()
{
isAccessible = true;
@@ -2345,6 +2424,50 @@ bool QQuickItemPrivate::focusNextPrev(QQuickItem *item, bool forward)
return true;
}
+QQuickItem *QQuickItemPrivate::nextTabChildItem(const QQuickItem *item, int start)
+{
+ if (!item) {
+ qWarning() << "QQuickItemPrivate::nextTabChildItem called with null item.";
+ return Q_NULLPTR;
+ }
+ const QList<QQuickItem *> &children = item->childItems();
+ const int count = children.count();
+ if (start < 0 || start >= count) {
+ qWarning() << "QQuickItemPrivate::nextTabChildItem: Start index value out of range for item" << item;
+ return Q_NULLPTR;
+ }
+ while (start < count) {
+ QQuickItem *child = children.at(start);
+ if (!child->d_func()->isTabFence)
+ return child;
+ ++start;
+ }
+ return Q_NULLPTR;
+}
+
+QQuickItem *QQuickItemPrivate::prevTabChildItem(const QQuickItem *item, int start)
+{
+ if (!item) {
+ qWarning() << "QQuickItemPrivate::prevTabChildItem called with null item.";
+ return Q_NULLPTR;
+ }
+ const QList<QQuickItem *> &children = item->childItems();
+ const int count = children.count();
+ if (start == -1)
+ start = count - 1;
+ if (start < 0 || start >= count) {
+ qWarning() << "QQuickItemPrivate::prevTabChildItem: Start index value out of range for item" << item;
+ return Q_NULLPTR;
+ }
+ while (start >= 0) {
+ QQuickItem *child = children.at(start);
+ if (!child->d_func()->isTabFence)
+ return child;
+ --start;
+ }
+ return Q_NULLPTR;
+}
+
QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, bool forward)
{
Q_ASSERT(item);
@@ -2367,7 +2490,6 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo
from = item->parentItem();
}
bool skip = false;
- const QQuickItem * const originalItem = item;
QQuickItem * startItem = item;
QQuickItem * firstFromItem = from;
QQuickItem *current = item;
@@ -2376,46 +2498,53 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo
QQuickItem *last = current;
bool hasChildren = !current->childItems().isEmpty() && current->isEnabled() && current->isVisible();
+ QQuickItem *firstChild = Q_NULLPTR;
+ QQuickItem *lastChild = Q_NULLPTR;
+ if (hasChildren) {
+ firstChild = nextTabChildItem(current, 0);
+ if (!firstChild)
+ hasChildren = false;
+ else
+ lastChild = prevTabChildItem(current, -1);
+ }
+ bool isTabFence = current->d_func()->isTabFence;
// coming from parent: check children
if (hasChildren && from == current->parentItem()) {
if (forward) {
- current = current->childItems().first();
+ current = firstChild;
} else {
- current = current->childItems().last();
+ current = lastChild;
if (!current->childItems().isEmpty())
skip = true;
}
- } else if (hasChildren && forward && from != current->childItems().last()) {
+ } else if (hasChildren && forward && from != lastChild) {
// not last child going forwards
int nextChild = current->childItems().indexOf(from) + 1;
- current = current->childItems().at(nextChild);
- } else if (hasChildren && !forward && from != current->childItems().first()) {
+ current = nextTabChildItem(current, nextChild);
+ } else if (hasChildren && !forward && from != firstChild) {
// not first child going backwards
int prevChild = current->childItems().indexOf(from) - 1;
- current = current->childItems().at(prevChild);
+ current = prevTabChildItem(current, prevChild);
if (!current->childItems().isEmpty())
skip = true;
// back to the parent
- } else if (current->parentItem()) {
- current = current->parentItem();
+ } else if (QQuickItem *parent = !isTabFence ? current->parentItem() : Q_NULLPTR) {
// we would evaluate the parent twice, thus we skip
if (forward) {
skip = true;
- } else if (!forward && !current->childItems().isEmpty()) {
- if (last != current->childItems().first()) {
- skip = true;
- } else if (last == current->childItems().first()) {
- if (current->isFocusScope() && current->activeFocusOnTab() && current->hasActiveFocus())
+ } else if (QQuickItem *firstSibling = !forward ? nextTabChildItem(parent, 0) : Q_NULLPTR) {
+ if (last != firstSibling
+ || (parent->isFocusScope() && parent->activeFocusOnTab() && parent->hasActiveFocus()))
skip = true;
- }
}
+ current = parent;
} else if (hasChildren) {
// Wrap around after checking all items forward
if (forward) {
- current = current->childItems().first();
+ current = firstChild;
} else {
- current = current->childItems().last();
+ current = lastChild;
if (!current->childItems().isEmpty())
skip = true;
}
@@ -2423,9 +2552,9 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo
from = last;
if (current == startItem && from == firstFromItem) {
// wrapped around, avoid endless loops
- if (originalItem == contentItem) {
+ if (item == contentItem) {
qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return contentItem";
- return item->window()->contentItem();
+ return item;
} else {
qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return " << startItem;
return startItem;
@@ -2475,7 +2604,7 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
QQuickItem *itemAncestor = parentItem;
while (itemAncestor != 0) {
if (itemAncestor == this) {
- qWarning("QQuickItem::setParentItem: Parent is already part of this items subtree.");
+ qWarning() << "QQuickItem::setParentItem: Parent" << parentItem << "is already part of the subtree of" << this;
return;
}
itemAncestor = itemAncestor->parentItem();
@@ -2587,7 +2716,15 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
/*!
Moves the specified \a sibling item to the index before this item
- within the visual stacking order.
+ within the list of children. The order of children affects both the
+ visual stacking order and tab focus navigation order.
+
+ Assuming the z values of both items are the same, this will cause \a
+ sibling to be rendered above this item.
+
+ If both items have activeFocusOnTab set to \c true, this will also cause
+ the tab focus order to change, with \a sibling receiving focus after this
+ item.
The given \a sibling must be a sibling of this item; that is, they must
have the same immediate \l parent.
@@ -2623,7 +2760,15 @@ void QQuickItem::stackBefore(const QQuickItem *sibling)
/*!
Moves the specified \a sibling item to the index after this item
- within the visual stacking order.
+ within the list of children. The order of children affects both the
+ visual stacking order and tab focus navigation order.
+
+ Assuming the z values of both items are the same, this will cause \a
+ sibling to be rendered below this item.
+
+ If both items have activeFocusOnTab set to \c true, this will also cause
+ the tab focus order to change, with \a sibling receiving focus before this
+ item.
The given \a sibling must be a sibling of this item; that is, they must
have the same immediate \l parent.
@@ -2778,7 +2923,7 @@ void QQuickItemPrivate::refWindow(QQuickWindow *c)
window = c;
if (polishScheduled)
- QQuickWindowPrivate::get(window)->itemsToPolish.insert(q);
+ QQuickWindowPrivate::get(window)->itemsToPolish.append(q);
if (!parentItem)
QQuickWindowPrivate::get(window)->parentlessItems.insert(q);
@@ -2810,7 +2955,7 @@ void QQuickItemPrivate::derefWindow()
removeFromDirtyList();
QQuickWindowPrivate *c = QQuickWindowPrivate::get(window);
if (polishScheduled)
- c->itemsToPolish.remove(q);
+ c->itemsToPolish.removeOne(q);
QMutableHashIterator<int, QQuickItem *> itemTouchMapIt(c->itemForTouchPointId);
while (itemTouchMapIt.hasNext()) {
if (itemTouchMapIt.next().value() == q)
@@ -2949,6 +3094,8 @@ QQuickItemPrivate::QQuickItemPrivate()
, activeFocusOnTab(false)
, implicitAntialiasing(false)
, antialiasingValid(false)
+ , isTabFence(false)
+ , replayingPressEvent(false)
, dirtyAttributes(0)
, nextDirtyItem(0)
, prevDirtyItem(0)
@@ -3962,6 +4109,11 @@ QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const
case Qt::ImPreferredLanguage:
if (d->extra.isAllocated() && d->extra->keyHandler)
v = d->extra->keyHandler->inputMethodQuery(query);
+ break;
+ case Qt::ImEnterKeyType:
+ if (d->extra.isAllocated() && d->extra->enterKeyAttached)
+ v = d->extra->enterKeyAttached->type();
+ break;
default:
break;
}
@@ -4104,7 +4256,7 @@ void QQuickItem::polish()
if (d->window) {
QQuickWindowPrivate *p = QQuickWindowPrivate::get(d->window);
bool maybeupdate = p->itemsToPolish.isEmpty();
- p->itemsToPolish.insert(this);
+ p->itemsToPolish.append(this);
if (maybeupdate) d->window->maybeUpdate();
}
}
@@ -4126,8 +4278,10 @@ void QQuickItem::polish()
*/
void QQuickItem::mapFromItem(QQmlV4Function *args) const
{
- if (args->length() == 0)
+ if (args->length() != 3 && args->length() != 5) {
+ args->v4engine()->throwTypeError();
return;
+ }
QV4::ExecutionEngine *v4 = args->v4engine();
QV4::Scope scope(v4);
@@ -4143,19 +4297,33 @@ void QQuickItem::mapFromItem(QQmlV4Function *args) const
if (!itemObj && !item->isNull()) {
qmlInfo(this) << "mapFromItem() given argument \"" << item->toQStringNoThrow()
<< "\" which is neither null nor an Item";
+ args->v4engine()->throwTypeError();
return;
}
- QV4::ScopedValue v(scope);
+ QV4::ScopedValue vx(scope, (*args)[1]);
+ QV4::ScopedValue vy(scope, (*args)[2]);
- qreal x = (args->length() > 1) ? (v = (*args)[1])->asDouble() : 0;
- qreal y = (args->length() > 2) ? (v = (*args)[2])->asDouble() : 0;
+ if (!vx->isNumber() || !vy->isNumber()) {
+ args->v4engine()->throwTypeError();
+ return;
+ }
+
+ qreal x = vx->asDouble();
+ qreal y = vy->asDouble();
QVariant result;
if (args->length() > 3) {
- qreal w = (v = (*args)[3])->asDouble();
- qreal h = (args->length() > 4) ? (v = (*args)[4])->asDouble() : 0;
+ QV4::ScopedValue vw(scope, (*args)[3]);
+ QV4::ScopedValue vh(scope, (*args)[4]);
+ if (!vw->isNumber() || !vh->isNumber()) {
+ args->v4engine()->throwTypeError();
+ return;
+ }
+ qreal w = vw->asDouble();
+ qreal h = vh->asDouble();
+
result = mapRectFromItem(itemObj, QRectF(x, y, w, h));
} else {
result = mapFromItem(itemObj, QPointF(x, y));
@@ -4198,8 +4366,10 @@ QTransform QQuickItem::itemTransform(QQuickItem *other, bool *ok) const
*/
void QQuickItem::mapToItem(QQmlV4Function *args) const
{
- if (args->length() == 0)
+ if (args->length() != 3 && args->length() != 5) {
+ args->v4engine()->throwTypeError();
return;
+ }
QV4::ExecutionEngine *v4 = args->v4engine();
QV4::Scope scope(v4);
@@ -4215,18 +4385,32 @@ void QQuickItem::mapToItem(QQmlV4Function *args) const
if (!itemObj && !item->isNull()) {
qmlInfo(this) << "mapToItem() given argument \"" << item->toQStringNoThrow()
<< "\" which is neither null nor an Item";
+ args->v4engine()->throwTypeError();
return;
}
- QV4::ScopedValue v(scope);
- QVariant result;
+ QV4::ScopedValue vx(scope, (*args)[1]);
+ QV4::ScopedValue vy(scope, (*args)[2]);
+
+ if (!vx->isNumber() || !vy->isNumber()) {
+ args->v4engine()->throwTypeError();
+ return;
+ }
+
+ qreal x = vx->asDouble();
+ qreal y = vy->asDouble();
- qreal x = (args->length() > 1) ? (v = (*args)[1])->asDouble() : 0;
- qreal y = (args->length() > 2) ? (v = (*args)[2])->asDouble() : 0;
+ QVariant result;
if (args->length() > 3) {
- qreal w = (v = (*args)[3])->asDouble();
- qreal h = (args->length() > 4) ? (v = (*args)[4])->asDouble() : 0;
+ QV4::ScopedValue vw(scope, (*args)[3]);
+ QV4::ScopedValue vh(scope, (*args)[4]);
+ if (!vw->isNumber() || !vh->isNumber()) {
+ args->v4engine()->throwTypeError();
+ return;
+ }
+ qreal w = vw->asDouble();
+ qreal h = vh->asDouble();
result = mapRectToItem(itemObj, QRectF(x, y, w, h));
} else {
@@ -5578,7 +5762,7 @@ QString QQuickItemPrivate::dirtyToString() const
{
#define DIRTY_TO_STRING(value) if (dirtyAttributes & value) { \
if (!rv.isEmpty()) \
- rv.append(QLatin1String("|")); \
+ rv.append(QLatin1Char('|')); \
rv.append(QLatin1String(#value)); \
}
@@ -7408,6 +7592,7 @@ QQuickItemLayer::QQuickItemLayer(QQuickItem *item)
, m_effectComponent(0)
, m_effect(0)
, m_effectSource(0)
+ , m_textureMirroring(QQuickShaderEffectSource::MirrorVertically)
{
}
@@ -7481,6 +7666,7 @@ void QQuickItemLayer::activate()
m_effectSource->setMipmap(m_mipmap);
m_effectSource->setWrapMode(m_wrapMode);
m_effectSource->setFormat(m_format);
+ m_effectSource->setTextureMirroring(m_textureMirroring);
if (m_effectComponent)
activateEffect();
@@ -7745,6 +7931,35 @@ void QQuickItemLayer::setWrapMode(QQuickShaderEffectSource::WrapMode mode)
}
/*!
+ \qmlproperty enumeration QtQuick::Item::layer.textureMirroring
+ \since 5.6
+
+ This property defines how the generated OpenGL texture should be mirrored.
+ The default value is \c{ShaderEffectSource.MirrorVertically}.
+ Custom mirroring can be useful if the generated texture is directly accessed by custom shaders,
+ such as those specified by ShaderEffect. If no effect is specified for the layered
+ item, mirroring has no effect on the UI representation of the item.
+
+ \list
+ \li ShaderEffectSource.NoMirroring - No mirroring
+ \li ShaderEffectSource.MirrorHorizontally - The generated texture is flipped along X-axis.
+ \li ShaderEffectSource.MirrorVertically - The generated texture is flipped along Y-axis.
+ \endlist
+ */
+
+void QQuickItemLayer::setTextureMirroring(QQuickShaderEffectSource::TextureMirroring mirroring)
+{
+ if (mirroring == m_textureMirroring)
+ return;
+ m_textureMirroring = mirroring;
+
+ if (m_effectSource)
+ m_effectSource->setTextureMirroring(m_textureMirroring);
+
+ emit textureMirroringChanged(mirroring);
+}
+
+/*!
\qmlproperty string QtQuick::Item::layer.samplerName
Holds the name of the effect's source texture property.
@@ -7856,6 +8071,7 @@ void QQuickItemLayer::updateMatrix()
QQuickItemPrivate::ExtraData::ExtraData()
: z(0), scale(1), rotation(0), opacity(1),
contents(0), screenAttached(0), layoutDirectionAttached(0),
+ enterKeyAttached(0),
keyHandler(0), layer(0),
effectRefCount(0), hideRefCount(0),
opacityNode(0), clipNode(0), rootNode(0),
@@ -7864,6 +8080,19 @@ QQuickItemPrivate::ExtraData::ExtraData()
{
}
+
+#ifndef QT_NO_ACCESSIBILITY
+QAccessible::Role QQuickItemPrivate::accessibleRole() const
+{
+ Q_Q(const QQuickItem);
+ QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, false));
+ if (accessibleAttached)
+ return accessibleAttached->role();
+
+ return QAccessible::NoRole;
+}
+#endif
+
QT_END_NAMESPACE
#include <moc_qquickitem.cpp>
diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h
index 463113386b..d92910ce9c 100644
--- a/src/quick/items/qquickitem.h
+++ b/src/quick/items/qquickitem.h
@@ -141,7 +141,6 @@ class Q_QUICK_EXPORT QQuickItem : public QObject, public QQmlParserStatus
Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickItemLayer *layer READ layer DESIGNABLE false CONSTANT FINAL)
- Q_ENUMS(TransformOrigin)
Q_CLASSINFO("DefaultProperty", "data")
Q_CLASSINFO("qt_HasQmlAccessors", "true")
@@ -187,6 +186,7 @@ public:
Left, Center, Right,
BottomLeft, Bottom, BottomRight
};
+ Q_ENUM(TransformOrigin)
QQuickItem(QQuickItem *parent = 0);
virtual ~QQuickItem();
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 64d8bd0ede..634aa2b658 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -78,6 +78,7 @@ QT_BEGIN_NAMESPACE
class QNetworkReply;
class QQuickItemKeyFilter;
class QQuickLayoutMirroringAttached;
+class QQuickEnterKeyAttached;
class QQuickScreenAttached;
class QQuickContents : public QQuickItemChangeListener
@@ -142,6 +143,7 @@ class QQuickItemLayer : public QObject, public QQuickItemChangeListener
Q_PROPERTY(QQuickShaderEffectSource::Format format READ format WRITE setFormat NOTIFY formatChanged)
Q_PROPERTY(QByteArray samplerName READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(QQmlComponent *effect READ effect WRITE setEffect NOTIFY effectChanged)
+ Q_PROPERTY(QQuickShaderEffectSource::TextureMirroring textureMirroring READ textureMirroring WRITE setTextureMirroring NOTIFY textureMirroringChanged)
public:
QQuickItemLayer(QQuickItem *item);
~QQuickItemLayer();
@@ -176,6 +178,9 @@ public:
QQmlComponent *effect() const { return m_effectComponent; }
void setEffect(QQmlComponent *effect);
+ QQuickShaderEffectSource::TextureMirroring textureMirroring() const { return m_textureMirroring; }
+ void setTextureMirroring(QQuickShaderEffectSource::TextureMirroring mirroring);
+
QQuickShaderEffectSource *effectSource() const { return m_effectSource; }
void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &) Q_DECL_OVERRIDE;
@@ -199,6 +204,7 @@ Q_SIGNALS:
void smoothChanged(bool smooth);
void formatChanged(QQuickShaderEffectSource::Format format);
void sourceRectChanged(const QRectF &sourceRect);
+ void textureMirroringChanged(QQuickShaderEffectSource::TextureMirroring mirroring);
private:
friend class QQuickTransformAnimatorJob;
@@ -222,6 +228,7 @@ private:
QQmlComponent *m_effectComponent;
QQuickItem *m_effect;
QQuickShaderEffectSource *m_effectSource;
+ QQuickShaderEffectSource::TextureMirroring m_textureMirroring;
};
class Q_QUICK_PRIVATE_EXPORT QQuickItemPrivate : public QObjectPrivate
@@ -338,6 +345,7 @@ public:
QQuickContents *contents;
QQuickScreenAttached *screenAttached;
QQuickLayoutMirroringAttached* layoutDirectionAttached;
+ QQuickEnterKeyAttached *enterKeyAttached;
QQuickItemKeyFilter *keyHandler;
mutable QQuickItemLayer *layer;
#ifndef QT_NO_CURSOR
@@ -419,6 +427,13 @@ public:
bool activeFocusOnTab:1;
bool implicitAntialiasing:1;
bool antialiasingValid:1;
+ // isTabFence: When true, the item acts as a fence within the tab focus chain.
+ // This means that the item and its children will be skipped from the tab focus
+ // chain when navigating from its parent or any of its siblings. Similarly,
+ // when any of the item's descendants gets focus, the item constrains the tab
+ // focus chain and prevents tabbing outside.
+ bool isTabFence:1;
+ bool replayingPressEvent:1;
enum DirtyType {
TransformOrigin = 0x00000001,
@@ -490,6 +505,8 @@ public:
void itemToParentTransform(QTransform &) const;
static bool focusNextPrev(QQuickItem *item, bool forward);
+ static QQuickItem *nextTabChildItem(const QQuickItem *item, int start);
+ static QQuickItem *prevTabChildItem(const QQuickItem *item, int start);
static QQuickItem *nextPrevItemInTabFocusChain(QQuickItem *item, bool forward);
static bool canAcceptTabFocus(QQuickItem *item);
@@ -517,6 +534,10 @@ public:
virtual void implicitWidthChanged();
virtual void implicitHeightChanged();
+#ifndef QT_NO_ACCESSIBILITY
+ virtual QAccessible::Role accessibleRole() const;
+#endif
+
void setImplicitAntialiasing(bool antialiasing);
void resolveLayoutMirror();
@@ -645,8 +666,6 @@ class Q_QUICK_PRIVATE_EXPORT QQuickKeyNavigationAttached : public QObject, publi
Q_PROPERTY(QQuickItem *backtab READ backtab WRITE setBacktab NOTIFY backtabChanged)
Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged)
- Q_ENUMS(Priority)
-
public:
QQuickKeyNavigationAttached(QObject * = 0);
@@ -664,6 +683,7 @@ public:
void setBacktab(QQuickItem *);
enum Priority { BeforeItem, AfterItem };
+ Q_ENUM(Priority)
Priority priority() const;
void setPriority(Priority);
@@ -710,6 +730,27 @@ private:
QQuickItemPrivate *itemPrivate;
};
+class QQuickEnterKeyAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt::EnterKeyType type READ type WRITE setType NOTIFY typeChanged)
+
+public:
+ explicit QQuickEnterKeyAttached(QObject *parent = Q_NULLPTR);
+
+ Qt::EnterKeyType type() const;
+ void setType(Qt::EnterKeyType type);
+
+ static QQuickEnterKeyAttached *qmlAttachedProperties(QObject *);
+Q_SIGNALS:
+ void typeChanged();
+private:
+ friend class QQuickItemPrivate;
+ QQuickItemPrivate *itemPrivate;
+
+ Qt::EnterKeyType keyType;
+};
+
class QQuickKeysAttachedPrivate : public QObjectPrivate
{
public:
@@ -739,8 +780,6 @@ class QQuickKeysAttached : public QObject, public QQuickItemKeyFilter
Q_PROPERTY(QQmlListProperty<QQuickItem> forwardTo READ forwardTo)
Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged)
- Q_ENUMS(Priority)
-
public:
QQuickKeysAttached(QObject *parent=0);
~QQuickKeysAttached();
@@ -755,6 +794,7 @@ public:
}
enum Priority { BeforeItem, AfterItem};
+ Q_ENUM(Priority)
Priority priority() const;
void setPriority(Priority);
@@ -895,5 +935,7 @@ QML_DECLARE_TYPE(QQuickKeyNavigationAttached)
QML_DECLARE_TYPEINFO(QQuickKeyNavigationAttached, QML_HAS_ATTACHED_PROPERTIES)
QML_DECLARE_TYPE(QQuickLayoutMirroringAttached)
QML_DECLARE_TYPEINFO(QQuickLayoutMirroringAttached, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(QQuickEnterKeyAttached)
+QML_DECLARE_TYPEINFO(QQuickEnterKeyAttached, QML_HAS_ATTACHED_PROPERTIES)
#endif // QQUICKITEM_P_H
diff --git a/src/quick/items/qquickitemanimation_p.h b/src/quick/items/qquickitemanimation_p.h
index 907687a2bd..338af46ecb 100644
--- a/src/quick/items/qquickitemanimation_p.h
+++ b/src/quick/items/qquickitemanimation_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKITEMANIMATION_H
#define QQUICKITEMANIMATION_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickitem.h"
#include <QtQuick/private/qquickanimation_p.h>
@@ -136,7 +147,7 @@ public:
BottomFirst,
TopFirst
};
- Q_ENUMS(Orientation)
+ Q_ENUM(Orientation)
int duration() const;
void setDuration(int);
diff --git a/src/quick/items/qquickitemchangelistener_p.h b/src/quick/items/qquickitemchangelistener_p.h
index d987b62454..fd8076c6a2 100644
--- a/src/quick/items/qquickitemchangelistener_p.h
+++ b/src/quick/items/qquickitemchangelistener_p.h
@@ -55,16 +55,16 @@ class QQuickAnchorsPrivate;
class QQuickItemChangeListener
{
public:
- virtual ~QQuickItemChangeListener() {};
+ virtual ~QQuickItemChangeListener() {}
virtual void itemGeometryChanged(QQuickItem *, const QRectF & /* new */, const QRectF & /* old */ ) {}
virtual void itemSiblingOrderChanged(QQuickItem *) {}
virtual void itemVisibilityChanged(QQuickItem *) {}
virtual void itemOpacityChanged(QQuickItem *) {}
virtual void itemDestroyed(QQuickItem *) {}
- virtual void itemChildAdded(QQuickItem *, QQuickItem *) {}
- virtual void itemChildRemoved(QQuickItem *, QQuickItem *) {}
- virtual void itemParentChanged(QQuickItem *, QQuickItem *) {}
+ virtual void itemChildAdded(QQuickItem *, QQuickItem * /* child */ ) {}
+ virtual void itemChildRemoved(QQuickItem *, QQuickItem * /* child */ ) {}
+ virtual void itemParentChanged(QQuickItem *, QQuickItem * /* parent */ ) {}
virtual void itemRotationChanged(QQuickItem *) {}
virtual void itemImplicitWidthChanged(QQuickItem *) {}
virtual void itemImplicitHeightChanged(QQuickItem *) {}
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index 5fbae66b6c..62e0adcb0a 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -158,11 +158,6 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickPathView>(uri,major,minor,"PathView");
qmlRegisterUncreatableType<QQuickBasePositioner>(uri,major,minor,"Positioner",
QStringLiteral("Positioner is an abstract type that is only available as an attached property."));
-#ifndef QT_NO_VALIDATOR
- qmlRegisterType<QQuickIntValidator>(uri,major,minor,"IntValidator");
- qmlRegisterType<QQuickDoubleValidator>(uri,major,minor,"DoubleValidator");
- qmlRegisterType<QRegExpValidator>(uri,major,minor,"RegExpValidator");
-#endif
qmlRegisterType<QQuickRectangle>(uri,major,minor,"Rectangle");
qmlRegisterType<QQuickRepeater>(uri,major,minor,"Repeater");
qmlRegisterType<QQuickRow>(uri,major,minor,"Row");
@@ -190,9 +185,6 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickCurve>();
qmlRegisterType<QQuickScaleGrid>();
qmlRegisterType<QQuickTextLine>();
-#ifndef QT_NO_VALIDATOR
- qmlRegisterType<QValidator>();
-#endif
qmlRegisterType<QQuickPen>();
qmlRegisterType<QQuickFlickableVisibleArea>();
qRegisterMetaType<QQuickAnchorLine>("QQuickAnchorLine");
@@ -269,6 +261,19 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickPinchArea, 1>(uri, 2, 5,"PinchArea");
qmlRegisterType<QQuickImage, 2>(uri, 2, 5,"Image");
qmlRegisterType<QQuickMouseArea, 2>(uri, 2, 5, "MouseArea");
+
+ qmlRegisterType<QQuickText, 6>(uri, 2, 6, "Text");
+ qmlRegisterType<QQuickTextEdit, 6>(uri, 2, 6, "TextEdit");
+ qmlRegisterType<QQuickTextInput, 6>(uri, 2, 6, "TextInput");
+ qmlRegisterUncreatableType<QQuickBasePositioner, 6>(uri, 2, 6, "Positioner",
+ QStringLiteral("Positioner is an abstract type that is only available as an attached property."));
+ qmlRegisterType<QQuickColumn, 6>(uri, 2, 6, "Column");
+ qmlRegisterType<QQuickRow, 6>(uri, 2, 6, "Row");
+ qmlRegisterType<QQuickGrid, 6>(uri, 2, 6, "Grid");
+ qmlRegisterType<QQuickFlow, 6>(uri, 2, 6, "Flow");
+ qmlRegisterUncreatableType<QQuickEnterKeyAttached, 6>(uri, 2, 6, "EnterKey",
+ QQuickEnterKeyAttached::tr("EnterKey is only available via attached properties"));
+ qmlRegisterType<QQuickShaderEffectSource, 1>(uri, 2, 6, "ShaderEffectSource");
}
static void initResources()
diff --git a/src/quick/items/qquickitemsmodule_p.h b/src/quick/items/qquickitemsmodule_p.h
index a7442e972a..b04e9ff23f 100644
--- a/src/quick/items/qquickitemsmodule_p.h
+++ b/src/quick/items/qquickitemsmodule_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKITEMSMODULE_P_H
#define QQUICKITEMSMODULE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index 01ef1e65f7..e301e8f0f2 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -71,19 +71,19 @@ FxViewItem::~FxViewItem()
qreal FxViewItem::itemX() const
{
- return transitionableItem ? transitionableItem->itemX() : item->x();
+ return transitionableItem ? transitionableItem->itemX() : (item ? item->x() : 0);
}
qreal FxViewItem::itemY() const
{
- return transitionableItem ? transitionableItem->itemY() : item->y();
+ return transitionableItem ? transitionableItem->itemY() : (item ? item->y() : 0);
}
void FxViewItem::moveTo(const QPointF &pos, bool immediate)
{
if (transitionableItem)
transitionableItem->moveTo(pos, immediate);
- else
+ else if (item)
item->setPosition(pos);
}
@@ -91,21 +91,26 @@ void FxViewItem::setVisible(bool visible)
{
if (!visible && transitionableItem && transitionableItem->transitionScheduledOrRunning())
return;
- QQuickItemPrivate::get(item)->setCulled(!visible);
+ if (item)
+ QQuickItemPrivate::get(item)->setCulled(!visible);
}
void FxViewItem::trackGeometry(bool track)
{
if (track) {
if (!trackGeom) {
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- itemPrivate->addItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
+ if (item) {
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ itemPrivate->addItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
+ }
trackGeom = true;
}
} else {
if (trackGeom) {
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- itemPrivate->removeItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
+ if (item) {
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ itemPrivate->removeItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
+ }
trackGeom = false;
}
}
@@ -905,11 +910,7 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode)
qreal pos = isContentFlowReversed() ? -position() - size() : position();
FxViewItem *item = visibleItem(idx);
- qreal maxExtent;
- if (layoutOrientation() == Qt::Vertical)
- maxExtent = isContentFlowReversed() ? q->minYExtent()-size(): -q->maxYExtent();
- else
- maxExtent = isContentFlowReversed() ? q->minXExtent()-size(): -q->maxXExtent();
+ qreal maxExtent = calculatedMaxExtent();
if (!item) {
qreal itemPos = positionAt(idx);
changedVisibleIndex(idx);
@@ -927,7 +928,7 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode)
switch (mode) {
case QQuickItemView::Beginning:
pos = itemPos;
- if (index < 0 && header)
+ if (header && (index < 0 || hasStickyHeader()))
pos -= headerSize();
break;
case QQuickItemView::Center:
@@ -935,7 +936,7 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode)
break;
case QQuickItemView::End:
pos = itemPos - size() + item->size();
- if (index >= model->count() && footer)
+ if (footer && (index >= model->count() || hasStickyFooter()))
pos += footerSize();
break;
case QQuickItemView::Visible:
@@ -955,11 +956,7 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode)
break;
}
pos = qMin(pos, maxExtent);
- qreal minExtent;
- if (layoutOrientation() == Qt::Vertical)
- minExtent = isContentFlowReversed() ? q->maxYExtent()-size(): -q->minYExtent();
- else
- minExtent = isContentFlowReversed() ? q->maxXExtent()-size(): -q->minXExtent();
+ qreal minExtent = calculatedMinExtent();
pos = qMax(pos, minExtent);
moveReason = QQuickItemViewPrivate::Other;
q->cancelFlick();
@@ -1130,6 +1127,29 @@ qreal QQuickItemViewPrivate::maxExtentForAxis(const AxisData &axisData, bool for
return extent;
}
+qreal QQuickItemViewPrivate::calculatedMinExtent() const
+{
+ Q_Q(const QQuickItemView);
+ qreal minExtent;
+ if (layoutOrientation() == Qt::Vertical)
+ minExtent = isContentFlowReversed() ? q->maxYExtent() - size(): -q->minYExtent();
+ else
+ minExtent = isContentFlowReversed() ? q->maxXExtent() - size(): -q->minXExtent();
+ return minExtent;
+
+}
+
+qreal QQuickItemViewPrivate::calculatedMaxExtent() const
+{
+ Q_Q(const QQuickItemView);
+ qreal maxExtent;
+ if (layoutOrientation() == Qt::Vertical)
+ maxExtent = isContentFlowReversed() ? q->minYExtent() - size(): -q->maxYExtent();
+ else
+ maxExtent = isContentFlowReversed() ? q->minXExtent() - size(): -q->maxXExtent();
+ return maxExtent;
+}
+
// for debugging only
void QQuickItemViewPrivate::checkVisible() const
{
@@ -1199,7 +1219,7 @@ void QQuickItemView::destroyRemoved()
for (QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
it != d->visibleItems.end();) {
FxViewItem *item = *it;
- if (item->index == -1 && item->attached->delayRemove() == false) {
+ if (item->index == -1 && (!item->attached || item->attached->delayRemove() == false)) {
if (d->transitioner && d->transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, true)) {
// don't remove from visibleItems until next layout()
d->runDelayedRemoveTransition = true;
@@ -1277,10 +1297,12 @@ void QQuickItemView::trackedPositionChanged()
if (trackedPos < pos + d->highlightRangeStart)
pos = trackedPos - d->highlightRangeStart;
if (d->highlightRange != StrictlyEnforceRange) {
- if (pos > d->endPosition() - d->size())
- pos = d->endPosition() - d->size();
- if (pos < d->startPosition())
- pos = d->startPosition();
+ qreal maxExtent = d->calculatedMaxExtent();
+ if (pos > maxExtent)
+ pos = maxExtent;
+ qreal minExtent = d->calculatedMinExtent();
+ if (pos < minExtent)
+ pos = minExtent;
}
} else {
if (d->trackedItem != d->currentItem) {
@@ -1344,7 +1366,7 @@ void QQuickItemView::geometryChanged(const QRectF &newGeometry, const QRectF &ol
{
Q_D(QQuickItemView);
d->markExtentsDirty();
- if (isComponentComplete() && d->isValid())
+ if (isComponentComplete() && (d->isValid() || !d->visibleItems.isEmpty()))
d->forceLayoutPolish();
QQuickFlickable::geometryChanged(newGeometry, oldGeometry);
}
@@ -1641,7 +1663,8 @@ void QQuickItemViewPrivate::updateCurrent(int modelIndex)
applyPendingChanges();
if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
if (currentItem) {
- currentItem->attached->setIsCurrentItem(false);
+ if (currentItem->attached)
+ currentItem->attached->setIsCurrentItem(false);
releaseItem(currentItem);
currentItem = 0;
currentIndex = modelIndex;
@@ -1664,18 +1687,20 @@ void QQuickItemViewPrivate::updateCurrent(int modelIndex)
int oldCurrentIndex = currentIndex;
currentIndex = modelIndex;
currentItem = createItem(modelIndex, false);
- if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
+ if (oldCurrentItem && oldCurrentItem->attached && (!currentItem || oldCurrentItem->item != currentItem->item))
oldCurrentItem->attached->setIsCurrentItem(false);
if (currentItem) {
currentItem->item->setFocus(true);
- currentItem->attached->setIsCurrentItem(true);
+ if (currentItem->attached)
+ currentItem->attached->setIsCurrentItem(true);
initializeCurrentItem();
}
updateHighlight();
if (oldCurrentIndex != currentIndex)
emit q->currentIndexChanged();
- if (oldCurrentItem != currentItem)
+ if (oldCurrentItem != currentItem
+ && (!oldCurrentItem || !currentItem || oldCurrentItem->item != currentItem->item))
emit q->currentItemChanged();
releaseItem(oldCurrentItem);
}
@@ -1806,7 +1831,7 @@ void QQuickItemViewPrivate::updateViewport()
{
Q_Q(QQuickItemView);
qreal extra = headerSize() + footerSize();
- qreal contentSize = isValid() ? (endPosition() - startPosition()) : 0.0;
+ qreal contentSize = isValid() || !visibleItems.isEmpty() ? (endPosition() - startPosition()) : 0.0;
if (layoutOrientation() == Qt::Vertical)
q->setContentHeight(contentSize + extra);
else
@@ -1824,6 +1849,7 @@ void QQuickItemViewPrivate::layout()
if (!isValid() && !visibleItems.count()) {
clear();
setPosition(contentStartOffset());
+ updateViewport();
if (transitioner)
transitioner->setPopulateTransitionEnabled(false);
inLayout = false;
@@ -1967,7 +1993,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
QQmlChangeSet::Change removal;
for (QList<FxViewItem*>::Iterator it = visibleItems.begin(); it != visibleItems.end();) {
FxViewItem *item = *it;
- if (item->index == -1 && !item->attached->delayRemove()) {
+ if (item->index == -1 && (!item->attached || !item->attached->delayRemove())) {
removeItem(item, removal, &removalResult);
removedCount++;
it = visibleItems.erase(it);
@@ -2007,8 +2033,10 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
}
itemCount += insertions[i].count;
}
- for (int i=0; i<newItems.count(); i++)
- newItems.at(i)->attached->emitAdd();
+ for (int i=0; i<newItems.count(); i++) {
+ if (newItems.at(i)->attached)
+ newItems.at(i)->attached->emitAdd();
+ }
// for each item that was moved directly into the view as a result of a move(),
// find the index it was moved from in order to set its initial position, so that we
@@ -2040,7 +2068,8 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
if (currentChanges.currentChanged) {
if (currentChanges.currentRemoved && currentItem) {
- currentItem->attached->setIsCurrentItem(false);
+ if (currentItem->item && currentItem->attached)
+ currentItem->attached->setIsCurrentItem(false);
releaseItem(currentItem);
currentItem = 0;
}
@@ -2092,10 +2121,10 @@ bool QQuickItemViewPrivate::applyRemovalChange(const QQmlChangeSet::Change &remo
} else {
// removed item
visibleAffected = true;
- if (!removal.isMove())
+ if (!removal.isMove() && item->item && item->attached)
item->attached->emitRemove();
- if (item->attached->delayRemove() && !removal.isMove()) {
+ if (item->item && item->attached && item->attached->delayRemove() && !removal.isMove()) {
item->index = -1;
QObject::connect(item->attached, SIGNAL(delayRemoveChanged()), q, SLOT(destroyRemoved()), Qt::QueuedConnection);
++it;
@@ -2352,12 +2381,14 @@ bool QQuickItemViewPrivate::releaseItem(FxViewItem *item)
item->trackGeometry(false);
QQmlInstanceModel::ReleaseFlags flags = model->release(item->item);
- if (flags == 0) {
- // item was not destroyed, and we no longer reference it.
- QQuickItemPrivate::get(item->item)->setCulled(true);
- unrequestedItems.insert(item->item, model->indexOf(item->item, q));
- } else if (flags & QQmlInstanceModel::Destroyed) {
- item->item->setParentItem(0);
+ if (item->item) {
+ if (flags == 0) {
+ // item was not destroyed, and we no longer reference it.
+ QQuickItemPrivate::get(item->item)->setCulled(true);
+ unrequestedItems.insert(item->item, model->indexOf(item->item, q));
+ } else if (flags & QQmlInstanceModel::Destroyed) {
+ item->item->setParentItem(0);
+ }
}
delete item;
return flags != QQmlInstanceModel::Referenced;
@@ -2421,7 +2452,7 @@ void QQuickItemViewPrivate::updateUnrequestedIndexes()
void QQuickItemViewPrivate::updateUnrequestedPositions()
{
- for (QHash<QQuickItem*,int>::const_iterator it = unrequestedItems.begin(), cend = unrequestedItems.end(); it != cend; ++it)
+ for (QHash<QQuickItem*,int>::const_iterator it = unrequestedItems.cbegin(), cend = unrequestedItems.cend(); it != cend; ++it)
repositionPackageItemAt(it.key(), it.value());
}
diff --git a/src/quick/items/qquickitemview_p.h b/src/quick/items/qquickitemview_p.h
index 6e5ae032c2..d5c4f59ed2 100644
--- a/src/quick/items/qquickitemview_p.h
+++ b/src/quick/items/qquickitemview_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKITEMVIEW_P_H
#define QQUICKITEMVIEW_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickflickable_p.h"
#include <qpointer.h>
#include <QtCore/QLoggingCategory>
@@ -46,7 +57,7 @@ class QQmlChangeSet;
class QQuickItemViewPrivate;
-class Q_AUTOTEST_EXPORT QQuickItemView : public QQuickFlickable
+class Q_QUICK_PRIVATE_EXPORT QQuickItemView : public QQuickFlickable
{
Q_OBJECT
@@ -88,11 +99,6 @@ class Q_AUTOTEST_EXPORT QQuickItemView : public QQuickFlickable
Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged RESET resetPreferredHighlightEnd)
Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged)
- Q_ENUMS(HighlightRangeMode)
- Q_ENUMS(PositionMode)
- Q_ENUMS(VerticalLayoutDirection)
- Q_ENUMS(LayoutDirection)
-
public:
// this holds all layout enum values so they can be referred to by other enums
// to ensure consistent values - e.g. QML references to GridView.TopToBottom flow
@@ -103,11 +109,13 @@ public:
VerticalTopToBottom,
VerticalBottomToTop
};
+ Q_ENUM(LayoutDirection)
enum VerticalLayoutDirection {
TopToBottom = VerticalTopToBottom,
BottomToTop = VerticalBottomToTop
};
+ Q_ENUM(VerticalLayoutDirection)
QQuickItemView(QQuickFlickablePrivate &dd, QQuickItem *parent = 0);
~QQuickItemView();
@@ -185,6 +193,7 @@ public:
virtual void setHighlightFollowsCurrentItem(bool);
enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
+ Q_ENUM(HighlightRangeMode)
HighlightRangeMode highlightRangeMode() const;
void setHighlightRangeMode(HighlightRangeMode mode);
@@ -200,6 +209,7 @@ public:
virtual void setHighlightMoveDuration(int);
enum PositionMode { Beginning, Center, End, Visible, Contain, SnapPosition };
+ Q_ENUM(PositionMode)
Q_INVOKABLE void positionViewAtIndex(int index, int mode);
Q_INVOKABLE int indexAt(qreal x, qreal y) const;
@@ -274,7 +284,7 @@ private:
};
-class Q_AUTOTEST_EXPORT QQuickItemViewAttached : public QObject
+class Q_QUICK_PRIVATE_EXPORT QQuickItemViewAttached : public QObject
{
Q_OBJECT
diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h
index a8352b229e..925cffcbd9 100644
--- a/src/quick/items/qquickitemview_p_p.h
+++ b/src/quick/items/qquickitemview_p_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKITEMVIEW_P_P_H
#define QQUICKITEMVIEW_P_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickitemview_p.h"
#include "qquickitemviewtransition_p.h"
#include "qquickflickable_p_p.h"
@@ -45,7 +56,7 @@
QT_BEGIN_NAMESPACE
-class FxViewItem
+class Q_AUTOTEST_EXPORT FxViewItem
{
public:
FxViewItem(QQuickItem *, QQuickItemView *, bool own, QQuickItemViewAttached *attached);
@@ -53,6 +64,8 @@ public:
qreal itemX() const;
qreal itemY() const;
+ inline qreal itemWidth() const { return item ? item->width() : 0; }
+ inline qreal itemHeight() const { return item ? item->height() : 0; }
void moveTo(const QPointF &pos, bool immediate);
void setVisible(bool visible);
@@ -75,7 +88,7 @@ public:
virtual bool contains(qreal x, qreal y) const = 0;
- QQuickItem *item;
+ QPointer<QQuickItem> item;
QQuickItemView *view;
QQuickItemViewTransitionableItem *transitionableItem;
QQuickItemViewAttached *attached;
@@ -110,7 +123,7 @@ public:
};
-class QQuickItemViewPrivate : public QQuickFlickablePrivate, public QQuickItemViewTransitionChangeListener, public QAnimationJobChangeListener
+class Q_AUTOTEST_EXPORT QQuickItemViewPrivate : public QQuickFlickablePrivate, public QQuickItemViewTransitionChangeListener, public QAnimationJobChangeListener
{
Q_DECLARE_PUBLIC(QQuickItemView)
public:
@@ -198,6 +211,8 @@ public:
qreal minExtentForAxis(const AxisData &axisData, bool forXAxis) const;
qreal maxExtentForAxis(const AxisData &axisData, bool forXAxis) const;
+ qreal calculatedMinExtent() const;
+ qreal calculatedMaxExtent() const;
void applyPendingChanges();
bool applyModelChanges(ChangeResult *insertionResult, ChangeResult *removalResult);
@@ -321,6 +336,8 @@ protected:
virtual bool showFooterForIndex(int index) const = 0;
virtual void updateHeader() = 0;
virtual void updateFooter() = 0;
+ virtual bool hasStickyHeader() const { return false; };
+ virtual bool hasStickyFooter() const { return false; };
virtual void createHighlight() = 0;
virtual void updateHighlight() = 0;
diff --git a/src/quick/items/qquickitemviewtransition.cpp b/src/quick/items/qquickitemviewtransition.cpp
index 3218e3847c..565377df58 100644
--- a/src/quick/items/qquickitemviewtransition.cpp
+++ b/src/quick/items/qquickitemviewtransition.cpp
@@ -34,6 +34,7 @@
#include "qquickitemviewtransition_p.h"
#include <QtQuick/qquickitem.h>
#include <QtQuick/private/qquicktransition_p.h>
+#include <QtQuick/private/qquicktransitionmanager_p_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick/items/qquickitemviewtransition_p.h b/src/quick/items/qquickitemviewtransition_p.h
index 170072a814..b4c2705fd3 100644
--- a/src/quick/items/qquickitemviewtransition_p.h
+++ b/src/quick/items/qquickitemviewtransition_p.h
@@ -34,16 +34,31 @@
#ifndef QQUICKITEMVIEWTRANSITION_P_P_H
#define QQUICKITEMVIEWTRANSITION_P_P_H
-#include <private/qquicktransitionmanager_p_p.h>
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuick/private/qtquickglobal_p.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qpoint.h>
+#include <QtQml/qqml.h>
QT_BEGIN_NAMESPACE
class QQuickItem;
+class QQuickTransition;
class QQuickItemViewTransitionableItem;
class QQuickItemViewTransitionJob;
-class QQuickItemViewTransitionChangeListener
+class Q_QUICK_PRIVATE_EXPORT QQuickItemViewTransitionChangeListener
{
public:
QQuickItemViewTransitionChangeListener() {}
@@ -53,7 +68,7 @@ public:
};
-class QQuickItemViewTransitioner
+class Q_QUICK_PRIVATE_EXPORT QQuickItemViewTransitioner
{
public:
enum TransitionType {
@@ -113,7 +128,7 @@ private:
/*
An item that can be transitioned using QQuickViewTransitionJob.
*/
-class QQuickItemViewTransitionableItem
+class Q_QUICK_PRIVATE_EXPORT QQuickItemViewTransitionableItem
{
public:
QQuickItemViewTransitionableItem(QQuickItem *i);
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 20b6dd5b36..242fdd2cfa 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -81,6 +81,8 @@ public:
bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) Q_DECL_OVERRIDE;
void visibleItemsChanged() Q_DECL_OVERRIDE;
+ void removeItem(FxViewItem *item);
+
FxViewItem *newViewItem(int index, QQuickItem *item) Q_DECL_OVERRIDE;
void initializeViewItem(FxViewItem *item) Q_DECL_OVERRIDE;
bool releaseItem(FxViewItem *item) Q_DECL_OVERRIDE;
@@ -115,8 +117,8 @@ public:
bool showFooterForIndex(int index) const Q_DECL_OVERRIDE;
void updateHeader() Q_DECL_OVERRIDE;
void updateFooter() Q_DECL_OVERRIDE;
- bool hasStickyHeader() const;
- bool hasStickyFooter() const;
+ bool hasStickyHeader() const Q_DECL_OVERRIDE;
+ bool hasStickyFooter() const Q_DECL_OVERRIDE;
void changedVisibleIndex(int newIndex) Q_DECL_OVERRIDE;
void initializeCurrentItem() Q_DECL_OVERRIDE;
@@ -249,7 +251,7 @@ public:
}
inline QQuickItem *section() const {
- return attached ? static_cast<QQuickListViewAttached*>(attached)->m_sectionItem : 0;
+ return item && attached ? static_cast<QQuickListViewAttached*>(attached)->m_sectionItem : 0;
}
void setSection(QQuickItem *s) {
static_cast<QQuickListViewAttached*>(attached)->m_sectionItem = s;
@@ -267,18 +269,18 @@ public:
}
qreal itemPosition() const {
if (view->orientation() == QQuickListView::Vertical)
- return (view->verticalLayoutDirection() == QQuickItemView::BottomToTop ? -item->height()-itemY() : itemY());
+ return (view->verticalLayoutDirection() == QQuickItemView::BottomToTop ? -itemHeight()-itemY() : itemY());
else
- return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -item->width()-itemX() : itemX());
+ return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -itemWidth()-itemX() : itemX());
}
qreal size() const Q_DECL_OVERRIDE {
if (section())
- return (view->orientation() == QQuickListView::Vertical ? item->height()+section()->height() : item->width()+section()->width());
+ return (view->orientation() == QQuickListView::Vertical ? itemHeight()+section()->height() : itemWidth()+section()->width());
else
- return (view->orientation() == QQuickListView::Vertical ? item->height() : item->width());
+ return (view->orientation() == QQuickListView::Vertical ? itemHeight() : itemWidth());
}
qreal itemSize() const {
- return (view->orientation() == QQuickListView::Vertical ? item->height() : item->width());
+ return (view->orientation() == QQuickListView::Vertical ? itemHeight() : itemWidth());
}
qreal sectionSize() const Q_DECL_OVERRIDE {
if (section())
@@ -289,11 +291,11 @@ public:
if (view->orientation() == QQuickListView::Vertical) {
return (view->verticalLayoutDirection() == QQuickItemView::BottomToTop
? -itemY()
- : itemY() + item->height());
+ : itemY() + itemHeight());
} else {
return (view->effectiveLayoutDirection() == Qt::RightToLeft
? -itemX()
- : itemX() + item->width());
+ : itemX() + itemWidth());
}
}
void setPosition(qreal pos, bool immediate = false) {
@@ -320,8 +322,8 @@ public:
item->setWidth(size);
}
bool contains(qreal x, qreal y) const Q_DECL_OVERRIDE {
- return (x >= itemX() && x < itemX() + item->width() &&
- y >= itemY() && y < itemY() + item->height());
+ return (x >= itemX() && x < itemX() + itemWidth() &&
+ y >= itemY() && y < itemY() + itemHeight());
}
QQuickListView *view;
@@ -332,7 +334,7 @@ private:
if (view->verticalLayoutDirection() == QQuickItemView::BottomToTop) {
if (section())
pos += section()->height();
- return QPointF(itemX(), -item->height() - pos);
+ return QPointF(itemX(), -itemHeight() - pos);
} else {
if (section())
pos += section()->height();
@@ -342,7 +344,7 @@ private:
if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
if (section())
pos += section()->width();
- return QPointF(-item->width() - pos, itemY());
+ return QPointF(-itemWidth() - pos, itemY());
} else {
if (section())
pos += section()->width();
@@ -427,14 +429,24 @@ qreal QQuickListViewPrivate::lastPosition() const
{
qreal pos = 0;
if (!visibleItems.isEmpty()) {
- int invisibleCount = visibleItems.count() - visibleIndex;
+ int invisibleCount = INT_MIN;
+ int delayRemovedCount = 0;
for (int i = visibleItems.count()-1; i >= 0; --i) {
if (visibleItems.at(i)->index != -1) {
- invisibleCount = model->count() - visibleItems.at(i)->index - 1;
+ // Find the invisible count after the last visible item with known index
+ invisibleCount = model->count() - (visibleItems.at(i)->index + 1 + delayRemovedCount);
break;
+ } else if (visibleItems.at(i)->attached->delayRemove()) {
+ ++delayRemovedCount;
}
}
- pos = (*(--visibleItems.constEnd()))->endPosition() + invisibleCount * (averageSize + spacing);
+ if (invisibleCount == INT_MIN) {
+ // All visible items are in delayRemove state
+ invisibleCount = model->count();
+ }
+ pos = (*(--visibleItems.constEnd()))->endPosition();
+ if (invisibleCount > 0)
+ pos += invisibleCount * (averageSize + spacing);
} else if (model && model->count()) {
pos = (model->count() * averageSize + (model->count()-1) * spacing);
}
@@ -599,10 +611,11 @@ bool QQuickListViewPrivate::releaseItem(FxViewItem *item)
if (!item || !model)
return true;
+ QPointer<QQuickItem> it = item->item;
QQuickListViewAttached *att = static_cast<QQuickListViewAttached*>(item->attached);
bool released = QQuickItemViewPrivate::releaseItem(item);
- if (released && att && att->m_sectionItem) {
+ if (released && it && att && att->m_sectionItem) {
// We hold no more references to this item
int i = 0;
do {
@@ -657,10 +670,11 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal
while (modelIndex < model->count() && pos <= fillTo) {
if (!(item = static_cast<FxListItemSG*>(createItem(modelIndex, doBuffer))))
break;
- qCDebug(lcItemViewDelegateLifecycle) << "refill: append item" << modelIndex << "pos" << pos << "buffer" << doBuffer << "item" << item->item->objectName();
+ qCDebug(lcItemViewDelegateLifecycle) << "refill: append item" << modelIndex << "pos" << pos << "buffer" << doBuffer << "item" << (QObject *)(item->item);
if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
item->setPosition(pos, true);
- QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
+ if (item->item)
+ QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
pos += item->size() + spacing;
visibleItems.append(item);
++modelIndex;
@@ -673,12 +687,13 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal
while (visibleIndex > 0 && visibleIndex <= model->count() && visiblePos > fillFrom) {
if (!(item = static_cast<FxListItemSG*>(createItem(visibleIndex-1, doBuffer))))
break;
- qCDebug(lcItemViewDelegateLifecycle) << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos << "buffer" << doBuffer << "item" << item->item->objectName();
+ qCDebug(lcItemViewDelegateLifecycle) << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos << "buffer" << doBuffer << "item" << (QObject *)(item->item);
--visibleIndex;
visiblePos -= item->size() + spacing;
if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
item->setPosition(visiblePos, true);
- QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
+ if (item->item)
+ QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
visibleItems.prepend(item);
changed = true;
}
@@ -686,6 +701,18 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal
return changed;
}
+void QQuickListViewPrivate::removeItem(FxViewItem *item)
+{
+ if (item->transitionScheduledOrRunning()) {
+ qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item" << item->index << (QObject *)(item->item);
+ item->releaseAfterTransition = true;
+ releasePendingTransition.append(item);
+ } else {
+ qCDebug(lcItemViewDelegateLifecycle) << "\treleasing stationary item" << item->index << (QObject *)(item->item);
+ releaseItem(item);
+ }
+}
+
bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal bufferTo)
{
FxViewItem *item = 0;
@@ -708,13 +735,7 @@ bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
if (item->index != -1)
visibleIndex++;
visibleItems.removeAt(index);
- if (item->transitionScheduledOrRunning()) {
- qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item" << item->index << item->item->objectName();
- item->releaseAfterTransition = true;
- releasePendingTransition.append(item);
- } else {
- releaseItem(item);
- }
+ removeItem(item);
if (index == 0)
break;
item = visibleItems.at(--index);
@@ -728,15 +749,9 @@ bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
while (visibleItems.count() > 1 && (item = visibleItems.last()) && item->position() > bufferTo) {
if (item->attached->delayRemove())
break;
- qCDebug(lcItemViewDelegateLifecycle) << "refill: remove last" << visibleIndex+visibleItems.count()-1 << item->position() << item->item->objectName();
+ qCDebug(lcItemViewDelegateLifecycle) << "refill: remove last" << visibleIndex+visibleItems.count()-1 << item->position() << (QObject *)(item->item);
visibleItems.removeLast();
- if (item->transitionScheduledOrRunning()) {
- qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item" << item->index << item->item->objectName();
- item->releaseAfterTransition = true;
- releasePendingTransition.append(item);
- } else {
- releaseItem(item);
- }
+ removeItem(item);
changed = true;
}
@@ -1289,7 +1304,7 @@ bool QQuickListViewPrivate::showHeaderForIndex(int index) const
bool QQuickListViewPrivate::showFooterForIndex(int index) const
{
- return index == model->count()-1;
+ return model && index == model->count()-1;
}
void QQuickListViewPrivate::updateFooter()
@@ -1388,6 +1403,15 @@ void QQuickListViewPrivate::itemGeometryChanged(QQuickItem *item, const QRectF &
if (!q->isComponentComplete())
return;
+ if (currentItem && currentItem->item == item) {
+ const bool contentFlowReversed = isContentFlowReversed();
+ const qreal pos = position();
+ const qreal sz = size();
+ const qreal from = contentFlowReversed ? -pos - displayMarginBeginning - sz : pos - displayMarginBeginning;
+ const qreal to = contentFlowReversed ? -pos + displayMarginEnd : pos + sz + displayMarginEnd;
+ QQuickItemPrivate::get(currentItem->item)->setCulled(currentItem->endPosition() < from || currentItem->position() > to);
+ }
+
if (item != contentItem && (!highlight || item != highlight->item)) {
if ((orient == QQuickListView::Vertical && newGeometry.height() != oldGeometry.height())
|| (orient == QQuickListView::Horizontal && newGeometry.width() != oldGeometry.width())) {
@@ -1457,13 +1481,13 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte
tempPosition -= bias;
}
FxViewItem *topItem = snapItemAt(tempPosition+highlightRangeStart);
- if (!topItem && strictHighlightRange && currentItem) {
+ if (strictHighlightRange && currentItem && (!topItem || topItem->index != currentIndex)) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
topItem = currentItem;
}
FxViewItem *bottomItem = snapItemAt(tempPosition+highlightRangeEnd);
- if (!bottomItem && strictHighlightRange && currentItem) {
+ if (strictHighlightRange && currentItem && (!bottomItem || bottomItem->index != currentIndex)) {
// StrictlyEnforceRange always keeps an item in range
updateHighlight();
bottomItem = currentItem;
@@ -2844,7 +2868,8 @@ void QQuickListView::viewportMoved(Qt::Orientations orient)
qreal to = d->isContentFlowReversed() ? -d->position()+d->displayMarginEnd : d->position()+d->size()+d->displayMarginEnd;
for (int i = 0; i < d->visibleItems.count(); ++i) {
FxViewItem *item = static_cast<FxListItemSG*>(d->visibleItems.at(i));
- QQuickItemPrivate::get(item->item)->setCulled(item->endPosition() < from || item->position() > to);
+ if (item->item)
+ QQuickItemPrivate::get(item->item)->setCulled(item->endPosition() < from || item->position() > to);
}
if (d->currentItem)
QQuickItemPrivate::get(d->currentItem->item)->setCulled(d->currentItem->endPosition() < from || d->currentItem->position() > to);
@@ -3097,12 +3122,13 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
int i = 0;
qreal from = tempPos - displayMarginBeginning - buffer;
- for (i = count-1; i >= 0; --i) {
- if (pos > from && insertionIdx < visibleIndex) {
- // item won't be visible, just note the size for repositioning
- insertResult->sizeChangesBeforeVisiblePos += averageSize + spacing;
- pos -= averageSize + spacing;
- } else {
+ if (insertionIdx < visibleIndex) {
+ if (pos >= from) {
+ // items won't be visible, just note the size for repositioning
+ insertResult->sizeChangesBeforeVisiblePos += count * (averageSize + spacing);
+ }
+ } else {
+ for (i = count-1; i >= 0 && pos >= from; --i) {
// item is before first visible e.g. in cache buffer
FxViewItem *item = 0;
if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i))))
@@ -3117,17 +3143,33 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
insertResult->changedFirstItem = true;
if (!change.isMove()) {
addedItems->append(item);
- item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
+ if (transitioner)
+ item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
+ else
+ static_cast<FxListItemSG *>(item)->setPosition(pos, true);
}
insertResult->sizeChangesBeforeVisiblePos += item->size() + spacing;
pos -= item->size() + spacing;
+ index++;
+ }
+ }
+
+ int firstOkIdx = -1;
+ for (int i = 0; i <= insertionIdx && i < visibleItems.count() - 1; i++) {
+ if (visibleItems.at(i)->index + 1 != visibleItems.at(i + 1)->index) {
+ firstOkIdx = i + 1;
+ break;
}
- index++;
}
+ for (int i = 0; i < firstOkIdx; i++) {
+ FxViewItem *nvItem = visibleItems.takeFirst();
+ addedItems->removeOne(nvItem);
+ removeItem(nvItem);
+ }
+
} else {
- int i = 0;
qreal to = buffer + displayMarginEnd + tempPos + size();
- for (i = 0; i < count && pos <= to; ++i) {
+ for (int i = 0; i < count && pos <= to; ++i) {
FxViewItem *item = 0;
if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i))))
item->index = modelIndex + i;
@@ -3147,12 +3189,32 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
movingIntoView->append(MovedItem(item, change.moveKey(item->index)));
} else {
addedItems->append(item);
- item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
+ if (transitioner)
+ item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
+ else
+ static_cast<FxListItemSG *>(item)->setPosition(pos, true);
}
insertResult->sizeChangesAfterVisiblePos += item->size() + spacing;
pos += item->size() + spacing;
++index;
}
+
+ if (0 < index && index < visibleItems.count()) {
+ FxViewItem *prevItem = visibleItems.at(index - 1);
+ FxViewItem *item = visibleItems.at(index);
+ if (prevItem->index != item->index - 1) {
+ int i = index;
+ qreal prevPos = prevItem->position();
+ while (i < visibleItems.count()) {
+ FxListItemSG *nvItem = static_cast<FxListItemSG *>(visibleItems.takeLast());
+ insertResult->sizeChangesAfterVisiblePos -= nvItem->size() + spacing;
+ addedItems->removeOne(nvItem);
+ if (nvItem->transitionScheduledOrRunning())
+ nvItem->setPosition(prevPos + (nvItem->index - prevItem->index) * averageSize);
+ removeItem(nvItem);
+ }
+ }
+ }
}
updateVisibleIndex();
diff --git a/src/quick/items/qquicklistview_p.h b/src/quick/items/qquicklistview_p.h
index bcb4e18751..74bdad2d69 100644
--- a/src/quick/items/qquicklistview_p.h
+++ b/src/quick/items/qquicklistview_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKLISTVIEW_P_H
#define QQUICKLISTVIEW_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickitemview_p.h"
QT_BEGIN_NAMESPACE
@@ -47,8 +58,6 @@ class Q_AUTOTEST_EXPORT QQuickViewSection : public QObject
Q_PROPERTY(SectionCriteria criteria READ criteria WRITE setCriteria NOTIFY criteriaChanged)
Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
Q_PROPERTY(int labelPositioning READ labelPositioning WRITE setLabelPositioning NOTIFY labelPositioningChanged)
- Q_ENUMS(SectionCriteria)
- Q_ENUMS(LabelPositioning)
public:
QQuickViewSection(QQuickListView *parent=0);
@@ -56,6 +65,7 @@ public:
void setProperty(const QString &);
enum SectionCriteria { FullString, FirstCharacter };
+ Q_ENUM(SectionCriteria)
SectionCriteria criteria() const { return m_criteria; }
void setCriteria(SectionCriteria);
@@ -65,6 +75,7 @@ public:
QString sectionString(const QString &value);
enum LabelPositioning { InlineLabels = 0x01, CurrentLabelAtStart = 0x02, NextLabelAtEnd = 0x04 };
+ Q_ENUM(LabelPositioning)
int labelPositioning() { return m_labelPositioning; }
void setLabelPositioning(int pos);
@@ -106,10 +117,6 @@ class Q_AUTOTEST_EXPORT QQuickListView : public QQuickItemView
Q_PROPERTY(HeaderPositioning headerPositioning READ headerPositioning WRITE setHeaderPositioning NOTIFY headerPositioningChanged REVISION 2)
Q_PROPERTY(FooterPositioning footerPositioning READ footerPositioning WRITE setFooterPositioning NOTIFY footerPositioningChanged REVISION 2)
- Q_ENUMS(Orientation)
- Q_ENUMS(SnapMode)
- Q_ENUMS(HeaderPositioning)
- Q_ENUMS(FooterPositioning)
Q_CLASSINFO("DefaultProperty", "data")
public:
@@ -120,6 +127,7 @@ public:
void setSpacing(qreal spacing);
enum Orientation { Horizontal = Qt::Horizontal, Vertical = Qt::Vertical };
+ Q_ENUM(Orientation)
Orientation orientation() const;
void setOrientation(Orientation);
@@ -140,14 +148,17 @@ public:
void setHighlightMoveDuration(int) Q_DECL_OVERRIDE;
enum SnapMode { NoSnap, SnapToItem, SnapOneItem };
+ Q_ENUM(SnapMode)
SnapMode snapMode() const;
void setSnapMode(SnapMode mode);
enum HeaderPositioning { InlineHeader, OverlayHeader, PullBackHeader };
+ Q_ENUM(HeaderPositioning)
HeaderPositioning headerPositioning() const;
void setHeaderPositioning(HeaderPositioning positioning);
enum FooterPositioning { InlineFooter, OverlayFooter, PullBackFooter };
+ Q_ENUM(FooterPositioning)
FooterPositioning footerPositioning() const;
void setFooterPositioning(FooterPositioning positioning);
@@ -185,7 +196,7 @@ public:
~QQuickListViewAttached() {}
public:
- QQuickItem *m_sectionItem;
+ QPointer<QQuickItem> m_sectionItem;
};
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index dd04568db2..456eedd0be 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -576,7 +576,6 @@ void QQuickLoader::setSource(QQmlV4Function *args)
if (!ipv->isUndefined()) {
d->disposeInitialPropertyValues();
d->initialPropertyValues.set(args->v4engine(), ipv);
- d->qmlGlobalForIpv.set(args->v4engine(), args->qmlGlobal());
}
setSource(sourceUrl, false); // already cleared and set ipv above.
@@ -642,11 +641,11 @@ void QQuickLoaderPrivate::setInitialState(QObject *obj)
QQmlComponentPrivate *d = QQmlComponentPrivate::get(component);
Q_ASSERT(d && d->engine);
- QV4::ExecutionEngine *v4 = qmlGlobalForIpv.engine();
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(d->engine);
Q_ASSERT(v4);
QV4::Scope scope(v4);
QV4::ScopedValue ipv(scope, initialPropertyValues.value());
- d->initializeObjectWithInitialProperties(*qmlGlobalForIpv.valueRef(), ipv, obj);
+ d->initializeObjectWithInitialProperties(ipv, obj);
}
void QQuickLoaderIncubator::statusChanged(Status status)
@@ -932,7 +931,7 @@ QUrl QQuickLoaderPrivate::resolveSourceUrl(QQmlV4Function *args)
if (arg.isEmpty())
return QUrl();
- QQmlContextData *context = args->context();
+ QQmlContextData *context = scope.engine->callingQmlContext();
Q_ASSERT(context);
return context->resolvedUrl(QUrl(arg));
}
@@ -943,7 +942,7 @@ QV4::ReturnedValue QQuickLoaderPrivate::extractInitialPropertyValues(QQmlV4Funct
QV4::ScopedValue valuemap(scope, QV4::Primitive::undefinedValue());
if (args->length() >= 2) {
QV4::ScopedValue v(scope, (*args)[1]);
- if (!v->isObject() || v->asArrayObject()) {
+ if (!v->isObject() || v->as<QV4::ArrayObject>()) {
*error = true;
qmlInfo(loader) << QQuickLoader::tr("setSource: value is not an object");
} else {
diff --git a/src/quick/items/qquickloader_p.h b/src/quick/items/qquickloader_p.h
index 2c0e98de59..e9d765fa5c 100644
--- a/src/quick/items/qquickloader_p.h
+++ b/src/quick/items/qquickloader_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKLOADER_P_H
#define QQUICKLOADER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickimplicitsizeitem_p.h"
QT_BEGIN_NAMESPACE
@@ -42,7 +53,6 @@ class QQuickLoaderPrivate;
class Q_AUTOTEST_EXPORT QQuickLoader : public QQuickImplicitSizeItem
{
Q_OBJECT
- Q_ENUMS(Status)
Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
@@ -69,6 +79,7 @@ public:
void resetSourceComponent();
enum Status { Null, Ready, Loading, Error };
+ Q_ENUM(Status)
Status status() const;
qreal progress() const;
diff --git a/src/quick/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h
index 621419d1a7..9677318b58 100644
--- a/src/quick/items/qquickloader_p_p.h
+++ b/src/quick/items/qquickloader_p_p.h
@@ -50,7 +50,7 @@
#include "qquickitemchangelistener_p.h"
#include <qqmlincubator.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
QT_BEGIN_NAMESPACE
@@ -102,7 +102,6 @@ public:
QQmlContext *itemContext;
QQuickLoaderIncubator *incubator;
QV4::PersistentValue initialPropertyValues;
- QV4::PersistentValue qmlGlobalForIpv;
bool updatingSize: 1;
bool active : 1;
bool loadingFromSource : 1;
diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp
index 29d6680272..ef053abbd1 100644
--- a/src/quick/items/qquickmousearea.cpp
+++ b/src/quick/items/qquickmousearea.cpp
@@ -921,6 +921,7 @@ bool QQuickMouseArea::sendMouseEvent(QMouseEvent *event)
break;
case QEvent::MouseButtonRelease:
mouseReleaseEvent(&mouseEvent);
+ stealThisEvent = d->stealMouse;
break;
default:
break;
diff --git a/src/quick/items/qquickmousearea_p.h b/src/quick/items/qquickmousearea_p.h
index 4ad14e6bdd..e3cbf2553c 100644
--- a/src/quick/items/qquickmousearea_p.h
+++ b/src/quick/items/qquickmousearea_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKMOUSEAREA_P_H
#define QQUICKMOUSEAREA_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickitem.h"
#include <private/qtquickglobal_p.h>
#include <QtCore/qstringlist.h>
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
index e6b63d32f2..9e658cc668 100644
--- a/src/quick/items/qquickmultipointtoucharea.cpp
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -451,6 +451,12 @@ void QQuickMultiPointTouchArea::touchEvent(QTouchEvent *event)
}
break;
}
+ case QEvent::TouchCancel:
+ _stealMouse = false;
+ setKeepMouseGrab(false);
+ setKeepTouchGrab(false);
+ ungrabTouchPoints();
+ break;
default:
QQuickItem::touchEvent(event);
break;
@@ -496,8 +502,9 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
else if (event->type() == QEvent::MouseButtonRelease)
_mouseQpaTouchPoint.setState(Qt::TouchPointReleased);
else { // QEvent::MouseButtonPress
+ addTouchPoint(me);
+ started = true;
_mouseQpaTouchPoint.setState(Qt::TouchPointPressed);
- _pressedTouchPoints.append(_mouseTouchPoint);
}
touchPoints << _mouseQpaTouchPoint;
isMouseEvent = true;
@@ -723,9 +730,7 @@ void QQuickMultiPointTouchArea::mousePressEvent(QMouseEvent *event)
return;
if (_touchPoints.count() >= _minimumTouchPoints - 1 && _touchPoints.count() < _maximumTouchPoints) {
- addTouchPoint(event);
updateTouchData(event);
- emit pressed(_pressedTouchPoints);
}
}
@@ -756,10 +761,7 @@ void QQuickMultiPointTouchArea::mouseReleaseEvent(QMouseEvent *event)
if (_mouseTouchPoint) {
updateTouchData(event);
- _mouseTouchPoint->setPressed(false);
_mouseTouchPoint->setInUse(false);
- _releasedTouchPoints.append(_mouseTouchPoint);
- emit released(_releasedTouchPoints);
_releasedTouchPoints.removeAll(_mouseTouchPoint);
_mouseTouchPoint = Q_NULLPTR;
}
diff --git a/src/quick/items/qquickmultipointtoucharea_p.h b/src/quick/items/qquickmultipointtoucharea_p.h
index e5c547da81..034fe6df89 100644
--- a/src/quick/items/qquickmultipointtoucharea_p.h
+++ b/src/quick/items/qquickmultipointtoucharea_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKMULTIPOINTTOUCHAREA_H
#define QQUICKMULTIPOINTTOUCHAREA_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickitem.h"
#include "qevent.h"
@@ -72,6 +83,7 @@ public:
_qmlDefined(qmlDefined),
_inUse(false),
_pressed(false),
+ _startX(0.0), _startY(0.0),
_previousX(0.0), _previousY(0.0),
_sceneX(0.0), _sceneY(0.0)
{}
diff --git a/src/quick/items/qquickopenglinfo_p.h b/src/quick/items/qquickopenglinfo_p.h
index 2a2e2a719b..511413c814 100644
--- a/src/quick/items/qquickopenglinfo_p.h
+++ b/src/quick/items/qquickopenglinfo_p.h
@@ -63,7 +63,6 @@ class QQuickOpenGLInfo : public QObject
Q_PROPERTY(int minorVersion READ minorVersion NOTIFY minorVersionChanged FINAL)
Q_PROPERTY(ContextProfile profile READ profile NOTIFY profileChanged FINAL)
Q_PROPERTY(RenderableType renderableType READ renderableType NOTIFY renderableTypeChanged FINAL)
- Q_ENUMS(ContextProfile RenderableType)
public:
QQuickOpenGLInfo(QQuickItem *item = 0);
@@ -77,6 +76,7 @@ public:
CoreProfile = QSurfaceFormat::CoreProfile,
CompatibilityProfile = QSurfaceFormat::CompatibilityProfile
};
+ Q_ENUM(ContextProfile)
ContextProfile profile() const;
// keep in sync with QSurfaceFormat::RenderableType
@@ -85,6 +85,7 @@ public:
OpenGL = QSurfaceFormat::OpenGL,
OpenGLES = QSurfaceFormat::OpenGLES
};
+ Q_ENUM(RenderableType)
RenderableType renderableType() const;
static QQuickOpenGLInfo *qmlAttachedProperties(QObject *object);
diff --git a/src/quick/items/qquickpainteditem.cpp b/src/quick/items/qquickpainteditem.cpp
index 8d93c577ab..ad8d94d240 100644
--- a/src/quick/items/qquickpainteditem.cpp
+++ b/src/quick/items/qquickpainteditem.cpp
@@ -67,15 +67,11 @@ public:
To enable QPainter to do anti-aliased rendering, use setAntialiasing().
- To write your own painted item, you first create a subclass of QQuickPaintedItem, and then
- start by implementing its only pure virtual public function: paint(), which implements
- the actual painting. To get the size of the area painted by the item, use
- contentsBoundingRect().
-
- Starting Qt 5.4, the QQuickPaintedItem is a
- \l{QSGTextureProvider}{texture provider}
- and can be used directly in \l {ShaderEffect}{ShaderEffects} and other
- classes that consume texture providers.
+ To write your own painted item, you first create a subclass of
+ QQuickPaintedItem, and then start by implementing its only pure virtual
+ public function: paint(), which implements the actual painting. The
+ painting will be inside the rectangle spanning from 0,0 to
+ width(),height().
*/
/*!
@@ -109,11 +105,12 @@ public:
This enum describes flags that you can enable to improve rendering
performance in QQuickPaintedItem. By default, none of these flags are set.
- \value FastFBOResizing If your item gets resized often and you are using the
- QQuickPaintedItem::FramebufferObject render target, set this flag to true to reduce the
- item resizing time at the cost of using more graphics memory. Resizing a Framebuffer object
- is a costly operation, by enabling this property the Framebuffer Object will use a texture
- larger than the actual size of the item to avoid as much as possible resizing it.
+ \value FastFBOResizing Resizing an FBO can be a costly operation on a few
+ OpenGL driver implementations. To work around this, one can set this flag
+ to let the QQuickPaintedItem allocate one large framebuffer object and
+ instead draw into a subregion of it. This saves the resize at the cost of
+ using more memory. Please note that this is not a common problem.
+
*/
/*!
@@ -332,16 +329,47 @@ void QQuickPaintedItem::setPerformanceHints(QQuickPaintedItem::PerformanceHints
update();
}
+QSize QQuickPaintedItem::textureSize() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->textureSize;
+}
+
/*!
- This function returns the outer bounds of the item as a rectangle; all painting must be
- restricted to inside an item's bounding rect.
+ \property QQuickPaintedItem::textureSize
+
+ \brief Defines the size of the texture.
+
+ Changing the texture's size does not affect the coordinate system used in
+ paint(). A scale factor is instead applied so painting should still happen
+ inside 0,0 to width(),height().
+
+ By default, the texture size will have the same size as this item.
+
+ \note If the item is on a window with a device pixel ratio different from
+ 1, this scale factor will be implicitly applied to the texture size.
+
+ */
+void QQuickPaintedItem::setTextureSize(const QSize &size)
+{
+ Q_D(QQuickPaintedItem);
+ if (d->textureSize == size)
+ return;
+ d->textureSize = size;
+ emit textureSizeChanged();
+}
+
+#if QT_VERSION >= 0x060000
+#warning "Remove: QQuickPaintedItem::contentsBoundingRect, contentsScale, contentsSize. Also remove them from qsgadaptationlayer_p.h and qsgdefaultpainternode.h/cpp."
+#endif
- If the contents size has not been set it reflects the size of the item; otherwise
- it reflects the contents size scaled by the contents scale.
+/*!
+ \obsolete
- Use this function to know the area painted by the item.
+ This function is provided for compatibility, use size in combination
+ with textureSize to decide the size of what you are drawing.
- \sa QQuickItem::width(), QQuickItem::height(), contentsSize(), contentsScale()
+ \sa width(), height(), textureSize()
*/
QRectF QQuickPaintedItem::contentsBoundingRect() const
{
@@ -360,11 +388,13 @@ QRectF QQuickPaintedItem::contentsBoundingRect() const
/*!
\property QQuickPaintedItem::contentsSize
- \brief The size of the contents
+ \brief Obsolete method for setting the contents size.
+ \obsolete
- The contents size is the size of the item in regards to how it is painted
- using the paint() function. This is distinct from the size of the
- item in regards to height() and width().
+ This function is provided for compatibility, use size in combination
+ with textureSize to decide the size of what you are drawing.
+
+ \sa width(), height(), textureSize()
*/
QSize QQuickPaintedItem::contentsSize() const
{
@@ -386,6 +416,7 @@ void QQuickPaintedItem::setContentsSize(const QSize &size)
}
/*!
+ \obsolete
This convenience function is equivalent to calling setContentsSize(QSize()).
*/
void QQuickPaintedItem::resetContentsSize()
@@ -395,12 +426,13 @@ void QQuickPaintedItem::resetContentsSize()
/*!
\property QQuickPaintedItem::contentsScale
- \brief The scale of the contents
+ \brief Obsolete method for scaling the contents.
+ \obsolete
- All painting happening in paint() is scaled by the contents scale. This is distinct
- from the scale of the item in regards to scale().
+ This function is provided for compatibility, use size() in combination
+ with textureSize() to decide the size of what you are drawing.
- The default value is 1.
+ \sa width(), height(), textureSize()
*/
qreal QQuickPaintedItem::contentsScale() const
{
@@ -451,7 +483,7 @@ void QQuickPaintedItem::setFillColor(const QColor &c)
\brief The item's render target.
This property defines which render target the QPainter renders into, it can be either
- QSGPaintedItem::Image, QSGPaintedItem::FramebufferObject or QSGPaintedItem::InvertedYFramebufferObject.
+ QQuickPaintedItem::Image, QQuickPaintedItem::FramebufferObject or QQuickPaintedItem::InvertedYFramebufferObject.
Each has certain benefits, typically performance versus quality. Using a framebuffer
object avoids a costly upload of the image contents to the texture in graphics memory,
@@ -487,6 +519,9 @@ void QQuickPaintedItem::setRenderTarget(RenderTarget target)
This function, which is usually called by the QML Scene Graph, paints the
contents of an item in local coordinates.
+ The underlying texture will have a size defined by textureSize when set,
+ or the item's size, multiplied by the window's device pixel ratio.
+
The function is called after the item has been filled with the fillColor.
Reimplement this function in a QQuickPaintedItem subclass to provide the
@@ -500,6 +535,8 @@ void QQuickPaintedItem::setRenderTarget(RenderTarget target)
\warning Extreme caution must be used when creating QObjects, emitting signals, starting
timers and similar inside this function as these will have affinity to the rendering thread.
+
+ \sa width(), height(), textureSize
*/
/*!
@@ -525,17 +562,35 @@ QSGNode *QQuickPaintedItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
d->node = node;
}
- QRectF br = contentsBoundingRect();
+ bool hasTextureSize = d->textureSize.width() > 0 && d->textureSize.height() > 0;
+
+ // Use the compat mode if any of the compat things are set and
+ // textureSize is 0x0.
+ if (!hasTextureSize
+ && (d->contentsScale != 1
+ || (d->contentsSize.width() > 0 && d->contentsSize.height() > 0))) {
+ QRectF br = contentsBoundingRect();
+ node->setContentsScale(d->contentsScale);
+ QSize size = QSize(qRound(br.width()), qRound(br.height()));
+ node->setSize(size);
+ node->setTextureSize(size);
+ } else {
+ // The default, use textureSize or item's size * device pixel ratio
+ node->setContentsScale(1);
+ QSize itemSize(qRound(width()), qRound(height()));
+ node->setSize(itemSize);
+ QSize textureSize = (hasTextureSize ? d->textureSize : itemSize)
+ * window()->effectiveDevicePixelRatio();
+ node->setTextureSize(textureSize);
+ }
node->setPreferredRenderTarget(d->renderTarget);
node->setFastFBOResizing(d->performanceHints & FastFBOResizing);
- node->setSize(QSize(qRound(br.width()), qRound(br.height())));
node->setSmoothPainting(d->antialiasing);
node->setLinearFiltering(d->smooth);
node->setMipmapping(d->mipmap);
node->setOpaquePainting(d->opaquePainting);
node->setFillColor(d->fillColor);
- node->setContentsScale(d->contentsScale);
node->setDirty(d->dirtyRect);
node->update();
@@ -583,6 +638,13 @@ bool QQuickPaintedItem::isTextureProvider() const
*/
QSGTextureProvider *QQuickPaintedItem::textureProvider() const
{
+ // When Item::layer::enabled == true, QQuickItem will be a texture
+ // provider. In this case we should prefer to return the layer rather
+ // than the image itself. The layer will include any children and any
+ // the image's wrap and fill mode.
+ if (QQuickItem::isTextureProvider())
+ return QQuickItem::textureProvider();
+
Q_D(const QQuickPaintedItem);
QQuickWindow *w = window();
if (!w || !w->openglContext() || QThread::currentThread() != w->openglContext()->thread()) {
diff --git a/src/quick/items/qquickpainteditem.h b/src/quick/items/qquickpainteditem.h
index 356e4a46f6..8c9ae2eebb 100644
--- a/src/quick/items/qquickpainteditem.h
+++ b/src/quick/items/qquickpainteditem.h
@@ -43,12 +43,13 @@ class QQuickPaintedItemPrivate;
class Q_QUICK_EXPORT QQuickPaintedItem : public QQuickItem
{
Q_OBJECT
- Q_ENUMS(RenderTarget)
Q_PROPERTY(QSize contentsSize READ contentsSize WRITE setContentsSize NOTIFY contentsSizeChanged)
Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor NOTIFY fillColorChanged)
Q_PROPERTY(qreal contentsScale READ contentsScale WRITE setContentsScale NOTIFY contentsScaleChanged)
Q_PROPERTY(RenderTarget renderTarget READ renderTarget WRITE setRenderTarget NOTIFY renderTargetChanged)
+ Q_PROPERTY(QSize textureSize READ textureSize WRITE setTextureSize NOTIFY textureSizeChanged)
+
public:
QQuickPaintedItem(QQuickItem *parent = 0);
virtual ~QQuickPaintedItem();
@@ -58,6 +59,7 @@ public:
FramebufferObject,
InvertedYFramebufferObject
};
+ Q_ENUM(RenderTarget)
enum PerformanceHint {
FastFBOResizing = 0x1
@@ -88,6 +90,9 @@ public:
qreal contentsScale() const;
void setContentsScale(qreal);
+ QSize textureSize() const;
+ void setTextureSize(const QSize &size);
+
QColor fillColor() const;
void setFillColor(const QColor&);
@@ -104,6 +109,7 @@ Q_SIGNALS:
void contentsSizeChanged();
void contentsScaleChanged();
void renderTargetChanged();
+ void textureSizeChanged();
protected:
QQuickPaintedItem(QQuickPaintedItemPrivate &dd, QQuickItem *parent = 0);
diff --git a/src/quick/items/qquickpainteditem_p.h b/src/quick/items/qquickpainteditem_p.h
index 3712e964f8..d0e4f9481d 100644
--- a/src/quick/items/qquickpainteditem_p.h
+++ b/src/quick/items/qquickpainteditem_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKPAINTEDITEM_P_P_H
#define QQUICKPAINTEDITEM_P_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickitem_p.h"
#include <QtGui/qcolor.h>
@@ -42,7 +53,7 @@ QT_BEGIN_NAMESPACE
class QQuickPaintedItemTextureProvider;
class QSGPainterNode;
-class QQuickPaintedItemPrivate : public QQuickItemPrivate
+class Q_QUICK_PRIVATE_EXPORT QQuickPaintedItemPrivate : public QQuickItemPrivate
{
public:
QQuickPaintedItemPrivate();
@@ -52,6 +63,7 @@ public:
QColor fillColor;
QQuickPaintedItem::RenderTarget renderTarget;
QQuickPaintedItem::PerformanceHints performanceHints;
+ QSize textureSize;
QRect dirtyRect;
diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp
index 58605f79dd..05bf50574c 100644
--- a/src/quick/items/qquickpathview.cpp
+++ b/src/quick/items/qquickpathview.cpp
@@ -98,7 +98,7 @@ QQuickPathViewPrivate::QQuickPathViewPrivate()
, inRefill(false)
, dragMargin(0), deceleration(100), maximumFlickVelocity(QML_FLICK_DEFAULTMAXVELOCITY)
, moveOffset(this, &QQuickPathViewPrivate::setAdjustedOffset), flickDuration(0)
- , firstIndex(-1), pathItems(-1), requestedIndex(-1), cacheSize(0), requestedZ(0)
+ , pathItems(-1), requestedIndex(-1), cacheSize(0), requestedZ(0)
, moveReason(Other), moveDirection(Shortest), attType(0), highlightComponent(0), highlightItem(0)
, moveHighlight(this, &QQuickPathViewPrivate::setHighlightPosition)
, highlightPosition(0)
@@ -447,7 +447,6 @@ void QQuickPathViewPrivate::regenerate()
if (!isValid())
return;
- firstIndex = -1;
updateMappedRange();
q->refill();
}
@@ -754,7 +753,7 @@ void QQuickPathView::setCurrentIndex(int idx)
if (d->modelCount) {
d->createCurrentItem();
if (d->haveHighlightRange && d->highlightRangeMode == QQuickPathView::StrictlyEnforceRange)
- d->snapToIndex(d->currentIndex);
+ d->snapToIndex(d->currentIndex, QQuickPathViewPrivate::SetIndex);
d->currentItemOffset = d->positionOfIndex(d->currentIndex);
d->updateHighlight();
}
@@ -989,7 +988,7 @@ void QQuickPathView::setHighlightRangeMode(HighlightRangeMode mode)
d->regenerate();
int index = d->highlightRangeMode != NoHighlightRange ? d->currentIndex : d->calcCurrentIndex();
if (index >= 0)
- d->snapToIndex(index);
+ d->snapToIndex(index, QQuickPathViewPrivate::Other);
}
emit highlightRangeModeChanged();
}
@@ -1473,7 +1472,7 @@ int QQuickPathView::indexAt(qreal x, qreal y) const
QQuickItem *item = d->items.at(idx);
QPointF p = item->mapFromItem(this, QPointF(x, y));
if (item->contains(p))
- return (d->firstIndex + idx) % d->modelCount;
+ return d->model->indexOf(item, 0);
}
return -1;
@@ -1896,12 +1895,12 @@ void QQuickPathView::refill()
int count = d->pathItems == -1 ? d->modelCount : qMin(d->pathItems, d->modelCount);
// first move existing items and remove items off path
- int idx = d->firstIndex;
- qCDebug(lcItemViewDelegateLifecycle) << "firstIndex" << idx << "currentIndex" << d->currentIndex << "offset" << d->offset;
+ qCDebug(lcItemViewDelegateLifecycle) << "currentIndex" << d->currentIndex << "offset" << d->offset;
QList<QQuickItem*>::iterator it = d->items.begin();
while (it != d->items.end()) {
- qreal pos = d->positionOfIndex(idx);
QQuickItem *item = *it;
+ int idx = d->model->indexOf(item, 0);
+ qreal pos = d->positionOfIndex(idx);
if (lcItemViewDelegateLifecycle().isDebugEnabled()) {
QQuickText *text = qmlobject_cast<QQuickText*>(item);
if (text)
@@ -1923,81 +1922,140 @@ void QQuickPathView::refill()
if (!d->isInBound(pos, d->mappedRange - d->mappedCache, 1.0 + d->mappedCache)) {
qCDebug(lcItemViewDelegateLifecycle) << "release" << idx << "@" << pos << ", !isInBound: lower" << (d->mappedRange - d->mappedCache) << "upper" << (1.0 + d->mappedCache);
d->releaseItem(item);
- if (it == d->items.begin()) {
- if (++d->firstIndex >= d->modelCount) {
- d->firstIndex = 0;
- }
- }
it = d->items.erase(it);
} else {
++it;
}
}
- ++idx;
- if (idx >= d->modelCount)
- idx = 0;
}
- if (!d->items.count())
- d->firstIndex = -1;
-
bool waiting = false;
if (d->modelCount) {
- // add items to beginning and end
+ // add items as needed
if (d->items.count() < count+d->cacheSize) {
- int idx = qRound(d->modelCount - d->offset) % d->modelCount;
+ int endIdx = 0;
+ qreal endPos;
+ int startIdx = 0;
qreal startPos = 0.0;
- if (d->haveHighlightRange && (d->highlightRangeMode != QQuickPathView::NoHighlightRange
- || d->snapMode != QQuickPathView::NoSnap))
- startPos = d->highlightRangeStart;
- if (d->firstIndex >= 0) {
- startPos = d->positionOfIndex(d->firstIndex);
- idx = (d->firstIndex + d->items.count()) % d->modelCount;
+ if (d->items.count()) {
+ //Find the beginning and end, items may not be in sorted order
+ endPos = -1.0;
+ startPos = 2.0;
+
+ for (int i = 0; i < d->items.count(); i++) {
+ int idx = d->model->indexOf(d->items[i], 0);
+ qreal curPos = d->positionOfIndex(idx);
+ if (curPos > endPos) {
+ endPos = curPos;
+ endIdx = idx;
+ }
+
+ if (curPos < startPos) {
+ startPos = curPos;
+ startIdx = idx;
+ }
+ }
+ } else {
+ if (d->haveHighlightRange
+ && (d->highlightRangeMode != QQuickPathView::NoHighlightRange
+ || d->snapMode != QQuickPathView::NoSnap))
+ startPos = d->highlightRangeStart;
+ // With no items, then "end" is just off the top so we populate via append
+ endIdx = (qRound(d->modelCount - d->offset) - 1) % d->modelCount;
+ endPos = d->positionOfIndex(endIdx);
}
- qreal pos = d->positionOfIndex(idx);
- while ((d->isInBound(pos, startPos, 1.0 + d->mappedCache) || !d->items.count()) && d->items.count() < count+d->cacheSize) {
- qCDebug(lcItemViewDelegateLifecycle) << "append" << idx << "@" << pos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count();
- QQuickItem *item = d->getItem(idx, idx+1, pos >= 1.0);
+ //Append
+ int idx = endIdx + 1;
+ if (idx >= d->modelCount)
+ idx = 0;
+ qreal nextPos = d->positionOfIndex(idx);
+ while ((d->isInBound(nextPos, endPos, 1.0 + d->mappedCache) || !d->items.count())
+ && d->items.count() < count+d->cacheSize) {
+ qCDebug(lcItemViewDelegateLifecycle) << "append" << idx << "@" << nextPos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count();
+ QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1.0);
if (!item) {
waiting = true;
break;
}
+ if (d->items.contains(item)) {
+ break; //Otherwise we'd "re-add" it, and get confused
+ }
if (d->currentIndex == idx) {
currentVisible = true;
- d->currentItemOffset = pos;
+ d->currentItemOffset = nextPos;
}
- if (d->items.count() == 0)
- d->firstIndex = idx;
d->items.append(item);
- d->updateItem(item, pos);
+ d->updateItem(item, nextPos);
+ endIdx = idx;
+ endPos = nextPos;
++idx;
if (idx >= d->modelCount)
idx = 0;
- pos = d->positionOfIndex(idx);
+ nextPos = d->positionOfIndex(idx);
}
- idx = d->firstIndex - 1;
+ //Prepend
+ idx = startIdx - 1;
if (idx < 0)
idx = d->modelCount - 1;
- pos = d->positionOfIndex(idx);
- while (!waiting && d->isInBound(pos, d->mappedRange - d->mappedCache, startPos) && d->items.count() < count+d->cacheSize) {
- qCDebug(lcItemViewDelegateLifecycle) << "prepend" << idx << "@" << pos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count();
- QQuickItem *item = d->getItem(idx, idx+1, pos >= 1.0);
+ nextPos = d->positionOfIndex(idx);
+ while (!waiting && d->isInBound(nextPos, d->mappedRange - d->mappedCache, startPos)
+ && d->items.count() < count+d->cacheSize) {
+ qCDebug(lcItemViewDelegateLifecycle) << "prepend" << idx << "@" << nextPos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count();
+ QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1.0);
if (!item) {
waiting = true;
break;
}
+ if (d->items.contains(item)) {
+ break; //Otherwise we'd "re-add" it, and get confused
+ }
if (d->currentIndex == idx) {
currentVisible = true;
- d->currentItemOffset = pos;
+ d->currentItemOffset = nextPos;
}
d->items.prepend(item);
- d->updateItem(item, pos);
- d->firstIndex = idx;
- idx = d->firstIndex - 1;
+ d->updateItem(item, nextPos);
+ startIdx = idx;
+ startPos = nextPos;
+ --idx;
if (idx < 0)
idx = d->modelCount - 1;
- pos = d->positionOfIndex(idx);
+ nextPos = d->positionOfIndex(idx);
+ }
+
+ // In rare cases, when jumping around with pathCount close to modelCount,
+ // new items appear in the middle. This more generic addition iteration handles this
+ // Since this is the rare case, we try append/prepend first and only do this if
+ // there are gaps still left to fill.
+ if (!waiting && d->items.count() < count+d->cacheSize) {
+ qCDebug(lcItemViewDelegateLifecycle) << "Checking for pathview middle inserts, items count was" << d->items.count();
+ idx = startIdx;
+ QQuickItem *lastItem = d->items[0];
+ while (idx != endIdx) {
+ //This gets the reference from the delegate model, and will not re-create
+ QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1.0);
+ if (!item) {
+ waiting = true;
+ break;
+ }
+ if (!d->items.contains(item)) { //We found a hole
+ nextPos = d->positionOfIndex(idx);
+ qCDebug(lcItemViewDelegateLifecycle) << "middle insert" << idx << "@" << nextPos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count();
+ if (d->currentIndex == idx) {
+ currentVisible = true;
+ d->currentItemOffset = nextPos;
+ }
+ int lastListIdx = d->items.indexOf(lastItem);
+ d->items.insert(lastListIdx + 1, item);
+ d->updateItem(item, nextPos);
+ }
+
+ lastItem = item;
+ ++idx;
+ if (idx >= d->modelCount)
+ idx = 0;
+ }
}
}
}
@@ -2128,7 +2186,6 @@ void QQuickPathView::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
d->offset = qmlMod(d->modelCount - d->currentIndex, d->modelCount);
changedOffset = true;
}
- d->firstIndex = -1;
d->updateMappedRange();
d->scheduleLayout();
}
@@ -2185,8 +2242,16 @@ void QQuickPathViewPrivate::createCurrentItem()
{
if (requestedIndex != -1)
return;
- int itemIndex = (currentIndex - firstIndex + modelCount) % modelCount;
- if (itemIndex < items.count()) {
+
+ bool inItems = false;
+ for (int i = 0; i < items.count(); i++) {
+ if (model->indexOf(items[i], 0) == currentIndex) {
+ inItems = true;
+ break;
+ }
+ }
+
+ if (inItems) {
if ((currentItem = getItem(currentIndex, currentIndex))) {
currentItem->setFocus(true);
if (QQuickPathViewAttached *att = attached(currentItem))
@@ -2241,12 +2306,12 @@ void QQuickPathViewPrivate::fixOffset()
if (curr != currentIndex && highlightRangeMode == QQuickPathView::StrictlyEnforceRange)
q->setCurrentIndex(curr);
else
- snapToIndex(curr);
+ snapToIndex(curr, Other);
}
}
}
-void QQuickPathViewPrivate::snapToIndex(int index)
+void QQuickPathViewPrivate::snapToIndex(int index, MovementReason reason)
{
if (!model || modelCount <= 0)
return;
@@ -2256,7 +2321,7 @@ void QQuickPathViewPrivate::snapToIndex(int index)
if (offset == targetOffset)
return;
- moveReason = Other;
+ moveReason = reason;
offsetAdj = 0.0;
tl.reset(moveOffset);
moveOffset.setValue(offset);
diff --git a/src/quick/items/qquickpathview_p.h b/src/quick/items/qquickpathview_p.h
index 8062e07795..0973d65a58 100644
--- a/src/quick/items/qquickpathview_p.h
+++ b/src/quick/items/qquickpathview_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKPATHVIEW_P_H
#define QQUICKPATHVIEW_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickitem.h"
#include <private/qquickpath_p.h>
@@ -78,10 +89,6 @@ class Q_AUTOTEST_EXPORT QQuickPathView : public QQuickItem
Q_PROPERTY(int cacheItemCount READ cacheItemCount WRITE setCacheItemCount NOTIFY cacheItemCountChanged)
- Q_ENUMS(HighlightRangeMode)
- Q_ENUMS(SnapMode)
- Q_ENUMS(PositionMode)
-
public:
QQuickPathView(QQuickItem *parent=0);
virtual ~QQuickPathView();
@@ -105,6 +112,7 @@ public:
QQuickItem *highlightItem();
enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
+ Q_ENUM(HighlightRangeMode)
HighlightRangeMode highlightRangeMode() const;
void setHighlightRangeMode(HighlightRangeMode mode);
@@ -146,10 +154,12 @@ public:
void setCacheItemCount(int);
enum SnapMode { NoSnap, SnapToItem, SnapOneItem };
+ Q_ENUM(SnapMode)
SnapMode snapMode() const;
void setSnapMode(SnapMode mode);
enum PositionMode { Beginning, Center, End, Contain=4, SnapPosition }; // 3 == Visible in other views
+ Q_ENUM(PositionMode)
Q_INVOKABLE void positionViewAtIndex(int index, int mode);
Q_INVOKABLE int indexAt(qreal x, qreal y) const;
Q_INVOKABLE QQuickItem *itemAt(qreal x, qreal y) const;
diff --git a/src/quick/items/qquickpathview_p_p.h b/src/quick/items/qquickpathview_p_p.h
index 35ea8616a5..73e4884424 100644
--- a/src/quick/items/qquickpathview_p_p.h
+++ b/src/quick/items/qquickpathview_p_p.h
@@ -114,7 +114,8 @@ public:
void setAdjustedOffset(qreal offset);
void regenerate();
void updateItem(QQuickItem *, qreal);
- void snapToIndex(int index);
+ enum MovementReason { Other, SetIndex, Mouse };
+ void snapToIndex(int index, MovementReason reason);
QPointF pointNear(const QPointF &point, qreal *nearPercent=0) const;
void addVelocitySample(qreal v);
qreal calcVelocity() const;
@@ -155,7 +156,6 @@ public:
QQuickTimeLine tl;
QQuickTimeLineValueProxy<QQuickPathViewPrivate> moveOffset;
int flickDuration;
- int firstIndex;
int pathItems;
int requestedIndex;
int cacheSize;
@@ -164,7 +164,6 @@ public:
QList<QQuickItem *> itemCache;
QPointer<QQmlInstanceModel> model;
QVariant modelVariant;
- enum MovementReason { Other, SetIndex, Mouse };
MovementReason moveReason;
enum MovementDirection { Shortest, Negative, Positive };
MovementDirection moveDirection;
diff --git a/src/quick/items/qquickpincharea_p.h b/src/quick/items/qquickpincharea_p.h
index d2de59b5d6..d623a70010 100644
--- a/src/quick/items/qquickpincharea_p.h
+++ b/src/quick/items/qquickpincharea_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKPINCHAREA_H
#define QQUICKPINCHAREA_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickitem.h"
QT_BEGIN_NAMESPACE
@@ -42,7 +53,6 @@ class Q_AUTOTEST_EXPORT QQuickPinch : public QObject
{
Q_OBJECT
- Q_ENUMS(Axis)
Q_PROPERTY(QQuickItem *target READ target WRITE setTarget RESET resetTarget)
Q_PROPERTY(qreal minimumScale READ minimumScale WRITE setMinimumScale NOTIFY minimumScaleChanged)
Q_PROPERTY(qreal maximumScale READ maximumScale WRITE setMaximumScale NOTIFY maximumScaleChanged)
@@ -103,6 +113,7 @@ public:
}
enum Axis { NoDrag=0x00, XAxis=0x01, YAxis=0x02, XAndYAxis=0x03, XandYAxis=XAndYAxis };
+ Q_ENUM(Axis)
Axis axis() const { return m_axis; }
void setAxis(Axis a) {
if (a == m_axis)
diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp
index 887d317069..de2596b679 100644
--- a/src/quick/items/qquickpositioners.cpp
+++ b/src/quick/items/qquickpositioners.cpp
@@ -70,6 +70,10 @@ QQuickBasePositioner::PositionedItem::PositionedItem(QQuickItem *i)
, index(-1)
, isNew(false)
, isVisible(true)
+ , topPadding(0)
+ , leftPadding(0)
+ , rightPadding(0)
+ , bottomPadding(0)
{
}
@@ -116,6 +120,13 @@ void QQuickBasePositioner::PositionedItem::startTransition(QQuickItemViewTransit
transitionableItem->startTransition(transitioner, index);
}
+void QQuickBasePositioner::PositionedItem::updatePadding(qreal lp, qreal tp, qreal rp, qreal bp)
+{
+ leftPadding = lp;
+ topPadding = tp;
+ rightPadding = rp;
+ bottomPadding = bp;
+}
QQuickBasePositioner::QQuickBasePositioner(PositionerType at, QQuickItem *parent)
: QQuickImplicitSizeItem(*(new QQuickBasePositionerPrivate), parent)
@@ -388,11 +399,8 @@ void QQuickBasePositioner::prePositioning()
void QQuickBasePositioner::positionItem(qreal x, qreal y, PositionedItem *target)
{
- Q_D(QQuickBasePositioner);
- if ( (target->itemX() != x || target->itemY() != y)
- && d->type == Both) {
+ if ( target->itemX() != x || target->itemY() != y )
target->moveTo(QPointF(x, y));
- }
}
void QQuickBasePositioner::positionItemX(qreal x, PositionedItem *target)
@@ -503,6 +511,185 @@ void QQuickBasePositioner::updateAttachedProperties(QQuickPositionerAttached *sp
}
}
+qreal QQuickBasePositioner::padding() const
+{
+ Q_D(const QQuickBasePositioner);
+ return d->padding();
+}
+
+void QQuickBasePositioner::setPadding(qreal padding)
+{
+ Q_D(QQuickBasePositioner);
+ if (qFuzzyCompare(d->padding(), padding))
+ return;
+
+ d->extra.value().padding = padding;
+ d->setPositioningDirty();
+ emit paddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitTopPadding)
+ emit topPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitLeftPadding)
+ emit leftPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitRightPadding)
+ emit rightPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitBottomPadding)
+ emit bottomPaddingChanged();
+}
+
+void QQuickBasePositioner::resetPadding()
+{
+ setPadding(0);
+}
+
+qreal QQuickBasePositioner::topPadding() const
+{
+ Q_D(const QQuickBasePositioner);
+ if (d->extra.isAllocated() && d->extra->explicitTopPadding)
+ return d->extra->topPadding;
+ return d->padding();
+}
+
+void QQuickBasePositioner::setTopPadding(qreal padding)
+{
+ Q_D(QQuickBasePositioner);
+ d->setTopPadding(padding);
+}
+
+void QQuickBasePositioner::resetTopPadding()
+{
+ Q_D(QQuickBasePositioner);
+ d->setTopPadding(0, true);
+}
+
+qreal QQuickBasePositioner::leftPadding() const
+{
+ Q_D(const QQuickBasePositioner);
+ if (d->extra.isAllocated() && d->extra->explicitLeftPadding)
+ return d->extra->leftPadding;
+ return d->padding();
+}
+
+void QQuickBasePositioner::setLeftPadding(qreal padding)
+{
+ Q_D(QQuickBasePositioner);
+ d->setLeftPadding(padding);
+}
+
+void QQuickBasePositioner::resetLeftPadding()
+{
+ Q_D(QQuickBasePositioner);
+ d->setLeftPadding(0, true);
+}
+
+qreal QQuickBasePositioner::rightPadding() const
+{
+ Q_D(const QQuickBasePositioner);
+ if (d->extra.isAllocated() && d->extra->explicitRightPadding)
+ return d->extra->rightPadding;
+ return d->padding();
+}
+
+void QQuickBasePositioner::setRightPadding(qreal padding)
+{
+ Q_D(QQuickBasePositioner);
+ d->setRightPadding(padding);
+}
+
+void QQuickBasePositioner::resetRightPadding()
+{
+ Q_D(QQuickBasePositioner);
+ d->setRightPadding(0, true);
+}
+
+qreal QQuickBasePositioner::bottomPadding() const
+{
+ Q_D(const QQuickBasePositioner);
+ if (d->extra.isAllocated() && d->extra->explicitBottomPadding)
+ return d->extra->bottomPadding;
+ return d->padding();
+}
+
+void QQuickBasePositioner::setBottomPadding(qreal padding)
+{
+ Q_D(QQuickBasePositioner);
+ d->setBottomPadding(padding);
+}
+
+void QQuickBasePositioner::resetBottomPadding()
+{
+ Q_D(QQuickBasePositioner);
+ d->setBottomPadding(0, true);
+}
+
+QQuickBasePositionerPrivate::ExtraData::ExtraData()
+ : padding(0)
+ , topPadding(0)
+ , leftPadding(0)
+ , rightPadding(0)
+ , bottomPadding(0)
+ , explicitTopPadding(false)
+ , explicitLeftPadding(false)
+ , explicitRightPadding(false)
+ , explicitBottomPadding(false)
+{
+}
+
+void QQuickBasePositionerPrivate::setTopPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickBasePositioner);
+ qreal oldPadding = q->topPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().topPadding = value;
+ extra.value().explicitTopPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ setPositioningDirty();
+ emit q->topPaddingChanged();
+ }
+}
+
+void QQuickBasePositionerPrivate::setLeftPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickBasePositioner);
+ qreal oldPadding = q->leftPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().leftPadding = value;
+ extra.value().explicitLeftPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ setPositioningDirty();
+ emit q->leftPaddingChanged();
+ }
+}
+
+void QQuickBasePositionerPrivate::setRightPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickBasePositioner);
+ qreal oldPadding = q->rightPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().rightPadding = value;
+ extra.value().explicitRightPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ setPositioningDirty();
+ emit q->rightPaddingChanged();
+ }
+}
+
+void QQuickBasePositionerPrivate::setBottomPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickBasePositioner);
+ qreal oldPadding = q->bottomPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().bottomPadding = value;
+ extra.value().explicitBottomPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ setPositioningDirty();
+ emit q->bottomPaddingChanged();
+ }
+}
+
/*!
\qmltype Positioner
\instantiates QQuickPositionerAttached
@@ -640,6 +827,16 @@ void QQuickPositionerAttached::setIsLastItem(bool isLastItem)
\sa Row, Grid, Flow, Positioner, ColumnLayout, {Qt Quick Examples - Positioners}
*/
/*!
+ \since 5.6
+ \qmlproperty real QtQuick::Column::padding
+ \qmlproperty real QtQuick::Column::topPadding
+ \qmlproperty real QtQuick::Column::leftPadding
+ \qmlproperty real QtQuick::Column::bottomPadding
+ \qmlproperty real QtQuick::Column::rightPadding
+
+ These properties hold the padding around the content.
+*/
+/*!
\qmlproperty Transition QtQuick::Column::populate
This property holds the transition to be run for items that are part of
@@ -715,20 +912,23 @@ QQuickColumn::QQuickColumn(QQuickItem *parent)
void QQuickColumn::doPositioning(QSizeF *contentSize)
{
//Precondition: All items in the positioned list have a valid item pointer and should be positioned
- qreal voffset = 0;
+ qreal voffset = topPadding();
+ const qreal padding = leftPadding() + rightPadding();
+ contentSize->setWidth(qMax(contentSize->width(), padding));
for (int ii = 0; ii < positionedItems.count(); ++ii) {
PositionedItem &child = positionedItems[ii];
- positionItemY(voffset, &child);
- contentSize->setWidth(qMax(contentSize->width(), child.item->width()));
+ positionItem(child.itemX() + leftPadding() - child.leftPadding, voffset, &child);
+ child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
+ contentSize->setWidth(qMax(contentSize->width(), child.item->width() + padding));
voffset += child.item->height();
voffset += spacing();
}
- if (voffset != 0)//If we positioned any items, undo the spacing from the last item
+ if (voffset - topPadding() != 0)//If we positioned any items, undo the spacing from the last item
voffset -= spacing();
- contentSize->setHeight(voffset);
+ contentSize->setHeight(voffset + bottomPadding());
}
void QQuickColumn::reportConflictingAnchors()
@@ -794,6 +994,16 @@ void QQuickColumn::reportConflictingAnchors()
\sa Column, Grid, Flow, Positioner, RowLayout, {Qt Quick Examples - Positioners}
*/
/*!
+ \since 5.6
+ \qmlproperty real QtQuick::Row::padding
+ \qmlproperty real QtQuick::Row::topPadding
+ \qmlproperty real QtQuick::Row::leftPadding
+ \qmlproperty real QtQuick::Row::bottomPadding
+ \qmlproperty real QtQuick::Row::rightPadding
+
+ These properties hold the padding around the content.
+*/
+/*!
\qmlproperty Transition QtQuick::Row::populate
This property holds the transition to be run for items that are part of
@@ -940,27 +1150,34 @@ void QQuickRow::doPositioning(QSizeF *contentSize)
{
//Precondition: All items in the positioned list have a valid item pointer and should be positioned
QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate* >(QQuickBasePositionerPrivate::get(this));
- qreal hoffset = 0;
+ qreal hoffset1 = leftPadding();
+ qreal hoffset2 = rightPadding();
+ if (!d->isLeftToRight())
+ qSwap(hoffset1, hoffset2);
+ qreal hoffset = hoffset1;
+ const qreal padding = topPadding() + bottomPadding();
+ contentSize->setHeight(qMax(contentSize->height(), padding));
QList<qreal> hoffsets;
for (int ii = 0; ii < positionedItems.count(); ++ii) {
PositionedItem &child = positionedItems[ii];
if (d->isLeftToRight()) {
- positionItemX(hoffset, &child);
+ positionItem(hoffset, child.itemY() + topPadding() - child.topPadding, &child);
+ child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
} else {
hoffsets << hoffset;
}
- contentSize->setHeight(qMax(contentSize->height(), child.item->height()));
+ contentSize->setHeight(qMax(contentSize->height(), child.item->height() + padding));
hoffset += child.item->width();
hoffset += spacing();
}
- if (hoffset != 0)//If we positioned any items, undo the extra spacing from the last item
+ if (hoffset - hoffset1 != 0)//If we positioned any items, undo the extra spacing from the last item
hoffset -= spacing();
- contentSize->setWidth(hoffset);
+ contentSize->setWidth(hoffset + hoffset2);
if (d->isLeftToRight())
return;
@@ -976,7 +1193,8 @@ void QQuickRow::doPositioning(QSizeF *contentSize)
for (int ii = 0; ii < positionedItems.count(); ++ii) {
PositionedItem &child = positionedItems[ii];
hoffset = end - hoffsets[acc++] - child.item->width();
- positionItemX(hoffset, &child);
+ positionItem(hoffset, child.itemY() + topPadding() - child.topPadding, &child);
+ child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
}
}
@@ -1044,6 +1262,16 @@ void QQuickRow::reportConflictingAnchors()
\sa Flow, Row, Column, Positioner, GridLayout, {Qt Quick Examples - Positioners}
*/
/*!
+ \since 5.6
+ \qmlproperty real QtQuick::Grid::padding
+ \qmlproperty real QtQuick::Grid::topPadding
+ \qmlproperty real QtQuick::Grid::leftPadding
+ \qmlproperty real QtQuick::Grid::bottomPadding
+ \qmlproperty real QtQuick::Grid::rightPadding
+
+ These properties hold the padding around the content.
+*/
+/*!
\qmlproperty Transition QtQuick::Grid::populate
This property holds the transition to be run for items that are part of
@@ -1423,8 +1651,11 @@ void QQuickGrid::doPositioning(QSizeF *contentSize)
c = (numVisible+(m_rows-1))/m_rows;
}
- if (r == 0 || c == 0)
- return; //Nothing to do
+ if (r == 0 || c == 0) {
+ contentSize->setHeight(topPadding() + bottomPadding());
+ contentSize->setWidth(leftPadding() + rightPadding());
+ return; //Nothing else to do
+ }
QList<qreal> maxColWidth;
QList<qreal> maxRowHeight;
@@ -1476,6 +1707,7 @@ void QQuickGrid::doPositioning(QSizeF *contentSize)
widthSum += columnSpacing;
widthSum += maxColWidth[j];
}
+ widthSum += leftPadding() + rightPadding();
qreal heightSum = 0;
for (int i = 0; i < maxRowHeight.size(); i++) {
@@ -1483,6 +1715,7 @@ void QQuickGrid::doPositioning(QSizeF *contentSize)
heightSum += rowSpacing;
heightSum += maxRowHeight[i];
}
+ heightSum += topPadding() + bottomPadding();
contentSize->setHeight(heightSum);
contentSize->setWidth(widthSum);
@@ -1493,10 +1726,10 @@ void QQuickGrid::doPositioning(QSizeF *contentSize)
else
end = widthSum;
- qreal xoffset = 0;
+ qreal xoffset = leftPadding();
if (!d->isLeftToRight())
- xoffset = end;
- qreal yoffset = 0;
+ xoffset = end - rightPadding();
+ qreal yoffset = topPadding();
int curRow =0;
int curCol =0;
for (int i = 0; i < positionedItems.count(); ++i) {
@@ -1518,6 +1751,7 @@ void QQuickGrid::doPositioning(QSizeF *contentSize)
alignYOffset += maxRowHeight[curRow] - child.item->height();
positionItem(childXOffset, alignYOffset, &child);
+ child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
if (m_flow == LeftToRight) {
if (d->isLeftToRight())
@@ -1529,9 +1763,9 @@ void QQuickGrid::doPositioning(QSizeF *contentSize)
if (!curCol) {
yoffset += maxRowHeight[curRow]+rowSpacing;
if (d->isLeftToRight())
- xoffset = 0;
+ xoffset = leftPadding();
else
- xoffset = end;
+ xoffset = end - rightPadding();
curRow++;
if (curRow>=r)
break;
@@ -1545,7 +1779,7 @@ void QQuickGrid::doPositioning(QSizeF *contentSize)
xoffset += maxColWidth[curCol]+columnSpacing;
else
xoffset -= maxColWidth[curCol]+columnSpacing;
- yoffset = 0;
+ yoffset = topPadding();
curCol++;
if (curCol>=c)
break;
@@ -1603,6 +1837,16 @@ void QQuickGrid::reportConflictingAnchors()
\sa Column, Row, Grid, Positioner, {Qt Quick Examples - Positioners}
*/
/*!
+ \since 5.6
+ \qmlproperty real QtQuick::Flow::padding
+ \qmlproperty real QtQuick::Flow::topPadding
+ \qmlproperty real QtQuick::Flow::leftPadding
+ \qmlproperty real QtQuick::Flow::bottomPadding
+ \qmlproperty real QtQuick::Flow::rightPadding
+
+ These properties hold the padding around the content.
+*/
+/*!
\qmlproperty Transition QtQuick::Flow::populate
This property holds the transition to be run for items that are part of
@@ -1786,23 +2030,30 @@ void QQuickFlow::doPositioning(QSizeF *contentSize)
//Precondition: All items in the positioned list have a valid item pointer and should be positioned
Q_D(QQuickFlow);
- qreal hoffset = 0;
- qreal voffset = 0;
+ qreal hoffset1 = leftPadding();
+ qreal hoffset2 = rightPadding();
+ if (!d->isLeftToRight())
+ qSwap(hoffset1, hoffset2);
+ qreal hoffset = hoffset1;
+ const qreal voffset1 = topPadding();
+ qreal voffset = voffset1;
qreal linemax = 0;
QList<qreal> hoffsets;
+ contentSize->setWidth(qMax(contentSize->width(), hoffset1 + hoffset2));
+ contentSize->setHeight(qMax(contentSize->height(), voffset + bottomPadding()));
for (int i = 0; i < positionedItems.count(); ++i) {
PositionedItem &child = positionedItems[i];
if (d->flow == LeftToRight) {
- if (widthValid() && hoffset && hoffset + child.item->width() > width()) {
- hoffset = 0;
+ if (widthValid() && hoffset != hoffset1 && hoffset + child.item->width() + hoffset2 > width()) {
+ hoffset = hoffset1;
voffset += linemax + spacing();
linemax = 0;
}
} else {
- if (heightValid() && voffset && voffset + child.item->height() > height()) {
- voffset = 0;
+ if (heightValid() && voffset != voffset1 && voffset + child.item->height() + bottomPadding() > height()) {
+ voffset = voffset1;
hoffset += linemax + spacing();
linemax = 0;
}
@@ -1810,13 +2061,16 @@ void QQuickFlow::doPositioning(QSizeF *contentSize)
if (d->isLeftToRight()) {
positionItem(hoffset, voffset, &child);
+ child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
} else {
hoffsets << hoffset;
positionItemY(voffset, &child);
+ child.topPadding = topPadding();
+ child.bottomPadding = bottomPadding();
}
- contentSize->setWidth(qMax(contentSize->width(), hoffset + child.item->width()));
- contentSize->setHeight(qMax(contentSize->height(), voffset + child.item->height()));
+ contentSize->setWidth(qMax(contentSize->width(), hoffset + child.item->width() + hoffset2));
+ contentSize->setHeight(qMax(contentSize->height(), voffset + child.item->height() + bottomPadding()));
if (d->flow == LeftToRight) {
hoffset += child.item->width();
@@ -1828,6 +2082,7 @@ void QQuickFlow::doPositioning(QSizeF *contentSize)
linemax = qMax(linemax, child.item->width());
}
}
+
if (d->isLeftToRight())
return;
@@ -1841,6 +2096,8 @@ void QQuickFlow::doPositioning(QSizeF *contentSize)
PositionedItem &child = positionedItems[i];
hoffset = end - hoffsets[acc++] - child.item->width();
positionItemX(hoffset, &child);
+ child.leftPadding = leftPadding();
+ child.rightPadding = rightPadding();
}
}
diff --git a/src/quick/items/qquickpositioners_p.h b/src/quick/items/qquickpositioners_p.h
index ea779695eb..fca64b0a22 100644
--- a/src/quick/items/qquickpositioners_p.h
+++ b/src/quick/items/qquickpositioners_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKPOSITIONERS_P_H
#define QQUICKPOSITIONERS_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickimplicitsizeitem_p.h"
#include "qquickitemviewtransition_p.h"
@@ -86,6 +97,12 @@ class Q_QUICK_PRIVATE_EXPORT QQuickBasePositioner : public QQuickImplicitSizeIte
Q_PROPERTY(QQuickTransition *populate READ populate WRITE setPopulate NOTIFY populateChanged)
Q_PROPERTY(QQuickTransition *move READ move WRITE setMove NOTIFY moveChanged)
Q_PROPERTY(QQuickTransition *add READ add WRITE setAdd NOTIFY addChanged)
+
+ Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6)
+ Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6)
+ Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6)
+ Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6)
+ Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6)
public:
enum PositionerType { None = 0x0, Horizontal = 0x1, Vertical = 0x2, Both = 0x3 };
@@ -108,6 +125,26 @@ public:
void updateAttachedProperties(QQuickPositionerAttached *specificProperty = 0, QQuickItem *specificPropertyOwner = 0) const;
+ qreal padding() const;
+ void setPadding(qreal padding);
+ void resetPadding();
+
+ qreal topPadding() const;
+ void setTopPadding(qreal padding);
+ void resetTopPadding();
+
+ qreal leftPadding() const;
+ void setLeftPadding(qreal padding);
+ void resetLeftPadding();
+
+ qreal rightPadding() const;
+ void setRightPadding(qreal padding);
+ void resetRightPadding();
+
+ qreal bottomPadding() const;
+ void setBottomPadding(qreal padding);
+ void resetBottomPadding();
+
protected:
QQuickBasePositioner(QQuickBasePositionerPrivate &dd, PositionerType at, QQuickItem *parent);
void componentComplete() Q_DECL_OVERRIDE;
@@ -120,6 +157,11 @@ Q_SIGNALS:
void populateChanged();
void moveChanged();
void addChanged();
+ Q_REVISION(6) void paddingChanged();
+ Q_REVISION(6) void topPaddingChanged();
+ Q_REVISION(6) void leftPaddingChanged();
+ Q_REVISION(6) void rightPaddingChanged();
+ Q_REVISION(6) void bottomPaddingChanged();
protected Q_SLOTS:
void prePositioning();
@@ -144,11 +186,18 @@ protected:
bool prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds);
void startTransition(QQuickItemViewTransitioner *transitioner);
+ void updatePadding(qreal lp, qreal tp, qreal rp, qreal bp);
+
QQuickItem *item;
QQuickItemViewTransitionableItem *transitionableItem;
int index;
bool isNew;
bool isVisible;
+
+ qreal topPadding;
+ qreal leftPadding;
+ qreal rightPadding;
+ qreal bottomPadding;
};
QPODVector<PositionedItem,8> positionedItems;
@@ -236,8 +285,8 @@ public:
void setColumnSpacing(qreal);
void resetColumnSpacing() { m_useColumnSpacing = false; }
- Q_ENUMS(Flow)
enum Flow { LeftToRight, TopToBottom };
+ Q_ENUM(Flow)
Flow flow() const;
void setFlow(Flow);
@@ -245,14 +294,14 @@ public:
void setLayoutDirection (Qt::LayoutDirection);
Qt::LayoutDirection effectiveLayoutDirection() const;
- Q_ENUMS(HAlignment)
- Q_ENUMS(VAlignment)
enum HAlignment { AlignLeft = Qt::AlignLeft,
AlignRight = Qt::AlignRight,
AlignHCenter = Qt::AlignHCenter};
+ Q_ENUM(HAlignment)
enum VAlignment { AlignTop = Qt::AlignTop,
AlignBottom = Qt::AlignBottom,
AlignVCenter = Qt::AlignVCenter };
+ Q_ENUM(VAlignment)
HAlignment hItemAlign() const;
void setHItemAlign(HAlignment align);
@@ -301,8 +350,8 @@ class Q_AUTOTEST_EXPORT QQuickFlow: public QQuickBasePositioner
public:
QQuickFlow(QQuickItem *parent=0);
- Q_ENUMS(Flow)
enum Flow { LeftToRight, TopToBottom };
+ Q_ENUM(Flow)
Flow flow() const;
void setFlow(Flow);
diff --git a/src/quick/items/qquickpositioners_p_p.h b/src/quick/items/qquickpositioners_p_p.h
index 3a8fe20351..6e1e15d4ef 100644
--- a/src/quick/items/qquickpositioners_p_p.h
+++ b/src/quick/items/qquickpositioners_p_p.h
@@ -51,6 +51,7 @@
#include <QtQuick/private/qquickstate_p.h>
#include <private/qquicktransitionmanager_p_p.h>
#include <private/qquickstatechangescript_p.h>
+#include <private/qlazilyallocated_p.h>
#include <QtCore/qobject.h>
#include <QtCore/qstring.h>
@@ -65,10 +66,26 @@ class QQuickBasePositionerPrivate : public QQuickImplicitSizeItemPrivate, public
Q_DECLARE_PUBLIC(QQuickBasePositioner)
public:
+ struct ExtraData {
+ ExtraData();
+
+ qreal padding;
+ qreal topPadding;
+ qreal leftPadding;
+ qreal rightPadding;
+ qreal bottomPadding;
+ bool explicitTopPadding : 1;
+ bool explicitLeftPadding : 1;
+ bool explicitRightPadding : 1;
+ bool explicitBottomPadding : 1;
+ };
+ QLazilyAllocated<ExtraData> extra;
+
QQuickBasePositionerPrivate()
: spacing(0), type(QQuickBasePositioner::None)
, transitioner(0), positioningDirty(false)
, doingPositioning(false), anchorConflict(false), layoutDirection(Qt::LeftToRight)
+
{
}
@@ -149,6 +166,12 @@ public:
virtual void effectiveLayoutDirectionChange()
{
}
+
+ inline qreal padding() const { return extra.isAllocated() ? extra->padding : 0.0; }
+ void setTopPadding(qreal value, bool reset = false);
+ void setLeftPadding(qreal value, bool reset = false);
+ void setRightPadding(qreal value, bool reset = false);
+ void setBottomPadding(qreal value, bool reset = false);
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickrectangle_p.h b/src/quick/items/qquickrectangle_p.h
index 8a00dbaf92..7cd4868f4a 100644
--- a/src/quick/items/qquickrectangle_p.h
+++ b/src/quick/items/qquickrectangle_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKRECTANGLE_P_H
#define QQUICKRECTANGLE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickitem.h"
#include <QtGui/qbrush.h>
@@ -42,7 +53,7 @@
QT_BEGIN_NAMESPACE
-class Q_AUTOTEST_EXPORT QQuickPen : public QObject
+class Q_QUICK_PRIVATE_EXPORT QQuickPen : public QObject
{
Q_OBJECT
@@ -125,7 +136,7 @@ private:
};
class QQuickRectanglePrivate;
-class Q_AUTOTEST_EXPORT QQuickRectangle : public QQuickItem
+class Q_QUICK_PRIVATE_EXPORT QQuickRectangle : public QQuickItem
{
Q_OBJECT
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
index 6b0b9c3a06..d00b02c005 100644
--- a/src/quick/items/qquickrendercontrol.cpp
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -46,7 +46,6 @@
#include <QtQuick/QQuickWindow>
#include <QtQuick/private/qquickwindow_p.h>
-#include <private/qqmlprofilerservice_p.h>
#include <QtCore/private/qobject_p.h>
QT_BEGIN_NAMESPACE
@@ -130,11 +129,6 @@ QQuickRenderControlPrivate::QQuickRenderControlPrivate()
rc = new QSGRenderContext(sg);
}
-QQuickRenderControlPrivate::~QQuickRenderControlPrivate()
-{
- delete rc;
-}
-
void QQuickRenderControlPrivate::cleanup()
{
delete sg;
@@ -163,13 +157,25 @@ QQuickRenderControl::~QQuickRenderControl()
if (d->window)
QQuickWindowPrivate::get(d->window)->renderControl = 0;
+
+ // It is likely that the cleanup in windowDestroyed() is not called since
+ // the standard pattern is to destroy the rendercontrol before the QQuickWindow.
+ // Do it here.
+ d->windowDestroyed();
+
+ delete d->rc;
}
void QQuickRenderControlPrivate::windowDestroyed()
{
- if (window == 0) {
+ if (window) {
rc->invalidate();
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+
+ delete QQuickWindowPrivate::get(window)->animationController;
+ QQuickWindowPrivate::get(window)->animationController = 0;
+
+ window = 0;
}
}
diff --git a/src/quick/items/qquickrendercontrol_p.h b/src/quick/items/qquickrendercontrol_p.h
index 8837ed79dc..6fe475bb93 100644
--- a/src/quick/items/qquickrendercontrol_p.h
+++ b/src/quick/items/qquickrendercontrol_p.h
@@ -56,7 +56,6 @@ public:
Q_DECLARE_PUBLIC(QQuickRenderControl)
QQuickRenderControlPrivate();
- ~QQuickRenderControlPrivate();
static QQuickRenderControlPrivate *get(QQuickRenderControl *renderControl) {
return renderControl->d_func();
diff --git a/src/quick/items/qquickrepeater.cpp b/src/quick/items/qquickrepeater.cpp
index 0168d73c8f..30fd98a63c 100644
--- a/src/quick/items/qquickrepeater.cpp
+++ b/src/quick/items/qquickrepeater.cpp
@@ -50,6 +50,7 @@ QQuickRepeaterPrivate::QQuickRepeaterPrivate()
, delegateValidated(false)
, itemCount(0)
{
+ setTransparentForPositioner(true);
}
QQuickRepeaterPrivate::~QQuickRepeaterPrivate()
@@ -199,11 +200,12 @@ void QQuickRepeater::setModel(const QVariant &m)
clear();
if (d->model) {
- disconnect(d->model, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
- this, SLOT(modelUpdated(QQmlChangeSet,bool)));
- disconnect(d->model, SIGNAL(createdItem(int,QObject*)), this, SLOT(createdItem(int,QObject*)));
- disconnect(d->model, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
-// disconnect(d->model, SIGNAL(destroyingItem(QObject*)), this, SLOT(destroyingItem(QObject*)));
+ qmlobject_disconnect(d->model, QQmlInstanceModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
+ this, QQuickRepeater, SLOT(modelUpdated(QQmlChangeSet,bool)));
+ qmlobject_disconnect(d->model, QQmlInstanceModel, SIGNAL(createdItem(int,QObject*)),
+ this, QQuickRepeater, SLOT(createdItem(int,QObject*)));
+ qmlobject_disconnect(d->model, QQmlInstanceModel, SIGNAL(initItem(int,QObject*)),
+ this, QQuickRepeater, SLOT(initItem(int,QObject*)));
}
d->dataSource = model;
QObject *object = qvariant_cast<QObject*>(model);
@@ -227,11 +229,12 @@ void QQuickRepeater::setModel(const QVariant &m)
dataModel->setModel(model);
}
if (d->model) {
- connect(d->model, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
- this, SLOT(modelUpdated(QQmlChangeSet,bool)));
- connect(d->model, SIGNAL(createdItem(int,QObject*)), this, SLOT(createdItem(int,QObject*)));
- connect(d->model, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
-// connect(d->model, SIGNAL(destroyingItem(QObject*)), this, SLOT(destroyingItem(QObject*)));
+ qmlobject_connect(d->model, QQmlInstanceModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
+ this, QQuickRepeater, SLOT(modelUpdated(QQmlChangeSet,bool)));
+ qmlobject_connect(d->model, QQmlInstanceModel, SIGNAL(createdItem(int,QObject*)),
+ this, QQuickRepeater, SLOT(createdItem(int,QObject*)));
+ qmlobject_connect(d->model, QQmlInstanceModel, SIGNAL(initItem(int,QObject*)),
+ this, QQuickRepeater, SLOT(initItem(int,QObject*)));
regenerate();
}
emit modelChanged();
@@ -360,8 +363,8 @@ void QQuickRepeater::clear()
if (QQuickItem *item = d->deletables.at(i)) {
if (complete)
emit itemRemoved(i, item);
- item->setParentItem(0);
d->model->release(item);
+ item->setParentItem(0);
}
}
}
@@ -397,9 +400,17 @@ void QQuickRepeaterPrivate::requestItems()
void QQuickRepeater::createdItem(int index, QObject *)
{
Q_D(QQuickRepeater);
+ QObject *object = d->model->object(index, false);
+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
+ emit itemAdded(index, item);
+}
+
+void QQuickRepeater::initItem(int index, QObject *object)
+{
+ Q_D(QQuickRepeater);
+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
+
if (!d->deletables.at(index)) {
- QObject *object = d->model->object(index, false);
- QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
if (!item) {
if (object) {
d->model->release(object);
@@ -425,17 +436,9 @@ void QQuickRepeater::createdItem(int index, QObject *)
}
item->stackBefore(after);
}
- emit itemAdded(index, item);
}
}
-void QQuickRepeater::initItem(int, QObject *object)
-{
- QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
- if (item)
- item->setParentItem(parentItem());
-}
-
void QQuickRepeater::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
{
Q_D(QQuickRepeater);
@@ -465,8 +468,8 @@ void QQuickRepeater::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
d->deletables.remove(index);
emit itemRemoved(index, item);
if (item) {
- item->setParentItem(0);
d->model->release(item);
+ item->setParentItem(0);
}
--d->itemCount;
}
diff --git a/src/quick/items/qquickrepeater_p.h b/src/quick/items/qquickrepeater_p.h
index 5f652da975..c0a0a32f5f 100644
--- a/src/quick/items/qquickrepeater_p.h
+++ b/src/quick/items/qquickrepeater_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKREPEATER_P_H
#define QQUICKREPEATER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickitem.h"
QT_BEGIN_NAMESPACE
diff --git a/src/quick/items/qquickscalegrid_p_p.h b/src/quick/items/qquickscalegrid_p_p.h
index 7e0c021c19..1d067f1a94 100644
--- a/src/quick/items/qquickscalegrid_p_p.h
+++ b/src/quick/items/qquickscalegrid_p_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKSCALEGRID_P_P_H
#define QQUICKSCALEGRID_P_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickborderimage_p.h"
#include <QtQml/qqml.h>
@@ -47,7 +58,6 @@ QT_BEGIN_NAMESPACE
class QQuickScaleGrid : public QObject
{
Q_OBJECT
- Q_ENUMS(TileRule)
Q_PROPERTY(int left READ left WRITE setLeft NOTIFY borderChanged)
Q_PROPERTY(int top READ top WRITE setTop NOTIFY borderChanged)
diff --git a/src/quick/items/qquickscreen_p.h b/src/quick/items/qquickscreen_p.h
index 266f7bfed8..d8c8cbde2f 100644
--- a/src/quick/items/qquickscreen_p.h
+++ b/src/quick/items/qquickscreen_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKSCREEN_P_H
#define QQUICKSCREEN_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include <QRect>
#include <QSize>
diff --git a/src/quick/items/qquickshadereffect_p.h b/src/quick/items/qquickshadereffect_p.h
index 1c60d9feaa..a5e993ee0c 100644
--- a/src/quick/items/qquickshadereffect_p.h
+++ b/src/quick/items/qquickshadereffect_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKSHADEREFFECT_P_H
#define QQUICKSHADEREFFECT_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuick/qquickitem.h>
#include <QtQuick/qsgmaterial.h>
@@ -92,8 +103,6 @@ class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffect : public QQuickItem
Q_PROPERTY(QString log READ log NOTIFY logChanged)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(bool supportsAtlasTextures READ supportsAtlasTextures WRITE setSupportsAtlasTextures NOTIFY supportsAtlasTexturesChanged REVISION 1)
- Q_ENUMS(CullMode)
- Q_ENUMS(Status)
public:
enum CullMode
@@ -102,6 +111,7 @@ public:
BackFaceCulling = QQuickShaderEffectMaterial::BackFaceCulling,
FrontFaceCulling = QQuickShaderEffectMaterial::FrontFaceCulling
};
+ Q_ENUM(CullMode)
enum Status
{
@@ -109,6 +119,7 @@ public:
Uncompiled,
Error
};
+ Q_ENUM(Status)
QQuickShaderEffect(QQuickItem *parent = 0);
~QQuickShaderEffect();
diff --git a/src/quick/items/qquickshadereffectmesh_p.h b/src/quick/items/qquickshadereffectmesh_p.h
index b392753bf8..eb0f03ea81 100644
--- a/src/quick/items/qquickshadereffectmesh_p.h
+++ b/src/quick/items/qquickshadereffectmesh_p.h
@@ -43,6 +43,17 @@
#ifndef QQUICKSHADEREFFECTMESH_P_H
#define QQUICKSHADEREFFECTMESH_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
QT_BEGIN_NAMESPACE
class QSGGeometry;
diff --git a/src/quick/items/qquickshadereffectnode.cpp b/src/quick/items/qquickshadereffectnode.cpp
index be6ecfae18..081e572e3b 100644
--- a/src/quick/items/qquickshadereffectnode.cpp
+++ b/src/quick/items/qquickshadereffectnode.cpp
@@ -83,7 +83,9 @@ QQuickCustomMaterialShader::QQuickCustomMaterialShader(const QQuickShaderEffectM
, m_compiled(false)
, m_initialized(false)
{
- for (int i = 0; i < m_attributes.count(); ++i)
+ const int attributesCount = m_attributes.count();
+ m_attributeNames.reserve(attributesCount + 1);
+ for (int i = 0; i < attributesCount; ++i)
m_attributeNames.append(m_attributes.at(i).constData());
m_attributeNames.append(0);
}
@@ -458,7 +460,7 @@ void QQuickShaderEffectMaterial::updateTextures() const
{
for (int i = 0; i < textureProviders.size(); ++i) {
if (QSGTextureProvider *provider = textureProviders.at(i)) {
- if (QSGLayer *texture = qobject_cast<QSGLayer *>(provider->texture()))
+ if (QSGDynamicTexture *texture = qobject_cast<QSGDynamicTexture *>(provider->texture()))
texture->updateTexture();
}
}
diff --git a/src/quick/items/qquickshadereffectnode_p.h b/src/quick/items/qquickshadereffectnode_p.h
index a6a6d1b2fc..76aecd1b04 100644
--- a/src/quick/items/qquickshadereffectnode_p.h
+++ b/src/quick/items/qquickshadereffectnode_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKSHADEREFFECTNODE_P_H
#define QQUICKSHADEREFFECTNODE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuick/qsgnode.h>
#include <QtQuick/qsgmaterial.h>
#include <QtQuick/qsgtextureprovider.h>
diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp
index bf69fe4277..2effc0d0ae 100644
--- a/src/quick/items/qquickshadereffectsource.cpp
+++ b/src/quick/items/qquickshadereffectsource.cpp
@@ -189,6 +189,7 @@ QQuickShaderEffectSource::QQuickShaderEffectSource(QQuickItem *parent)
, m_mipmap(false)
, m_recursive(false)
, m_grab(true)
+ , m_textureMirroring(MirrorVertically)
{
setFlag(ItemHasContents);
}
@@ -543,6 +544,37 @@ void QQuickShaderEffectSource::setRecursive(bool enabled)
}
/*!
+ \qmlproperty enumeration QtQuick::ShaderEffectSource::textureMirroring
+ \since 5.6
+
+ This property defines how the generated OpenGL texture should be mirrored.
+ The default value is \c{ShaderEffectSource.MirrorVertically}.
+ Custom mirroring can be useful if the generated texture is directly accessed by custom shaders,
+ such as those specified by ShaderEffect. Mirroring has no effect on the UI representation of
+ the ShaderEffectSource item itself.
+
+ \list
+ \li ShaderEffectSource.NoMirroring - No mirroring
+ \li ShaderEffectSource.MirrorHorizontally - The generated texture is flipped along X-axis.
+ \li ShaderEffectSource.MirrorVertically - The generated texture is flipped along Y-axis.
+ \endlist
+*/
+
+QQuickShaderEffectSource::TextureMirroring QQuickShaderEffectSource::textureMirroring() const
+{
+ return QQuickShaderEffectSource::TextureMirroring(m_textureMirroring);
+}
+
+void QQuickShaderEffectSource::setTextureMirroring(TextureMirroring mirroring)
+{
+ if (mirroring == QQuickShaderEffectSource::TextureMirroring(m_textureMirroring))
+ return;
+ m_textureMirroring = mirroring;
+ update();
+ emit textureMirroringChanged();
+}
+
+/*!
\qmlmethod QtQuick::ShaderEffectSource::scheduleUpdate()
Schedules a re-rendering of the texture for the next frame.
@@ -642,6 +674,8 @@ QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaint
m_texture->setRecursive(m_recursive);
m_texture->setFormat(GLenum(m_format));
m_texture->setHasMipmaps(m_mipmap);
+ m_texture->setMirrorHorizontal(m_textureMirroring & MirrorHorizontally);
+ m_texture->setMirrorVertical(m_textureMirroring & MirrorVertically);
if (m_grab)
m_texture->scheduleUpdate();
diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h
index 31e503be42..c9d50cef9e 100644
--- a/src/quick/items/qquickshadereffectsource_p.h
+++ b/src/quick/items/qquickshadereffectsource_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKSHADEREFFECTSOURCE_P_H
#define QQUICKSHADEREFFECTSOURCE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickitem.h"
#include <QtQuick/qsgtextureprovider.h>
#include <private/qsgadaptationlayer_p.h>
@@ -66,8 +77,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffectSource : public QQuickItem, publi
Q_PROPERTY(bool hideSource READ hideSource WRITE setHideSource NOTIFY hideSourceChanged)
Q_PROPERTY(bool mipmap READ mipmap WRITE setMipmap NOTIFY mipmapChanged)
Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged)
+ Q_PROPERTY(TextureMirroring textureMirroring READ textureMirroring WRITE setTextureMirroring NOTIFY textureMirroringChanged REVISION 1)
- Q_ENUMS(Format WrapMode)
public:
enum WrapMode {
ClampToEdge,
@@ -75,12 +86,21 @@ public:
RepeatVertically,
Repeat
};
+ Q_ENUM(WrapMode)
enum Format {
Alpha = GL_ALPHA,
RGB = GL_RGB,
RGBA = GL_RGBA
};
+ Q_ENUM(Format)
+
+ enum TextureMirroring {
+ NoMirroring = 0x00,
+ MirrorHorizontally = 0x01,
+ MirrorVertically = 0x02
+ };
+ Q_ENUM(TextureMirroring)
QQuickShaderEffectSource(QQuickItem *parent = 0);
~QQuickShaderEffectSource();
@@ -112,6 +132,9 @@ public:
bool recursive() const;
void setRecursive(bool enabled);
+ TextureMirroring textureMirroring() const;
+ void setTextureMirroring(TextureMirroring mirroring);
+
bool isTextureProvider() const Q_DECL_OVERRIDE { return true; }
QSGTextureProvider *textureProvider() const Q_DECL_OVERRIDE;
@@ -127,6 +150,7 @@ Q_SIGNALS:
void hideSourceChanged();
void mipmapChanged();
void recursiveChanged();
+ void textureMirroringChanged();
void scheduledUpdateCompleted();
@@ -156,6 +180,7 @@ private:
uint m_mipmap : 1;
uint m_recursive : 1;
uint m_grab : 1;
+ uint m_textureMirroring : 2; // Stores TextureMirroring enum
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicksprite_p.h b/src/quick/items/qquicksprite_p.h
index 86350738a0..43c5e44be3 100644
--- a/src/quick/items/qquicksprite_p.h
+++ b/src/quick/items/qquicksprite_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKSPRITE_P_H
#define QQUICKSPRITE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QObject>
#include <QUrl>
#include <QVariantMap>
diff --git a/src/quick/items/qquickspriteengine_p.h b/src/quick/items/qquickspriteengine_p.h
index ef52bcc9fe..48808e73c9 100644
--- a/src/quick/items/qquickspriteengine_p.h
+++ b/src/quick/items/qquickspriteengine_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKSPRITEENGINE_P_H
#define QQUICKSPRITEENGINE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QObject>
#include <QVector>
#include <QTimer>
diff --git a/src/quick/items/qquickspritesequence_p.h b/src/quick/items/qquickspritesequence_p.h
index f5d467580d..54ed2636b2 100644
--- a/src/quick/items/qquickspritesequence_p.h
+++ b/src/quick/items/qquickspritesequence_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKSPRITESEQUENCE_P_H
#define QQUICKSPRITESEQUENCE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuick/QQuickItem>
#include <QTime>
diff --git a/src/quick/items/qquickstateoperations.cpp b/src/quick/items/qquickstateoperations.cpp
index 579919db27..ac7fbc24af 100644
--- a/src/quick/items/qquickstateoperations.cpp
+++ b/src/quick/items/qquickstateoperations.cpp
@@ -358,7 +358,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions()
newBinding->setTarget(property);
QQuickStateAction xa;
xa.property = property;
- xa.toBinding = QQmlAbstractBinding::getPointer(newBinding);
+ xa.toBinding = newBinding;
xa.fromValue = xa.property.read();
xa.deletableToBinding = true;
actions << xa;
@@ -377,7 +377,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions()
newBinding->setTarget(property);
QQuickStateAction ya;
ya.property = property;
- ya.toBinding = QQmlAbstractBinding::getPointer(newBinding);
+ ya.toBinding = newBinding;
ya.fromValue = ya.property.read();
ya.deletableToBinding = true;
actions << ya;
@@ -396,7 +396,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions()
newBinding->setTarget(property);
QQuickStateAction sa;
sa.property = property;
- sa.toBinding = QQmlAbstractBinding::getPointer(newBinding);
+ sa.toBinding = newBinding;
sa.fromValue = sa.property.read();
sa.deletableToBinding = true;
actions << sa;
@@ -415,7 +415,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions()
newBinding->setTarget(property);
QQuickStateAction ra;
ra.property = property;
- ra.toBinding = QQmlAbstractBinding::getPointer(newBinding);
+ ra.toBinding = newBinding;
ra.fromValue = ra.property.read();
ra.deletableToBinding = true;
actions << ra;
@@ -434,7 +434,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions()
newBinding->setTarget(property);
QQuickStateAction wa;
wa.property = property;
- wa.toBinding = QQmlAbstractBinding::getPointer(newBinding);
+ wa.toBinding = newBinding;
wa.fromValue = wa.property.read();
wa.deletableToBinding = true;
actions << wa;
@@ -453,7 +453,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions()
newBinding->setTarget(property);
QQuickStateAction ha;
ha.property = property;
- ha.toBinding = QQmlAbstractBinding::getPointer(newBinding);
+ ha.toBinding = newBinding;
ha.fromValue = ha.property.read();
ha.deletableToBinding = true;
actions << ha;
@@ -482,7 +482,7 @@ void QQuickParentChange::saveOriginals()
saveCurrentValues();
}*/
-void QQuickParentChange::execute(Reason)
+void QQuickParentChange::execute()
{
Q_D(QQuickParentChange);
d->doChange(d->parent);
@@ -493,7 +493,7 @@ bool QQuickParentChange::isReversable()
return true;
}
-void QQuickParentChange::reverse(Reason)
+void QQuickParentChange::reverse()
{
Q_D(QQuickParentChange);
d->doChange(d->origParent, d->origStackBefore);
@@ -765,12 +765,7 @@ class QQuickAnchorChangesPrivate : public QQuickStateOperationPrivate
{
public:
QQuickAnchorChangesPrivate()
- : target(0), anchorSet(new QQuickAnchorSet),
- leftBinding(0), rightBinding(0), hCenterBinding(0),
- topBinding(0), bottomBinding(0), vCenterBinding(0), baselineBinding(0),
- origLeftBinding(0), origRightBinding(0), origHCenterBinding(0),
- origTopBinding(0), origBottomBinding(0), origVCenterBinding(0),
- origBaselineBinding(0)
+ : target(0), anchorSet(new QQuickAnchorSet)
{
}
@@ -779,21 +774,21 @@ public:
QQuickItem *target;
QQuickAnchorSet *anchorSet;
- QQmlBinding *leftBinding;
- QQmlBinding *rightBinding;
- QQmlBinding *hCenterBinding;
- QQmlBinding *topBinding;
- QQmlBinding *bottomBinding;
- QQmlBinding *vCenterBinding;
- QQmlBinding *baselineBinding;
-
- QQmlAbstractBinding *origLeftBinding;
- QQmlAbstractBinding *origRightBinding;
- QQmlAbstractBinding *origHCenterBinding;
- QQmlAbstractBinding *origTopBinding;
- QQmlAbstractBinding *origBottomBinding;
- QQmlAbstractBinding *origVCenterBinding;
- QQmlAbstractBinding *origBaselineBinding;
+ QExplicitlySharedDataPointer<QQmlBinding> leftBinding;
+ QExplicitlySharedDataPointer<QQmlBinding> rightBinding;
+ QExplicitlySharedDataPointer<QQmlBinding> hCenterBinding;
+ QExplicitlySharedDataPointer<QQmlBinding> topBinding;
+ QExplicitlySharedDataPointer<QQmlBinding> bottomBinding;
+ QExplicitlySharedDataPointer<QQmlBinding> vCenterBinding;
+ QExplicitlySharedDataPointer<QQmlBinding> baselineBinding;
+
+ QQmlAbstractBinding::Ptr origLeftBinding;
+ QQmlAbstractBinding::Ptr origRightBinding;
+ QQmlAbstractBinding::Ptr origHCenterBinding;
+ QQmlAbstractBinding::Ptr origTopBinding;
+ QQmlAbstractBinding::Ptr origBottomBinding;
+ QQmlAbstractBinding::Ptr origVCenterBinding;
+ QQmlAbstractBinding::Ptr origBaselineBinding;
QQuickAnchorLine rewindLeft;
QQuickAnchorLine rewindRight;
@@ -831,8 +826,6 @@ public:
qreal origX;
qreal origY;
- QList<QQmlAbstractBinding*> oldBindings;
-
QQmlProperty leftProp;
QQmlProperty rightProp;
QQmlProperty hCenterProp;
@@ -849,29 +842,6 @@ QQuickAnchorChanges::QQuickAnchorChanges(QObject *parent)
QQuickAnchorChanges::~QQuickAnchorChanges()
{
- /*
- if the anchorchanges is active at destruction, any non-active orig
- bindings need to be destroyed
-
- the basic logic is that if both e.g. left and origLeft are present,
- then we are active (otherwise left would have been destroyed), and
- left is in use and origLeft needs to be cleaned up.
- */
- Q_D(QQuickAnchorChanges);
- if (d->leftBinding && d->origLeftBinding)
- d->origLeftBinding->destroy();
- if (d->rightBinding && d->origRightBinding)
- d->origRightBinding->destroy();
- if (d->hCenterBinding && d->origHCenterBinding)
- d->origHCenterBinding->destroy();
- if (d->topBinding && d->origTopBinding)
- d->origTopBinding->destroy();
- if (d->bottomBinding && d->origBottomBinding)
- d->origBottomBinding->destroy();
- if (d->vCenterBinding && d->origVCenterBinding)
- d->origVCenterBinding->destroy();
- if (d->baselineBinding && d->origBaselineBinding)
- d->origBaselineBinding->destroy();
}
QQuickAnchorChanges::ActionList QQuickAnchorChanges::actions()
@@ -967,7 +937,7 @@ void QQuickAnchorChanges::setObject(QQuickItem *target)
\endqml
*/
-void QQuickAnchorChanges::execute(Reason reason)
+void QQuickAnchorChanges::execute()
{
Q_D(QQuickAnchorChanges);
if (!d->target)
@@ -978,94 +948,84 @@ void QQuickAnchorChanges::execute(Reason reason)
if (d->applyOrigLeft) {
if (!d->origLeftBinding)
targetPrivate->anchors()->resetLeft();
- QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding);
+ QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding.data());
}
if (d->applyOrigRight) {
if (!d->origRightBinding)
targetPrivate->anchors()->resetRight();
- QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding);
+ QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding.data());
}
if (d->applyOrigHCenter) {
if (!d->origHCenterBinding)
targetPrivate->anchors()->resetHorizontalCenter();
- QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding);
+ QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding.data());
}
if (d->applyOrigTop) {
if (!d->origTopBinding)
targetPrivate->anchors()->resetTop();
- QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding);
+ QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding.data());
}
if (d->applyOrigBottom) {
if (!d->origBottomBinding)
targetPrivate->anchors()->resetBottom();
- QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding);
+ QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding.data());
}
if (d->applyOrigVCenter) {
if (!d->origVCenterBinding)
targetPrivate->anchors()->resetVerticalCenter();
- QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding);
+ QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding.data());
}
if (d->applyOrigBaseline) {
if (!d->origBaselineBinding)
targetPrivate->anchors()->resetBaseline();
- QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding);
- }
-
- //destroy old bindings
- if (reason == ActualChange) {
- for (int i = 0; i < d->oldBindings.size(); ++i) {
- QQmlAbstractBinding *binding = d->oldBindings.at(i);
- if (binding)
- binding->destroy();
- }
- d->oldBindings.clear();
+ QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding.data());
}
//reset any anchors that have been specified as "undefined"
if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::LeftAnchor) {
targetPrivate->anchors()->resetLeft();
- QQmlPropertyPrivate::setBinding(d->leftProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->leftProp);
}
if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::RightAnchor) {
targetPrivate->anchors()->resetRight();
- QQmlPropertyPrivate::setBinding(d->rightProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->rightProp);
}
if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::HCenterAnchor) {
targetPrivate->anchors()->resetHorizontalCenter();
- QQmlPropertyPrivate::setBinding(d->hCenterProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->hCenterProp);
}
if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::TopAnchor) {
targetPrivate->anchors()->resetTop();
- QQmlPropertyPrivate::setBinding(d->topProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->topProp);
}
if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::BottomAnchor) {
targetPrivate->anchors()->resetBottom();
- QQmlPropertyPrivate::setBinding(d->bottomProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->bottomProp);
}
if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::VCenterAnchor) {
targetPrivate->anchors()->resetVerticalCenter();
- QQmlPropertyPrivate::setBinding(d->vCenterProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->vCenterProp);
}
if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::BaselineAnchor) {
targetPrivate->anchors()->resetBaseline();
- QQmlPropertyPrivate::setBinding(d->baselineProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->baselineProp);
}
//set any anchors that have been specified
if (d->leftBinding)
- QQmlPropertyPrivate::setBinding(d->leftBinding->property(), d->leftBinding);
+ QQmlPropertyPrivate::setBinding(d->leftBinding.data());
if (d->rightBinding)
- QQmlPropertyPrivate::setBinding(d->rightBinding->property(), d->rightBinding);
+ QQmlPropertyPrivate::setBinding(d->rightBinding.data());
if (d->hCenterBinding)
- QQmlPropertyPrivate::setBinding(d->hCenterBinding->property(), d->hCenterBinding);
+ QQmlPropertyPrivate::setBinding(d->hCenterBinding.data());
if (d->topBinding)
- QQmlPropertyPrivate::setBinding(d->topBinding->property(), d->topBinding);
+ QQmlPropertyPrivate::setBinding(d->topBinding.data());
if (d->bottomBinding)
- QQmlPropertyPrivate::setBinding(d->bottomBinding->property(), d->bottomBinding);
+ QQmlPropertyPrivate::setBinding(d->bottomBinding.data());
if (d->vCenterBinding)
- QQmlPropertyPrivate::setBinding(d->vCenterBinding->property(), d->vCenterBinding);
+ QQmlPropertyPrivate::setBinding(d->vCenterBinding.data());
if (d->baselineBinding)
- QQmlPropertyPrivate::setBinding(d->baselineBinding->property(), d->baselineBinding);
+ QQmlPropertyPrivate::setBinding(d->baselineBinding.data());
}
bool QQuickAnchorChanges::isReversable()
@@ -1073,7 +1033,7 @@ bool QQuickAnchorChanges::isReversable()
return true;
}
-void QQuickAnchorChanges::reverse(Reason reason)
+void QQuickAnchorChanges::reverse()
{
Q_D(QQuickAnchorChanges);
if (!d->target)
@@ -1083,69 +1043,48 @@ void QQuickAnchorChanges::reverse(Reason reason)
//reset any anchors set by the state
if (d->leftBinding) {
targetPrivate->anchors()->resetLeft();
- QQmlPropertyPrivate::setBinding(d->leftBinding->property(), 0);
- if (reason == ActualChange) {
- d->leftBinding->destroy(); d->leftBinding = 0;
- }
+ QQmlPropertyPrivate::removeBinding(d->leftBinding.data());
}
if (d->rightBinding) {
targetPrivate->anchors()->resetRight();
- QQmlPropertyPrivate::setBinding(d->rightBinding->property(), 0);
- if (reason == ActualChange) {
- d->rightBinding->destroy(); d->rightBinding = 0;
- }
+ QQmlPropertyPrivate::removeBinding(d->rightBinding.data());
}
if (d->hCenterBinding) {
targetPrivate->anchors()->resetHorizontalCenter();
- QQmlPropertyPrivate::setBinding(d->hCenterBinding->property(), 0);
- if (reason == ActualChange) {
- d->hCenterBinding->destroy(); d->hCenterBinding = 0;
- }
+ QQmlPropertyPrivate::removeBinding(d->hCenterBinding.data());
}
if (d->topBinding) {
targetPrivate->anchors()->resetTop();
- QQmlPropertyPrivate::setBinding(d->topBinding->property(), 0);
- if (reason == ActualChange) {
- d->topBinding->destroy(); d->topBinding = 0;
- }
+ QQmlPropertyPrivate::removeBinding(d->topBinding.data());
}
if (d->bottomBinding) {
targetPrivate->anchors()->resetBottom();
- QQmlPropertyPrivate::setBinding(d->bottomBinding->property(), 0);
- if (reason == ActualChange) {
- d->bottomBinding->destroy(); d->bottomBinding = 0;
- }
+ QQmlPropertyPrivate::removeBinding(d->bottomBinding.data());
}
if (d->vCenterBinding) {
targetPrivate->anchors()->resetVerticalCenter();
- QQmlPropertyPrivate::setBinding(d->vCenterBinding->property(), 0);
- if (reason == ActualChange) {
- d->vCenterBinding->destroy(); d->vCenterBinding = 0;
- }
+ QQmlPropertyPrivate::removeBinding(d->vCenterBinding.data());
}
if (d->baselineBinding) {
targetPrivate->anchors()->resetBaseline();
- QQmlPropertyPrivate::setBinding(d->baselineBinding->property(), 0);
- if (reason == ActualChange) {
- d->baselineBinding->destroy(); d->baselineBinding = 0;
- }
+ QQmlPropertyPrivate::removeBinding(d->baselineBinding.data());
}
//restore previous anchors
if (d->origLeftBinding)
- QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding);
+ QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding.data());
if (d->origRightBinding)
- QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding);
+ QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding.data());
if (d->origHCenterBinding)
- QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding);
+ QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding.data());
if (d->origTopBinding)
- QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding);
+ QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding.data());
if (d->origBottomBinding)
- QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding);
+ QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding.data());
if (d->origVCenterBinding)
- QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding);
+ QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding.data());
if (d->origBaselineBinding)
- QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding);
+ QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding.data());
//restore any absolute geometry changed by the state's anchors
QQuickAnchors::Anchors stateVAnchors = d->anchorSet->d_func()->usedAnchors & QQuickAnchors::Vertical_Mask;
@@ -1289,10 +1228,6 @@ void QQuickAnchorChanges::copyOriginals(QQuickStateActionEvent *other)
d->origX = acp->origX;
d->origY = acp->origY;
- d->oldBindings.clear();
- d->oldBindings << acp->leftBinding << acp->rightBinding << acp->hCenterBinding
- << acp->topBinding << acp->bottomBinding << acp->vCenterBinding << acp->baselineBinding;
-
//clear old values from other
//### could this be generalized for all QQuickStateActionEvents, and called after copyOriginals?
acp->leftBinding = 0;
@@ -1333,31 +1268,31 @@ void QQuickAnchorChanges::clearBindings()
d->anchorSet->d_func()->usedAnchors;
if (d->applyOrigLeft || (combined & QQuickAnchors::LeftAnchor)) {
targetPrivate->anchors()->resetLeft();
- QQmlPropertyPrivate::setBinding(d->leftProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->leftProp);
}
if (d->applyOrigRight || (combined & QQuickAnchors::RightAnchor)) {
targetPrivate->anchors()->resetRight();
- QQmlPropertyPrivate::setBinding(d->rightProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->rightProp);
}
if (d->applyOrigHCenter || (combined & QQuickAnchors::HCenterAnchor)) {
targetPrivate->anchors()->resetHorizontalCenter();
- QQmlPropertyPrivate::setBinding(d->hCenterProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->hCenterProp);
}
if (d->applyOrigTop || (combined & QQuickAnchors::TopAnchor)) {
targetPrivate->anchors()->resetTop();
- QQmlPropertyPrivate::setBinding(d->topProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->topProp);
}
if (d->applyOrigBottom || (combined & QQuickAnchors::BottomAnchor)) {
targetPrivate->anchors()->resetBottom();
- QQmlPropertyPrivate::setBinding(d->bottomProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->bottomProp);
}
if (d->applyOrigVCenter || (combined & QQuickAnchors::VCenterAnchor)) {
targetPrivate->anchors()->resetVerticalCenter();
- QQmlPropertyPrivate::setBinding(d->vCenterProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->vCenterProp);
}
if (d->applyOrigBaseline || (combined & QQuickAnchors::BaselineAnchor)) {
targetPrivate->anchors()->resetBaseline();
- QQmlPropertyPrivate::setBinding(d->baselineProp, 0);
+ QQmlPropertyPrivate::removeBinding(d->baselineProp);
}
}
diff --git a/src/quick/items/qquickstateoperations_p.h b/src/quick/items/qquickstateoperations_p.h
index 8d4231c5fa..f1959fa374 100644
--- a/src/quick/items/qquickstateoperations_p.h
+++ b/src/quick/items/qquickstateoperations_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKSTATEOPERATIONS_P_H
#define QQUICKSTATEOPERATIONS_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickitem.h"
#include "qquickanchors_p.h"
@@ -97,9 +108,9 @@ public:
void saveOriginals() Q_DECL_OVERRIDE;
//virtual void copyOriginals(QQuickStateActionEvent*);
- void execute(Reason reason = ActualChange) Q_DECL_OVERRIDE;
+ void execute() Q_DECL_OVERRIDE;
bool isReversable() Q_DECL_OVERRIDE;
- void reverse(Reason reason = ActualChange) Q_DECL_OVERRIDE;
+ void reverse() Q_DECL_OVERRIDE;
EventType type() const Q_DECL_OVERRIDE;
bool override(QQuickStateActionEvent*other) Q_DECL_OVERRIDE;
void rewind() Q_DECL_OVERRIDE;
@@ -180,9 +191,9 @@ public:
QQuickItem *object() const;
void setObject(QQuickItem *);
- void execute(Reason reason = ActualChange) Q_DECL_OVERRIDE;
+ void execute() Q_DECL_OVERRIDE;
bool isReversable() Q_DECL_OVERRIDE;
- void reverse(Reason reason = ActualChange) Q_DECL_OVERRIDE;
+ void reverse() Q_DECL_OVERRIDE;
EventType type() const Q_DECL_OVERRIDE;
bool override(QQuickStateActionEvent*other) Q_DECL_OVERRIDE;
bool changesBindings() Q_DECL_OVERRIDE;
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index 3129bda7cc..5c436d2074 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -40,6 +40,7 @@
#include "qquicktextnode_p.h"
#include "qquickimage_p_p.h"
#include "qquicktextutil_p.h"
+#include "qquicktextdocument_p.h"
#include <QtQuick/private/qsgtexture_p.h>
@@ -85,7 +86,16 @@ QQuickTextPrivate::QQuickTextPrivate()
}
QQuickTextPrivate::ExtraData::ExtraData()
- : lineHeight(1.0)
+ : padding(0)
+ , topPadding(0)
+ , leftPadding(0)
+ , rightPadding(0)
+ , bottomPadding(0)
+ , explicitTopPadding(false)
+ , explicitLeftPadding(false)
+ , explicitRightPadding(false)
+ , explicitBottomPadding(false)
+ , lineHeight(1.0)
, doc(0)
, minimumPixelSize(12)
, minimumPointSize(12)
@@ -104,180 +114,105 @@ void QQuickTextPrivate::init()
q->setFlag(QQuickItem::ItemHasContents);
}
-QQuickTextDocumentWithImageResources::QQuickTextDocumentWithImageResources(QQuickItem *parent)
-: QTextDocument(parent), outstanding(0)
-{
- setUndoRedoEnabled(false);
- documentLayout()->registerHandler(QTextFormat::ImageObject, this);
- connect(this, SIGNAL(baseUrlChanged(QUrl)), this, SLOT(reset()));
-}
-
-QQuickTextDocumentWithImageResources::~QQuickTextDocumentWithImageResources()
+QQuickTextPrivate::~QQuickTextPrivate()
{
- if (!m_resources.isEmpty())
- qDeleteAll(m_resources);
-}
+ delete elideLayout;
+ delete textLine; textLine = 0;
-QVariant QQuickTextDocumentWithImageResources::loadResource(int type, const QUrl &name)
-{
- QVariant resource = QTextDocument::loadResource(type, name);
- if (resource.isNull() && type == QTextDocument::ImageResource) {
- QQmlContext *context = qmlContext(parent());
- QUrl url = baseUrl().resolved(name);
- QQuickPixmap *p = loadPixmap(context, url);
- resource = p->image();
+ if (extra.isAllocated()) {
+ qDeleteAll(extra->imgTags);
+ extra->imgTags.clear();
}
-
- return resource;
}
-void QQuickTextDocumentWithImageResources::requestFinished()
+qreal QQuickTextPrivate::getImplicitWidth() const
{
- outstanding--;
- if (outstanding == 0) {
- markContentsDirty(0, characterCount());
- emit imagesLoaded();
+ if (!requireImplicitSize) {
+ // We don't calculate implicitWidth unless it is required.
+ // We need to force a size update now to ensure implicitWidth is calculated
+ QQuickTextPrivate *me = const_cast<QQuickTextPrivate*>(this);
+ me->requireImplicitSize = true;
+ me->updateSize();
}
+ return implicitWidth;
}
-QSizeF QQuickTextDocumentWithImageResources::intrinsicSize(
- QTextDocument *, int, const QTextFormat &format)
+qreal QQuickTextPrivate::getImplicitHeight() const
{
- if (format.isImageFormat()) {
- QTextImageFormat imageFormat = format.toImageFormat();
-
- const int width = qRound(imageFormat.width());
- const bool hasWidth = imageFormat.hasProperty(QTextFormat::ImageWidth) && width > 0;
- const int height = qRound(imageFormat.height());
- const bool hasHeight = imageFormat.hasProperty(QTextFormat::ImageHeight) && height > 0;
-
- QSizeF size(width, height);
- if (!hasWidth || !hasHeight) {
- QVariant res = resource(QTextDocument::ImageResource, QUrl(imageFormat.name()));
- QImage image = res.value<QImage>();
- if (image.isNull()) {
- if (!hasWidth)
- size.setWidth(16);
- if (!hasHeight)
- size.setHeight(16);
- return size;
- }
- QSize imgSize = image.size();
-
- if (!hasWidth) {
- if (!hasHeight)
- size.setWidth(imgSize.width());
- else
- size.setWidth(qRound(height * (imgSize.width() / (qreal) imgSize.height())));
- }
- if (!hasHeight) {
- if (!hasWidth)
- size.setHeight(imgSize.height());
- else
- size.setHeight(qRound(width * (imgSize.height() / (qreal) imgSize.width())));
- }
- }
- return size;
+ if (!requireImplicitSize) {
+ QQuickTextPrivate *me = const_cast<QQuickTextPrivate*>(this);
+ me->requireImplicitSize = true;
+ me->updateSize();
}
- return QSizeF();
-}
-
-void QQuickTextDocumentWithImageResources::drawObject(
- QPainter *, const QRectF &, QTextDocument *, int, const QTextFormat &)
-{
+ return implicitHeight;
}
-QImage QQuickTextDocumentWithImageResources::image(const QTextImageFormat &format)
+qreal QQuickTextPrivate::availableWidth() const
{
- QVariant res = resource(QTextDocument::ImageResource, QUrl(format.name()));
- return res.value<QImage>();
+ Q_Q(const QQuickText);
+ return q->width() - q->leftPadding() - q->rightPadding();
}
-void QQuickTextDocumentWithImageResources::reset()
+qreal QQuickTextPrivate::availableHeight() const
{
- clearResources();
- markContentsDirty(0, characterCount());
+ Q_Q(const QQuickText);
+ return q->height() - q->topPadding() - q->bottomPadding();
}
-QQuickPixmap *QQuickTextDocumentWithImageResources::loadPixmap(
- QQmlContext *context, const QUrl &url)
+void QQuickTextPrivate::setTopPadding(qreal value, bool reset)
{
-
- QHash<QUrl, QQuickPixmap *>::Iterator iter = m_resources.find(url);
-
- if (iter == m_resources.end()) {
- QQuickPixmap *p = new QQuickPixmap(context->engine(), url);
- iter = m_resources.insert(url, p);
-
- if (p->isLoading()) {
- p->connectFinished(this, SLOT(requestFinished()));
- outstanding++;
- }
+ Q_Q(QQuickText);
+ qreal oldPadding = q->topPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().topPadding = value;
+ extra.value().explicitTopPadding = !reset;
}
-
- QQuickPixmap *p = *iter;
- if (p->isError()) {
- if (!errors.contains(url)) {
- errors.insert(url);
- qmlInfo(parent()) << p->error();
- }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ updateSize();
+ emit q->topPaddingChanged();
}
- return p;
-}
-
-void QQuickTextDocumentWithImageResources::clearResources()
-{
- foreach (QQuickPixmap *pixmap, m_resources)
- pixmap->clear(this);
- qDeleteAll(m_resources);
- m_resources.clear();
- outstanding = 0;
-}
-
-void QQuickTextDocumentWithImageResources::setText(const QString &text)
-{
- clearResources();
-
-#ifndef QT_NO_TEXTHTMLPARSER
- setHtml(text);
-#else
- setPlainText(text);
-#endif
}
-QSet<QUrl> QQuickTextDocumentWithImageResources::errors;
-
-QQuickTextPrivate::~QQuickTextPrivate()
+void QQuickTextPrivate::setLeftPadding(qreal value, bool reset)
{
- delete elideLayout;
- delete textLine; textLine = 0;
-
- if (extra.isAllocated()) {
- qDeleteAll(extra->imgTags);
- extra->imgTags.clear();
+ Q_Q(QQuickText);
+ qreal oldPadding = q->leftPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().leftPadding = value;
+ extra.value().explicitLeftPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ updateSize();
+ emit q->leftPaddingChanged();
}
}
-qreal QQuickTextPrivate::getImplicitWidth() const
+void QQuickTextPrivate::setRightPadding(qreal value, bool reset)
{
- if (!requireImplicitSize) {
- // We don't calculate implicitWidth unless it is required.
- // We need to force a size update now to ensure implicitWidth is calculated
- QQuickTextPrivate *me = const_cast<QQuickTextPrivate*>(this);
- me->requireImplicitSize = true;
- me->updateSize();
+ Q_Q(QQuickText);
+ qreal oldPadding = q->rightPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().rightPadding = value;
+ extra.value().explicitRightPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ updateSize();
+ emit q->rightPaddingChanged();
}
- return implicitWidth;
}
-qreal QQuickTextPrivate::getImplicitHeight() const
+void QQuickTextPrivate::setBottomPadding(qreal value, bool reset)
{
- if (!requireImplicitSize) {
- QQuickTextPrivate *me = const_cast<QQuickTextPrivate*>(this);
- me->requireImplicitSize = true;
- me->updateSize();
+ Q_Q(QQuickText);
+ qreal oldPadding = q->bottomPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().bottomPadding = value;
+ extra.value().explicitBottomPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ updateSize();
+ emit q->bottomPaddingChanged();
}
- return implicitHeight;
}
/*!
@@ -323,9 +258,9 @@ void QQuickTextPrivate::updateLayout()
formatModifiesFontSize = fontSizeModified;
multilengthEos = -1;
} else {
- layout.clearAdditionalFormats();
+ layout.clearFormats();
if (elideLayout)
- elideLayout->clearAdditionalFormats();
+ elideLayout->clearFormats();
QString tmp = text;
multilengthEos = tmp.indexOf(QLatin1Char('\x9c'));
if (multilengthEos != -1) {
@@ -406,7 +341,7 @@ void QQuickTextPrivate::updateBaseline(qreal baseline, qreal dy)
yoff = dy/2;
}
- q->setBaselineOffset(baseline + yoff);
+ q->setBaselineOffset(baseline + yoff + q->topPadding());
}
void QQuickTextPrivate::updateSize()
@@ -426,6 +361,9 @@ void QQuickTextPrivate::updateSize()
return;
}
+ qreal hPadding = q->leftPadding() + q->rightPadding();
+ qreal vPadding = q->topPadding() + q->bottomPadding();
+
if (text.isEmpty() && !isLineLaidOutConnected() && fontSizeMode() == QQuickText::FixedSize) {
// How much more expensive is it to just do a full layout on an empty string here?
// There may be subtle differences in the height and baseline calculations between
@@ -438,8 +376,8 @@ void QQuickTextPrivate::updateSize()
? lineHeight()
: fontHeight * lineHeight();
}
- updateBaseline(fm.ascent(), q->height() - fontHeight);
- q->setImplicitSize(0, fontHeight);
+ updateBaseline(fm.ascent(), q->height() - fontHeight - vPadding);
+ q->setImplicitSize(hPadding, fontHeight + vPadding);
layedOutTextRect = QRectF(0, 0, 0, fontHeight);
emit q->contentSizeChanged();
updateType = UpdatePaintNode;
@@ -460,7 +398,7 @@ void QQuickTextPrivate::updateSize()
layedOutTextRect = textRect;
size = textRect.size();
- updateBaseline(baseline, q->height() - size.height());
+ updateBaseline(baseline, q->height() - size.height() - vPadding);
} else {
widthExceeded = true; // always relayout rich text on width changes..
heightExceeded = false; // rich text layout isn't affected by height changes.
@@ -484,15 +422,15 @@ void QQuickTextPrivate::updateSize()
naturalWidth = extra->doc->idealWidth();
const bool wasInLayout = internalWidthUpdate;
internalWidthUpdate = true;
- q->setImplicitWidth(naturalWidth);
+ q->setImplicitWidth(naturalWidth + hPadding);
internalWidthUpdate = wasInLayout;
}
if (internalWidthUpdate)
return;
extra->doc->setPageSize(QSizeF());
- if (q->widthValid() && (wrapMode != QQuickText::NoWrap || extra->doc->idealWidth() < q->width()))
- extra->doc->setTextWidth(q->width());
+ if (q->widthValid() && (wrapMode != QQuickText::NoWrap || extra->doc->idealWidth() < availableWidth()))
+ extra->doc->setTextWidth(availableWidth());
else
extra->doc->setTextWidth(extra->doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug)
@@ -501,7 +439,7 @@ void QQuickTextPrivate::updateSize()
size = QSizeF(extra->doc->idealWidth(),dsize.height());
QFontMetricsF fm(font);
- updateBaseline(fm.ascent(), q->height() - size.height());
+ updateBaseline(fm.ascent(), q->height() - size.height() - vPadding);
//### need to confirm cost of always setting these for richText
internalWidthUpdate = true;
@@ -509,11 +447,11 @@ void QQuickTextPrivate::updateSize()
if (!q->widthValid())
iWidth = size.width();
if (iWidth > -1)
- q->setImplicitSize(iWidth, size.height());
+ q->setImplicitSize(iWidth + hPadding, size.height() + vPadding);
internalWidthUpdate = false;
if (iWidth == -1)
- q->setImplicitHeight(size.height());
+ q->setImplicitHeight(size.height() + vPadding);
}
if (layedOutTextRect.size() != previousSize)
@@ -619,7 +557,7 @@ void QQuickTextPrivate::setupCustomLineGeometry(QTextLine &line, qreal &height,
// use the text item's width by default if it has one and wrap is on or text must be aligned
if (q->widthValid() && (q->wrapMode() != QQuickText::NoWrap ||
q->effectiveHAlign() != QQuickText::AlignLeft))
- textLine->setWidth(q->width());
+ textLine->setWidth(availableWidth());
else
textLine->setWidth(INT_MAX);
if (lineHeight() != 1.0)
@@ -631,10 +569,10 @@ void QQuickTextPrivate::setupCustomLineGeometry(QTextLine &line, qreal &height,
}
void QQuickTextPrivate::elideFormats(
- const int start, const int length, int offset, QList<QTextLayout::FormatRange> *elidedFormats)
+ const int start, const int length, int offset, QVector<QTextLayout::FormatRange> *elidedFormats)
{
const int end = start + length;
- QList<QTextLayout::FormatRange> formats = layout.additionalFormats();
+ const QVector<QTextLayout::FormatRange> formats = layout.formats();
for (int i = 0; i < formats.count(); ++i) {
QTextLayout::FormatRange format = formats.at(i);
const int formatLength = qMin(format.start + format.length, end) - qMax(format.start, start);
@@ -687,10 +625,11 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
&& (q->heightValid() || maximumLineCountValid);
if ((!requireImplicitSize || (implicitWidthValid && implicitHeightValid))
- && ((singlelineElide && q->width() <= 0.) || (multilineElide && q->heightValid() && q->height() <= 0.))) {
+ && ((singlelineElide && availableWidth() <= 0.)
+ || (multilineElide && q->heightValid() && availableHeight() <= 0.))) {
// we are elided and we have a zero width or height
- widthExceeded = q->widthValid() && q->width() <= 0.;
- heightExceeded = q->heightValid() && q->height() <= 0.;
+ widthExceeded = q->widthValid() && availableWidth() <= 0.;
+ heightExceeded = q->heightValid() && availableHeight() <= 0.;
if (!truncated) {
truncated = true;
@@ -726,7 +665,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
lineWidth = (q->widthValid() || implicitWidthValid) && q->width() > 0
? q->width()
: FLT_MAX;
- qreal maxHeight = q->heightValid() ? q->height() : FLT_MAX;
+ qreal maxHeight = q->heightValid() ? availableHeight() : FLT_MAX;
const bool customLayout = isLineLaidOutConnected();
const bool wasTruncated = truncated;
@@ -747,8 +686,8 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
int scaledFontSize = largeFont;
bool widthChanged = false;
- widthExceeded = q->width() <= 0 && (singlelineElide || canWrap || horizontalFit);
- heightExceeded = q->height() <= 0 && (multilineElide || verticalFit);
+ widthExceeded = availableWidth() <= 0 && (singlelineElide || canWrap || horizontalFit);
+ heightExceeded = availableHeight() <= 0 && (multilineElide || verticalFit);
QRectF br;
@@ -918,7 +857,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
bool wasInLayout = internalWidthUpdate;
internalWidthUpdate = true;
- q->setImplicitSize(naturalWidth, naturalHeight);
+ q->setImplicitSize(naturalWidth + q->leftPadding() + q->rightPadding(), naturalHeight + q->topPadding() + q->bottomPadding());
internalWidthUpdate = wasInLayout;
// Update any variables that are dependent on the validity of the width or height.
@@ -935,8 +874,11 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
const qreal oldWidth = lineWidth;
const qreal oldHeight = maxHeight;
- lineWidth = q->widthValid() && q->width() > 0 ? q->width() : naturalWidth;
- maxHeight = q->heightValid() ? q->height() : FLT_MAX;
+ const qreal availWidth = availableWidth();
+ const qreal availHeight = availableHeight();
+
+ lineWidth = q->widthValid() && availWidth > 0 ? availWidth : naturalWidth;
+ maxHeight = q->heightValid() ? availHeight : FLT_MAX;
// If the width of the item has changed and it's possible the result of wrapping,
// eliding, scaling has changed, or the text is not left aligned do another layout.
@@ -989,7 +931,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
&& (q->heightValid() || (maximumLineCountValid && canWrap));
const qreal oldHeight = maxHeight;
- maxHeight = q->heightValid() ? q->height() : FLT_MAX;
+ maxHeight = q->heightValid() ? availableHeight() : FLT_MAX;
// If the height of the item has changed and it's possible the result of eliding,
// line count truncation or scaling has changed, do another layout.
if ((maxHeight < qMin(oldHeight, naturalHeight) || (heightExceeded && maxHeight > oldHeight))
@@ -1069,7 +1011,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
elideLayout->setCacheEnabled(true);
}
if (styledText) {
- QList<QTextLayout::FormatRange> formats;
+ QVector<QTextLayout::FormatRange> formats;
switch (elideMode) {
case QQuickText::ElideRight:
elideFormats(elideStart, elideText.length() - 1, 0, &formats);
@@ -1092,7 +1034,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
default:
break;
}
- elideLayout->setAdditionalFormats(formats);
+ elideLayout->setFormats(formats);
}
elideLayout->setFont(layout.font());
@@ -1283,6 +1225,13 @@ QQuickText::QQuickText(QQuickItem *parent)
d->init();
}
+QQuickText::QQuickText(QQuickTextPrivate &dd, QQuickItem *parent)
+: QQuickImplicitSizeItem(dd, parent)
+{
+ Q_D(QQuickText);
+ d->init();
+}
+
QQuickText::~QQuickText()
{
}
@@ -1357,6 +1306,16 @@ QQuickText::~QQuickText()
*/
/*!
+ \qmlproperty string QtQuick::Text::font.styleName
+ \since 5.6
+
+ Sets the style name of the font.
+
+ The style name is case insensitive. If set, the font will be matched against style name instead
+ of the font properties \l font.weight, \l font.bold and \l font.italic.
+*/
+
+/*!
\qmlproperty bool QtQuick::Text::font.bold
Sets whether the font weight is bold.
@@ -2194,18 +2153,19 @@ void QQuickText::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeo
bool widthMaximum = newGeometry.width() >= oldGeometry.width() && !d->widthExceeded;
bool heightMaximum = newGeometry.height() >= oldGeometry.height() && !d->heightExceeded;
+ bool verticalPositionChanged = heightChanged && d->vAlign != AlignTop;
+
if ((!widthChanged && !heightChanged) || d->internalWidthUpdate)
goto geomChangeDone;
- if ((effectiveHAlign() != QQuickText::AlignLeft && widthChanged)
- || (vAlign() != QQuickText::AlignTop && heightChanged)) {
+ if ((effectiveHAlign() != QQuickText::AlignLeft && widthChanged) || verticalPositionChanged) {
// If the width has changed and we're not left aligned do an update so the text is
// repositioned even if a full layout isn't required. And the same for vertical.
d->updateType = QQuickTextPrivate::UpdatePaintNode;
update();
}
- if (!wrapped && !elide && !scaleFont)
+ if (!wrapped && !elide && !scaleFont && !verticalPositionChanged)
goto geomChangeDone; // left aligned unwrapped text without eliding never needs relayout
if (elide // eliding and dimensions were and remain invalid;
@@ -2214,7 +2174,7 @@ void QQuickText::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeo
goto geomChangeDone;
}
- if (widthMaximum && heightMaximum && !d->isLineLaidOutConnected()) // Size is sufficient and growing.
+ if (widthMaximum && heightMaximum && !d->isLineLaidOutConnected() && !verticalPositionChanged) // Size is sufficient and growing.
goto geomChangeDone;
if (!(widthChanged || widthMaximum) && !d->isLineLaidOutConnected()) { // only height has changed
@@ -2275,7 +2235,7 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data
d->updateType = QQuickTextPrivate::UpdateNone;
- const qreal dy = QQuickTextUtil::alignedY(d->layedOutTextRect.height() + d->lineHeightOffset(), height(), d->vAlign);
+ const qreal dy = QQuickTextUtil::alignedY(d->layedOutTextRect.height() + d->lineHeightOffset(), d->availableHeight(), d->vAlign) + topPadding();
QQuickTextNode *node = 0;
if (!oldNode)
@@ -2292,11 +2252,11 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data
const QColor linkColor = QColor::fromRgba(d->linkColor);
if (d->richText) {
- const qreal dx = QQuickTextUtil::alignedX(d->layedOutTextRect.width(), width(), effectiveHAlign());
+ const qreal dx = QQuickTextUtil::alignedX(d->layedOutTextRect.width(), d->availableWidth(), effectiveHAlign()) + leftPadding();
d->ensureDoc();
node->addTextDocument(QPointF(dx, dy), d->extra->doc, color, d->style, styleColor, linkColor);
} else if (d->layedOutTextRect.width() > 0) {
- const qreal dx = QQuickTextUtil::alignedX(d->lineWidth, width(), effectiveHAlign());
+ const qreal dx = QQuickTextUtil::alignedX(d->lineWidth, d->availableWidth(), effectiveHAlign()) + leftPadding();
int unelidedLineCount = d->lineCount;
if (d->elideLayout)
unelidedLineCount -= 1;
@@ -2566,7 +2526,7 @@ QString QQuickTextPrivate::anchorAt(const QTextLayout *layout, const QPointF &mo
QTextLine line = layout->lineAt(i);
if (line.naturalTextRect().contains(mousePos)) {
int charPos = line.xToCursor(mousePos.x(), QTextLine::CursorOnCharacter);
- foreach (const QTextLayout::FormatRange &formatRange, layout->additionalFormats()) {
+ foreach (const QTextLayout::FormatRange &formatRange, layout->formats()) {
if (formatRange.format.isAnchor()
&& charPos >= formatRange.start
&& charPos < formatRange.start + formatRange.length) {
@@ -2583,14 +2543,15 @@ QString QQuickTextPrivate::anchorAt(const QPointF &mousePos) const
{
Q_Q(const QQuickText);
QPointF translatedMousePos = mousePos;
- translatedMousePos.ry() -= QQuickTextUtil::alignedY(layedOutTextRect.height() + lineHeightOffset(), q->height(), vAlign);
+ translatedMousePos.rx() -= q->leftPadding();
+ translatedMousePos.ry() -= q->topPadding() + QQuickTextUtil::alignedY(layedOutTextRect.height() + lineHeightOffset(), availableHeight(), vAlign);
if (styledText) {
QString link = anchorAt(&layout, translatedMousePos);
if (link.isEmpty() && elideLayout)
link = anchorAt(elideLayout, translatedMousePos);
return link;
} else if (richText && extra.isAllocated() && extra->doc) {
- translatedMousePos.rx() -= QQuickTextUtil::alignedX(layedOutTextRect.width(), q->width(), q->effectiveHAlign());
+ translatedMousePos.rx() -= QQuickTextUtil::alignedX(layedOutTextRect.width(), availableWidth(), q->effectiveHAlign());
return extra->doc->documentLayout()->anchorAt(translatedMousePos);
}
return QString();
@@ -2808,4 +2769,125 @@ void QQuickText::invalidateFontCaches()
}
}
+/*!
+ \since 5.6
+ \qmlproperty real QtQuick::Text::padding
+ \qmlproperty real QtQuick::Text::topPadding
+ \qmlproperty real QtQuick::Text::leftPadding
+ \qmlproperty real QtQuick::Text::bottomPadding
+ \qmlproperty real QtQuick::Text::rightPadding
+
+ These properties hold the padding around the content. This space is reserved
+ in addition to the contentWidth and contentHeight.
+*/
+qreal QQuickText::padding() const
+{
+ Q_D(const QQuickText);
+ return d->padding();
+}
+
+void QQuickText::setPadding(qreal padding)
+{
+ Q_D(QQuickText);
+ if (qFuzzyCompare(d->padding(), padding))
+ return;
+
+ d->extra.value().padding = padding;
+ d->updateSize();
+ emit paddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitTopPadding)
+ emit topPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitLeftPadding)
+ emit leftPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitRightPadding)
+ emit rightPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitBottomPadding)
+ emit bottomPaddingChanged();
+}
+
+void QQuickText::resetPadding()
+{
+ setPadding(0);
+}
+
+qreal QQuickText::topPadding() const
+{
+ Q_D(const QQuickText);
+ if (d->extra.isAllocated() && d->extra->explicitTopPadding)
+ return d->extra->topPadding;
+ return d->padding();
+}
+
+void QQuickText::setTopPadding(qreal padding)
+{
+ Q_D(QQuickText);
+ d->setTopPadding(padding);
+}
+
+void QQuickText::resetTopPadding()
+{
+ Q_D(QQuickText);
+ d->setTopPadding(0, true);
+}
+
+qreal QQuickText::leftPadding() const
+{
+ Q_D(const QQuickText);
+ if (d->extra.isAllocated() && d->extra->explicitLeftPadding)
+ return d->extra->leftPadding;
+ return d->padding();
+}
+
+void QQuickText::setLeftPadding(qreal padding)
+{
+ Q_D(QQuickText);
+ d->setLeftPadding(padding);
+}
+
+void QQuickText::resetLeftPadding()
+{
+ Q_D(QQuickText);
+ d->setLeftPadding(0, true);
+}
+
+qreal QQuickText::rightPadding() const
+{
+ Q_D(const QQuickText);
+ if (d->extra.isAllocated() && d->extra->explicitRightPadding)
+ return d->extra->rightPadding;
+ return d->padding();
+}
+
+void QQuickText::setRightPadding(qreal padding)
+{
+ Q_D(QQuickText);
+ d->setRightPadding(padding);
+}
+
+void QQuickText::resetRightPadding()
+{
+ Q_D(QQuickText);
+ d->setRightPadding(0, true);
+}
+
+qreal QQuickText::bottomPadding() const
+{
+ Q_D(const QQuickText);
+ if (d->extra.isAllocated() && d->extra->explicitBottomPadding)
+ return d->extra->bottomPadding;
+ return d->padding();
+}
+
+void QQuickText::setBottomPadding(qreal padding)
+{
+ Q_D(QQuickText);
+ d->setBottomPadding(padding);
+}
+
+void QQuickText::resetBottomPadding()
+{
+ Q_D(QQuickText);
+ d->setBottomPadding(0, true);
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h
index 283e3b510b..5b385aeb0a 100644
--- a/src/quick/items/qquicktext_p.h
+++ b/src/quick/items/qquicktext_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKTEXT_P_H
#define QQUICKTEXT_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickimplicitsizeitem_p.h"
#include <private/qtquickglobal_p.h>
#include <QtGui/qtextoption.h>
@@ -45,15 +56,6 @@ class QQuickTextLine;
class Q_QUICK_PRIVATE_EXPORT QQuickText : public QQuickImplicitSizeItem
{
Q_OBJECT
- Q_ENUMS(HAlignment)
- Q_ENUMS(VAlignment)
- Q_ENUMS(TextStyle)
- Q_ENUMS(TextFormat)
- Q_ENUMS(TextElideMode)
- Q_ENUMS(WrapMode)
- Q_ENUMS(LineHeightMode)
- Q_ENUMS(FontSizeMode)
- Q_ENUMS(RenderType)
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
@@ -84,6 +86,12 @@ class Q_QUICK_PRIVATE_EXPORT QQuickText : public QQuickImplicitSizeItem
Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged)
Q_PROPERTY(QString hoveredLink READ hoveredLink NOTIFY linkHovered REVISION 2)
+ Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6)
+ Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6)
+ Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6)
+ Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6)
+ Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6)
+
public:
QQuickText(QQuickItem *parent=0);
~QQuickText();
@@ -92,21 +100,26 @@ public:
AlignRight = Qt::AlignRight,
AlignHCenter = Qt::AlignHCenter,
AlignJustify = Qt::AlignJustify };
+ Q_ENUM(HAlignment)
enum VAlignment { AlignTop = Qt::AlignTop,
AlignBottom = Qt::AlignBottom,
AlignVCenter = Qt::AlignVCenter };
+ Q_ENUM(VAlignment)
enum TextStyle { Normal,
Outline,
Raised,
Sunken };
+ Q_ENUM(TextStyle)
enum TextFormat { PlainText = Qt::PlainText,
RichText = Qt::RichText,
AutoText = Qt::AutoText,
StyledText = 4 };
+ Q_ENUM(TextFormat)
enum TextElideMode { ElideLeft = Qt::ElideLeft,
ElideRight = Qt::ElideRight,
ElideMiddle = Qt::ElideMiddle,
ElideNone = Qt::ElideNone };
+ Q_ENUM(TextElideMode)
enum WrapMode { NoWrap = QTextOption::NoWrap,
WordWrap = QTextOption::WordWrap,
@@ -114,15 +127,19 @@ public:
WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT
Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere
};
+ Q_ENUM(WrapMode)
enum RenderType { QtRendering,
NativeRendering
};
+ Q_ENUM(RenderType)
enum LineHeightMode { ProportionalHeight, FixedHeight };
+ Q_ENUM(LineHeightMode)
enum FontSizeMode { FixedSize = 0x0, HorizontalFit = 0x01, VerticalFit = 0x02,
Fit = HorizontalFit | VerticalFit };
+ Q_ENUM(FontSizeMode)
QString text() const;
void setText(const QString &);
@@ -204,6 +221,26 @@ public:
Q_REVISION(3) Q_INVOKABLE QString linkAt(qreal x, qreal y) const;
+ qreal padding() const;
+ void setPadding(qreal padding);
+ void resetPadding();
+
+ qreal topPadding() const;
+ void setTopPadding(qreal padding);
+ void resetTopPadding();
+
+ qreal leftPadding() const;
+ void setLeftPadding(qreal padding);
+ void resetLeftPadding();
+
+ qreal rightPadding() const;
+ void setRightPadding(qreal padding);
+ void resetRightPadding();
+
+ qreal bottomPadding() const;
+ void setBottomPadding(qreal padding);
+ void resetBottomPadding();
+
Q_SIGNALS:
void textChanged(const QString &text);
void linkActivated(const QString &link);
@@ -231,8 +268,15 @@ Q_SIGNALS:
void lineLaidOut(QQuickTextLine *line);
void baseUrlChanged();
void renderTypeChanged();
+ Q_REVISION(6) void paddingChanged();
+ Q_REVISION(6) void topPaddingChanged();
+ Q_REVISION(6) void leftPaddingChanged();
+ Q_REVISION(6) void rightPaddingChanged();
+ Q_REVISION(6) void bottomPaddingChanged();
protected:
+ QQuickText(QQuickTextPrivate &dd, QQuickItem *parent = 0);
+
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void itemChange(ItemChange change, const ItemChangeData &value) Q_DECL_OVERRIDE;
diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h
index 28435bc8c5..c8cadcece9 100644
--- a/src/quick/items/qquicktext_p_p.h
+++ b/src/quick/items/qquicktext_p_p.h
@@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
class QTextLayout;
class QQuickTextDocumentWithImageResources;
-class Q_AUTOTEST_EXPORT QQuickTextPrivate : public QQuickImplicitSizeItemPrivate
+class Q_QUICK_PRIVATE_EXPORT QQuickTextPrivate : public QQuickImplicitSizeItemPrivate
{
Q_DECLARE_PUBLIC(QQuickText)
public:
@@ -78,7 +78,7 @@ public:
int lineHeightOffset() const;
QString elidedText(qreal lineWidth, const QTextLine &line, QTextLine *nextLine = 0) const;
- void elideFormats(int start, int length, int offset, QList<QTextLayout::FormatRange> *elidedFormats);
+ void elideFormats(int start, int length, int offset, QVector<QTextLayout::FormatRange> *elidedFormats);
void processHoverEvent(QHoverEvent *event);
@@ -87,6 +87,15 @@ public:
struct ExtraData {
ExtraData();
+ qreal padding;
+ qreal topPadding;
+ qreal leftPadding;
+ qreal rightPadding;
+ qreal bottomPadding;
+ bool explicitTopPadding : 1;
+ bool explicitLeftPadding : 1;
+ bool explicitRightPadding : 1;
+ bool explicitBottomPadding : 1;
qreal lineHeight;
QQuickTextDocumentWithImageResources *doc;
QString activeLink;
@@ -160,6 +169,15 @@ public:
qreal getImplicitWidth() const Q_DECL_OVERRIDE;
qreal getImplicitHeight() const Q_DECL_OVERRIDE;
+ qreal availableWidth() const;
+ qreal availableHeight() const;
+
+ inline qreal padding() const { return extra.isAllocated() ? extra->padding : 0.0; }
+ void setTopPadding(qreal value, bool reset = false);
+ void setLeftPadding(qreal value, bool reset = false);
+ void setRightPadding(qreal value, bool reset = false);
+ void setBottomPadding(qreal value, bool reset = false);
+
void ensureDoc();
QRectF setupTextLayout(qreal * const baseline);
@@ -178,45 +196,6 @@ public:
static inline QQuickTextPrivate *get(QQuickText *t) { return t->d_func(); }
};
-class QQuickPixmap;
-class Q_AUTOTEST_EXPORT QQuickTextDocumentWithImageResources : public QTextDocument, public QTextObjectInterface
-{
- Q_OBJECT
- Q_INTERFACES(QTextObjectInterface)
-public:
- QQuickTextDocumentWithImageResources(QQuickItem *parent);
- virtual ~QQuickTextDocumentWithImageResources();
-
- void setText(const QString &);
- int resourcesLoading() const { return outstanding; }
-
- QSizeF intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format);
- void drawObject(QPainter *p, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format);
-
- QImage image(const QTextImageFormat &format);
-
-public Q_SLOTS:
- void clearResources();
-
-Q_SIGNALS:
- void imagesLoaded();
-
-protected:
- QVariant loadResource(int type, const QUrl &name);
-
- QQuickPixmap *loadPixmap(QQmlContext *context, const QUrl &name);
-
-private Q_SLOTS:
- void reset();
- void requestFinished();
-
-private:
- QHash<QUrl, QQuickPixmap *> m_resources;
-
- int outstanding;
- static QSet<QUrl> errors;
-};
-
QT_END_NAMESPACE
#endif // QQUICKTEXT_P_P_H
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index 6929bb44a2..04e43c017e 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -106,7 +106,9 @@ QQuickTextControlPrivate::QQuickTextControlPrivate()
hadSelectionOnMousePress(false),
wordSelectionEnabled(false),
hasImState(false),
- cursorRectangleChanged(false)
+ cursorRectangleChanged(false),
+ lastSelectionStart(-1),
+ lastSelectionEnd(-1)
{}
bool QQuickTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e)
@@ -403,11 +405,19 @@ void QQuickTextControlPrivate::selectionChanged(bool forceEmitSelectionChanged /
}
bool current = cursor.hasSelection();
- if (current == lastSelectionState)
+ int selectionStart = cursor.selectionStart();
+ int selectionEnd = cursor.selectionEnd();
+ if (current == lastSelectionState && (!current || (selectionStart == lastSelectionStart && selectionEnd == lastSelectionEnd)))
return;
- lastSelectionState = current;
- emit q->copyAvailable(current);
+ if (lastSelectionState != current) {
+ lastSelectionState = current;
+ emit q->copyAvailable(current);
+ }
+
+ lastSelectionStart = selectionStart;
+ lastSelectionEnd = selectionEnd;
+
if (!forceEmitSelectionChanged) {
#ifndef QT_NO_IM
if (hasFocus)
@@ -1313,7 +1323,7 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
QTextLayout *layout = block.layout();
if (isGettingInput)
layout->setPreeditArea(cursor.position() - block.position(), e->preeditString());
- QList<QTextLayout::FormatRange> overrides;
+ QVector<QTextLayout::FormatRange> overrides;
const int oldPreeditCursor = preeditCursor;
preeditCursor = e->preeditString().length();
hasImState = !e->preeditString().isEmpty();
@@ -1336,7 +1346,7 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
}
}
}
- layout->setAdditionalFormats(overrides);
+ layout->setFormats(overrides);
cursor.endEditBlock();
diff --git a/src/quick/items/qquicktextcontrol_p_p.h b/src/quick/items/qquicktextcontrol_p_p.h
index 4c3e03a552..3c2e579737 100644
--- a/src/quick/items/qquicktextcontrol_p_p.h
+++ b/src/quick/items/qquicktextcontrol_p_p.h
@@ -156,6 +156,9 @@ public:
bool hasImState : 1;
bool cursorRectangleChanged : 1;
+ int lastSelectionStart;
+ int lastSelectionEnd;
+
void _q_copyLink();
};
diff --git a/src/quick/items/qquicktextdocument.cpp b/src/quick/items/qquicktextdocument.cpp
index fa89d43b86..c8b29dc1ad 100644
--- a/src/quick/items/qquicktextdocument.cpp
+++ b/src/quick/items/qquicktextdocument.cpp
@@ -32,11 +32,16 @@
****************************************************************************/
#include "qquicktextdocument.h"
+#include "qquicktextdocument_p.h"
#include "qquicktextedit_p.h"
#include "qquicktextedit_p_p.h"
#include "qquicktext_p_p.h"
+#include <QtQml/qqmlinfo.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQuick/private/qquickpixmapcache_p.h>
+
QT_BEGIN_NAMESPACE
/*!
@@ -85,4 +90,147 @@ QTextDocument* QQuickTextDocument::textDocument() const
return d->document.data();
}
+QQuickTextDocumentWithImageResources::QQuickTextDocumentWithImageResources(QQuickItem *parent)
+: QTextDocument(parent), outstanding(0)
+{
+ setUndoRedoEnabled(false);
+ documentLayout()->registerHandler(QTextFormat::ImageObject, this);
+ connect(this, SIGNAL(baseUrlChanged(QUrl)), this, SLOT(reset()));
+}
+
+QQuickTextDocumentWithImageResources::~QQuickTextDocumentWithImageResources()
+{
+ if (!m_resources.isEmpty())
+ qDeleteAll(m_resources);
+}
+
+QVariant QQuickTextDocumentWithImageResources::loadResource(int type, const QUrl &name)
+{
+ QVariant resource = QTextDocument::loadResource(type, name);
+ if (resource.isNull() && type == QTextDocument::ImageResource) {
+ QQmlContext *context = qmlContext(parent());
+ QUrl url = baseUrl().resolved(name);
+ QQuickPixmap *p = loadPixmap(context, url);
+ resource = p->image();
+ }
+
+ return resource;
+}
+
+void QQuickTextDocumentWithImageResources::requestFinished()
+{
+ outstanding--;
+ if (outstanding == 0) {
+ markContentsDirty(0, characterCount());
+ emit imagesLoaded();
+ }
+}
+
+QSizeF QQuickTextDocumentWithImageResources::intrinsicSize(
+ QTextDocument *, int, const QTextFormat &format)
+{
+ if (format.isImageFormat()) {
+ QTextImageFormat imageFormat = format.toImageFormat();
+
+ const int width = qRound(imageFormat.width());
+ const bool hasWidth = imageFormat.hasProperty(QTextFormat::ImageWidth) && width > 0;
+ const int height = qRound(imageFormat.height());
+ const bool hasHeight = imageFormat.hasProperty(QTextFormat::ImageHeight) && height > 0;
+
+ QSizeF size(width, height);
+ if (!hasWidth || !hasHeight) {
+ QVariant res = resource(QTextDocument::ImageResource, QUrl(imageFormat.name()));
+ QImage image = res.value<QImage>();
+ if (image.isNull()) {
+ if (!hasWidth)
+ size.setWidth(16);
+ if (!hasHeight)
+ size.setHeight(16);
+ return size;
+ }
+ QSize imgSize = image.size();
+
+ if (!hasWidth) {
+ if (!hasHeight)
+ size.setWidth(imgSize.width());
+ else
+ size.setWidth(qRound(height * (imgSize.width() / (qreal) imgSize.height())));
+ }
+ if (!hasHeight) {
+ if (!hasWidth)
+ size.setHeight(imgSize.height());
+ else
+ size.setHeight(qRound(width * (imgSize.height() / (qreal) imgSize.width())));
+ }
+ }
+ return size;
+ }
+ return QSizeF();
+}
+
+void QQuickTextDocumentWithImageResources::drawObject(
+ QPainter *, const QRectF &, QTextDocument *, int, const QTextFormat &)
+{
+}
+
+QImage QQuickTextDocumentWithImageResources::image(const QTextImageFormat &format)
+{
+ QVariant res = resource(QTextDocument::ImageResource, QUrl(format.name()));
+ return res.value<QImage>();
+}
+
+void QQuickTextDocumentWithImageResources::reset()
+{
+ clearResources();
+ markContentsDirty(0, characterCount());
+}
+
+QQuickPixmap *QQuickTextDocumentWithImageResources::loadPixmap(
+ QQmlContext *context, const QUrl &url)
+{
+
+ QHash<QUrl, QQuickPixmap *>::Iterator iter = m_resources.find(url);
+
+ if (iter == m_resources.end()) {
+ QQuickPixmap *p = new QQuickPixmap(context->engine(), url);
+ iter = m_resources.insert(url, p);
+
+ if (p->isLoading()) {
+ p->connectFinished(this, SLOT(requestFinished()));
+ outstanding++;
+ }
+ }
+
+ QQuickPixmap *p = *iter;
+ if (p->isError()) {
+ if (!errors.contains(url)) {
+ errors.insert(url);
+ qmlInfo(parent()) << p->error();
+ }
+ }
+ return p;
+}
+
+void QQuickTextDocumentWithImageResources::clearResources()
+{
+ foreach (QQuickPixmap *pixmap, m_resources)
+ pixmap->clear(this);
+ qDeleteAll(m_resources);
+ m_resources.clear();
+ outstanding = 0;
+}
+
+void QQuickTextDocumentWithImageResources::setText(const QString &text)
+{
+ clearResources();
+
+#ifndef QT_NO_TEXTHTMLPARSER
+ setHtml(text);
+#else
+ setPlainText(text);
+#endif
+}
+
+QSet<QUrl> QQuickTextDocumentWithImageResources::errors;
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktextdocument_p.h b/src/quick/items/qquicktextdocument_p.h
new file mode 100644
index 0000000000..1a9d71fe1c
--- /dev/null
+++ b/src/quick/items/qquicktextdocument_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKTEXTDOCUMENT_P_H
+#define QQUICKTEXTDOCUMENT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qhash.h>
+#include <QtCore/qvariant.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qtextdocument.h>
+#include <QtGui/qabstracttextdocumentlayout.h>
+#include <QtGui/qtextlayout.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickItem;
+class QQuickPixmap;
+class QQmlContext;
+
+class Q_AUTOTEST_EXPORT QQuickTextDocumentWithImageResources : public QTextDocument, public QTextObjectInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QTextObjectInterface)
+public:
+ QQuickTextDocumentWithImageResources(QQuickItem *parent);
+ virtual ~QQuickTextDocumentWithImageResources();
+
+ void setText(const QString &);
+ int resourcesLoading() const { return outstanding; }
+
+ QSizeF intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format);
+ void drawObject(QPainter *p, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format);
+
+ QImage image(const QTextImageFormat &format);
+
+public Q_SLOTS:
+ void clearResources();
+
+Q_SIGNALS:
+ void imagesLoaded();
+
+protected:
+ QVariant loadResource(int type, const QUrl &name);
+
+ QQuickPixmap *loadPixmap(QQmlContext *context, const QUrl &name);
+
+private Q_SLOTS:
+ void reset();
+ void requestFinished();
+
+private:
+ QHash<QUrl, QQuickPixmap *> m_resources;
+
+ int outstanding;
+ static QSet<QUrl> errors;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKDOCUMENT_P_H
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index cd1cf5eef1..8282c09770 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -34,7 +34,7 @@
#include "qquicktextedit_p.h"
#include "qquicktextedit_p_p.h"
#include "qquicktextcontrol_p.h"
-#include "qquicktext_p_p.h"
+#include "qquicktextdocument_p.h"
#include "qquickevents_p_p.h"
#include "qquickwindow.h"
#include "qquicktextnode_p.h"
@@ -172,6 +172,13 @@ QQuickTextEdit::QQuickTextEdit(QQuickItem *parent)
d->init();
}
+QQuickTextEdit::QQuickTextEdit(QQuickTextEditPrivate &dd, QQuickItem *parent)
+: QQuickImplicitSizeItem(dd, parent)
+{
+ Q_D(QQuickTextEdit);
+ d->init();
+}
+
QString QQuickTextEdit::text() const
{
Q_D(const QQuickTextEdit);
@@ -199,6 +206,17 @@ QString QQuickTextEdit::text() const
*/
/*!
+ \qmlproperty string QtQuick::TextEdit::font.styleName
+ \since 5.6
+
+ Sets the style name of the font.
+
+ The style name is case insensitive. If set, the font will be matched against style name instead
+ of the font properties \l font.weight, \l font.bold and \l font.italic.
+*/
+
+
+/*!
\qmlproperty bool QtQuick::TextEdit::font.bold
Sets whether the font weight is bold.
@@ -699,6 +717,75 @@ Qt::InputMethodHints QQuickTextEditPrivate::effectiveInputMethodHints() const
}
#endif
+void QQuickTextEditPrivate::setTopPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickTextEdit);
+ qreal oldPadding = q->topPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().topPadding = value;
+ extra.value().explicitTopPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ q->updateSize();
+ emit q->topPaddingChanged();
+ }
+}
+
+void QQuickTextEditPrivate::setLeftPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickTextEdit);
+ qreal oldPadding = q->leftPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().leftPadding = value;
+ extra.value().explicitLeftPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ q->updateSize();
+ emit q->leftPaddingChanged();
+ }
+}
+
+void QQuickTextEditPrivate::setRightPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickTextEdit);
+ qreal oldPadding = q->rightPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().rightPadding = value;
+ extra.value().explicitRightPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ q->updateSize();
+ emit q->rightPaddingChanged();
+ }
+}
+
+void QQuickTextEditPrivate::setBottomPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickTextEdit);
+ qreal oldPadding = q->bottomPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().bottomPadding = value;
+ extra.value().explicitBottomPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ q->updateSize();
+ emit q->bottomPaddingChanged();
+ }
+}
+
+bool QQuickTextEditPrivate::isImplicitResizeEnabled() const
+{
+ return !extra.isAllocated() || extra->implicitResize;
+}
+
+void QQuickTextEditPrivate::setImplicitResizeEnabled(bool enabled)
+{
+ if (!enabled)
+ extra.value().implicitResize = false;
+ else if (extra.isAllocated())
+ extra->implicitResize = true;
+}
+
QQuickTextEdit::VAlignment QQuickTextEdit::vAlign() const
{
Q_D(const QQuickTextEdit);
@@ -1658,6 +1745,8 @@ void QQuickTextEdit::mousePressEvent(QMouseEvent *event)
#ifndef QT_NO_IM
if (hasActiveFocus() && hadActiveFocus && !isReadOnly())
qGuiApp->inputMethod()->show();
+#else
+ Q_UNUSED(hadActiveFocus);
#endif
}
if (!event->isAccepted())
@@ -1793,6 +1882,14 @@ void QQuickTextEdit::invalidateFontCaches()
}
}
+inline void resetEngine(QQuickTextNodeEngine *engine, const QColor& textColor, const QColor& selectedTextColor, const QColor& selectionColor)
+{
+ *engine = QQuickTextNodeEngine();
+ engine->setTextColor(textColor);
+ engine->setSelectedTextColor(selectedTextColor);
+ engine->setSelectionColor(selectionColor);
+}
+
QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData)
{
Q_UNUSED(updatePaintNodeData);
@@ -1818,6 +1915,8 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
while (nodeIterator != d->textNodeMap.end() && !(*nodeIterator)->dirty())
++nodeIterator;
+ QQuickTextNodeEngine engine;
+ QQuickTextNodeEngine frameDecorationsEngine;
if (!oldNode || nodeIterator < d->textNodeMap.end()) {
@@ -1837,6 +1936,7 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
// FIXME: the text decorations could probably be handled separately (only updated for affected textFrames)
rootNode->resetFrameDecorations(d->createTextNode());
+ resetEngine(&frameDecorationsEngine, d->color, d->selectedTextColor, d->selectionColor);
QQuickTextNode *node = 0;
@@ -1856,11 +1956,12 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
while (!frames.isEmpty()) {
QTextFrame *textFrame = frames.takeFirst();
frames.append(textFrame->childFrames());
- rootNode->frameDecorationsNode->m_engine->addFrameDecorations(d->document, textFrame);
+ frameDecorationsEngine.addFrameDecorations(d->document, textFrame);
if (textFrame->lastPosition() < firstDirtyPos || (firstCleanNode && textFrame->firstPosition() >= firstCleanNode->startPos()))
continue;
node = d->createTextNode();
+ resetEngine(&engine, d->color, d->selectedTextColor, d->selectionColor);
if (textFrame->firstPosition() > textFrame->lastPosition()
&& textFrame->frameFormat().position() != QTextFrameFormat::InFlow) {
@@ -1869,8 +1970,8 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
ProtectedLayoutAccessor *a = static_cast<ProtectedLayoutAccessor *>(d->document->documentLayout());
QTextCharFormat format = a->formatAccessor(pos);
QTextBlock block = textFrame->firstCursorPosition().block();
- node->m_engine->setCurrentLine(block.layout()->lineForTextPosition(pos - block.position()));
- node->m_engine->addTextObject(QPointF(0, 0), format, QQuickTextNodeEngine::Unselected, d->document,
+ engine.setCurrentLine(block.layout()->lineForTextPosition(pos - block.position()));
+ engine.addTextObject(QPointF(0, 0), format, QQuickTextNodeEngine::Unselected, d->document,
pos, textFrame->frameFormat().position());
nodeStart = pos;
} else {
@@ -1888,13 +1989,13 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
if (block.position() < firstDirtyPos)
continue;
- if (!node->m_engine->hasContents()) {
+ if (!engine.hasContents()) {
nodeOffset = d->document->documentLayout()->blockBoundingRect(block).topLeft();
updateNodeTransform(node, nodeOffset);
nodeStart = block.position();
}
- node->m_engine->addTextBlock(d->document, block, -nodeOffset, d->color, QColor(), selectionStart(), selectionEnd() - 1);
+ engine.addTextBlock(d->document, block, -nodeOffset, d->color, QColor(), selectionStart(), selectionEnd() - 1);
currentNodeSize += block.length();
if ((it.atEnd()) || (firstCleanNode && block.next().position() >= firstCleanNode->startPos())) // last node that needed replacing or last block of the frame
@@ -1903,15 +2004,16 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
QList<int>::const_iterator lowerBound = std::lower_bound(frameBoundaries.constBegin(), frameBoundaries.constEnd(), block.next().position());
if (currentNodeSize > nodeBreakingSize || lowerBound == frameBoundaries.constEnd() || *lowerBound > nodeStart) {
currentNodeSize = 0;
- d->addCurrentTextNodeToRoot(rootNode, node, nodeIterator, nodeStart);
+ d->addCurrentTextNodeToRoot(&engine, rootNode, node, nodeIterator, nodeStart);
node = d->createTextNode();
+ resetEngine(&engine, d->color, d->selectedTextColor, d->selectionColor);
nodeStart = block.next().position();
}
}
}
- d->addCurrentTextNodeToRoot(rootNode, node, nodeIterator, nodeStart);
+ d->addCurrentTextNodeToRoot(&engine, rootNode, node, nodeIterator, nodeStart);
}
- rootNode->frameDecorationsNode->m_engine->addToSceneGraph(rootNode->frameDecorationsNode, QQuickText::Normal, QColor());
+ frameDecorationsEngine.addToSceneGraph(rootNode->frameDecorationsNode, QQuickText::Normal, QColor());
// Now prepend the frame decorations since we want them rendered first, with the text nodes and cursor in front.
rootNode->prependChildNode(rootNode->frameDecorationsNode);
@@ -2016,6 +2118,20 @@ bool QQuickTextEdit::isInputMethodComposing() const
#endif // QT_NO_IM
}
+QQuickTextEditPrivate::ExtraData::ExtraData()
+ : padding(0)
+ , topPadding(0)
+ , leftPadding(0)
+ , rightPadding(0)
+ , bottomPadding(0)
+ , explicitTopPadding(false)
+ , explicitLeftPadding(false)
+ , explicitRightPadding(false)
+ , explicitBottomPadding(false)
+ , implicitResize(true)
+{
+}
+
void QQuickTextEditPrivate::init()
{
Q_Q(QQuickTextEdit);
@@ -2099,7 +2215,7 @@ void QQuickTextEdit::markDirtyNodesForRange(int start, int end, int charDelta)
}
// mark the affected nodes as dirty
- while (it != d->textNodeMap.constEnd()) {
+ while (it != d->textNodeMap.end()) {
if ((*it)->startPos() <= end)
(*it)->setDirty();
else if (charDelta)
@@ -2225,7 +2341,7 @@ void QQuickTextEdit::updateSize()
return;
}
- qreal naturalWidth = d->implicitWidth;
+ qreal naturalWidth = d->implicitWidth - leftPadding() - rightPadding();
qreal newWidth = d->document->idealWidth();
// ### assumes that if the width is set, the text will fill to edges
@@ -2243,13 +2359,14 @@ void QQuickTextEdit::updateSize()
const bool wasInLayout = d->inLayout;
d->inLayout = true;
- setImplicitWidth(naturalWidth);
+ if (d->isImplicitResizeEnabled())
+ setImplicitWidth(naturalWidth + leftPadding() + rightPadding());
d->inLayout = wasInLayout;
if (d->inLayout) // probably the result of a binding loop, but by letting it
return; // get this far we'll get a warning to that effect.
}
if (d->document->textWidth() != width()) {
- d->document->setTextWidth(width());
+ d->document->setTextWidth(width() - leftPadding() - rightPadding());
newWidth = d->document->idealWidth();
}
//### need to confirm cost of always setting these
@@ -2262,14 +2379,16 @@ void QQuickTextEdit::updateSize()
QFontMetricsF fm(d->font);
qreal newHeight = d->document->isEmpty() ? qCeil(fm.height()) : d->document->size().height();
- // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed.
- if (!widthValid() && !d->requireImplicitWidth)
- setImplicitSize(newWidth, newHeight);
- else
- setImplicitHeight(newHeight);
+ if (d->isImplicitResizeEnabled()) {
+ // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed.
+ if (!widthValid() && !d->requireImplicitWidth)
+ setImplicitSize(newWidth + leftPadding() + rightPadding(), newHeight + topPadding() + bottomPadding());
+ else
+ setImplicitHeight(newHeight + topPadding() + bottomPadding());
+ }
- d->xoff = qMax(qreal(0), QQuickTextUtil::alignedX(d->document->size().width(), width(), effectiveHAlign()));
- d->yoff = QQuickTextUtil::alignedY(d->document->size().height(), height(), d->vAlign);
+ d->xoff = leftPadding() + qMax(qreal(0), QQuickTextUtil::alignedX(d->document->size().width(), width() - leftPadding() - rightPadding(), effectiveHAlign()));
+ d->yoff = topPadding() + QQuickTextUtil::alignedY(d->document->size().height(), height() - topPadding() - bottomPadding(), d->vAlign);
setBaselineOffset(fm.ascent() + d->yoff + d->textMargin);
QSizeF size(newWidth, newHeight);
@@ -2416,16 +2535,19 @@ void QQuickTextEditPrivate::handleFocusEvent(QFocusEvent *event)
qGuiApp->inputMethod()->show();
q->connect(QGuiApplication::inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
q, SLOT(q_updateAlignment()));
+#endif
} else {
+#ifndef QT_NO_IM
q->disconnect(QGuiApplication::inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
q, SLOT(q_updateAlignment()));
#endif
+ emit q->editingFinished();
}
}
-void QQuickTextEditPrivate::addCurrentTextNodeToRoot(QSGTransformNode *root, QQuickTextNode *node, TextNodeIterator &it, int startPos)
+void QQuickTextEditPrivate::addCurrentTextNodeToRoot(QQuickTextNodeEngine *engine, QSGTransformNode *root, QQuickTextNode *node, TextNodeIterator &it, int startPos)
{
- node->m_engine->addToSceneGraph(node, QQuickText::Normal, QColor());
+ engine->addToSceneGraph(node, QQuickText::Normal, QColor());
it = textNodeMap.insert(it, new TextNode(startPos, node));
++it;
root->appendChildNode(node);
@@ -2436,7 +2558,6 @@ QQuickTextNode *QQuickTextEditPrivate::createTextNode()
Q_Q(QQuickTextEdit);
QQuickTextNode* node = new QQuickTextNode(q);
node->setUseNativeRenderer(renderType == QQuickTextEdit::NativeRendering);
- node->initEngine(color, selectedTextColor, selectionColor);
return node;
}
@@ -2588,6 +2709,15 @@ bool QQuickTextEditPrivate::isLinkHoveredConnected()
*/
/*!
+ \qmlsignal QtQuick::TextEdit::editingFinished()
+ \since 5.6
+
+ This signal is emitted when the text edit loses focus.
+
+ The corresponding handler is \c onEditingFinished.
+*/
+
+/*!
\qmlproperty string QtQuick::TextEdit::hoveredLink
\since 5.2
@@ -2680,7 +2810,132 @@ void QQuickTextEdit::append(const QString &text)
QString QQuickTextEdit::linkAt(qreal x, qreal y) const
{
Q_D(const QQuickTextEdit);
- return d->control->anchorAt(QPointF(x, y));
+ return d->control->anchorAt(QPointF(x + topPadding(), y + leftPadding()));
+}
+
+/*!
+ \since 5.6
+ \qmlproperty real QtQuick::TextEdit::padding
+ \qmlproperty real QtQuick::TextEdit::topPadding
+ \qmlproperty real QtQuick::TextEdit::leftPadding
+ \qmlproperty real QtQuick::TextEdit::bottomPadding
+ \qmlproperty real QtQuick::TextEdit::rightPadding
+
+ These properties hold the padding around the content. This space is reserved
+ in addition to the contentWidth and contentHeight.
+*/
+qreal QQuickTextEdit::padding() const
+{
+ Q_D(const QQuickTextEdit);
+ return d->padding();
+}
+
+void QQuickTextEdit::setPadding(qreal padding)
+{
+ Q_D(QQuickTextEdit);
+ if (qFuzzyCompare(d->padding(), padding))
+ return;
+
+ d->extra.value().padding = padding;
+ updateSize();
+ if (isComponentComplete()) {
+ d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
+ update();
+ }
+ emit paddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitTopPadding)
+ emit topPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitLeftPadding)
+ emit leftPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitRightPadding)
+ emit rightPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitBottomPadding)
+ emit bottomPaddingChanged();
+}
+
+void QQuickTextEdit::resetPadding()
+{
+ setPadding(0);
+}
+
+qreal QQuickTextEdit::topPadding() const
+{
+ Q_D(const QQuickTextEdit);
+ if (d->extra.isAllocated() && d->extra->explicitTopPadding)
+ return d->extra->topPadding;
+ return d->padding();
+}
+
+void QQuickTextEdit::setTopPadding(qreal padding)
+{
+ Q_D(QQuickTextEdit);
+ d->setTopPadding(padding);
+}
+
+void QQuickTextEdit::resetTopPadding()
+{
+ Q_D(QQuickTextEdit);
+ d->setTopPadding(0, true);
+}
+
+qreal QQuickTextEdit::leftPadding() const
+{
+ Q_D(const QQuickTextEdit);
+ if (d->extra.isAllocated() && d->extra->explicitLeftPadding)
+ return d->extra->leftPadding;
+ return d->padding();
+}
+
+void QQuickTextEdit::setLeftPadding(qreal padding)
+{
+ Q_D(QQuickTextEdit);
+ d->setLeftPadding(padding);
+}
+
+void QQuickTextEdit::resetLeftPadding()
+{
+ Q_D(QQuickTextEdit);
+ d->setLeftPadding(0, true);
+}
+
+qreal QQuickTextEdit::rightPadding() const
+{
+ Q_D(const QQuickTextEdit);
+ if (d->extra.isAllocated() && d->extra->explicitRightPadding)
+ return d->extra->rightPadding;
+ return d->padding();
+}
+
+void QQuickTextEdit::setRightPadding(qreal padding)
+{
+ Q_D(QQuickTextEdit);
+ d->setRightPadding(padding);
+}
+
+void QQuickTextEdit::resetRightPadding()
+{
+ Q_D(QQuickTextEdit);
+ d->setRightPadding(0, true);
+}
+
+qreal QQuickTextEdit::bottomPadding() const
+{
+ Q_D(const QQuickTextEdit);
+ if (d->extra.isAllocated() && d->extra->explicitBottomPadding)
+ return d->extra->bottomPadding;
+ return d->padding();
+}
+
+void QQuickTextEdit::setBottomPadding(qreal padding)
+{
+ Q_D(QQuickTextEdit);
+ d->setBottomPadding(padding);
+}
+
+void QQuickTextEdit::resetBottomPadding()
+{
+ Q_D(QQuickTextEdit);
+ d->setBottomPadding(0, true);
}
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h
index bf6763f772..de72071319 100644
--- a/src/quick/items/qquicktextedit_p.h
+++ b/src/quick/items/qquicktextedit_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKTEXTEDIT_P_H
#define QQUICKTEXTEDIT_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickimplicitsizeitem_p.h"
#include <QtGui/qtextoption.h>
@@ -47,12 +58,6 @@ class QTextBlock;
class Q_QUICK_PRIVATE_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem
{
Q_OBJECT
- Q_ENUMS(VAlignment)
- Q_ENUMS(HAlignment)
- Q_ENUMS(TextFormat)
- Q_ENUMS(WrapMode)
- Q_ENUMS(SelectionMode)
- Q_ENUMS(RenderType)
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
@@ -91,8 +96,13 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem
Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged)
Q_PROPERTY(QUrl baseUrl READ baseUrl WRITE setBaseUrl RESET resetBaseUrl NOTIFY baseUrlChanged)
Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged)
- Q_PROPERTY(QQuickTextDocument *textDocument READ textDocument FINAL REVISION 1)
+ Q_PROPERTY(QQuickTextDocument *textDocument READ textDocument CONSTANT FINAL REVISION 1)
Q_PROPERTY(QString hoveredLink READ hoveredLink NOTIFY linkHovered REVISION 2)
+ Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6)
+ Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6)
+ Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6)
+ Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6)
+ Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6)
public:
QQuickTextEdit(QQuickItem *parent=0);
@@ -103,18 +113,21 @@ public:
AlignHCenter = Qt::AlignHCenter,
AlignJustify = Qt::AlignJustify
};
+ Q_ENUM(HAlignment)
enum VAlignment {
AlignTop = Qt::AlignTop,
AlignBottom = Qt::AlignBottom,
AlignVCenter = Qt::AlignVCenter
};
+ Q_ENUM(VAlignment)
enum TextFormat {
PlainText = Qt::PlainText,
RichText = Qt::RichText,
AutoText = Qt::AutoText
};
+ Q_ENUM(TextFormat)
enum WrapMode { NoWrap = QTextOption::NoWrap,
WordWrap = QTextOption::WordWrap,
@@ -122,15 +135,18 @@ public:
WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT
Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere
};
+ Q_ENUM(WrapMode)
enum SelectionMode {
SelectCharacters,
SelectWords
};
+ Q_ENUM(SelectionMode)
enum RenderType { QtRendering,
NativeRendering
};
+ Q_ENUM(RenderType)
QString text() const;
void setText(const QString &);
@@ -247,6 +263,26 @@ public:
Q_REVISION(3) Q_INVOKABLE QString linkAt(qreal x, qreal y) const;
+ qreal padding() const;
+ void setPadding(qreal padding);
+ void resetPadding();
+
+ qreal topPadding() const;
+ void setTopPadding(qreal padding);
+ void resetTopPadding();
+
+ qreal leftPadding() const;
+ void setLeftPadding(qreal padding);
+ void resetLeftPadding();
+
+ qreal rightPadding() const;
+ void setRightPadding(qreal padding);
+ void resetRightPadding();
+
+ qreal bottomPadding() const;
+ void setBottomPadding(qreal padding);
+ void resetBottomPadding();
+
Q_SIGNALS:
void textChanged();
void contentSizeChanged();
@@ -259,11 +295,11 @@ Q_SIGNALS:
void selectionColorChanged(const QColor &color);
void selectedTextColorChanged(const QColor &color);
void fontChanged(const QFont &font);
- void horizontalAlignmentChanged(HAlignment alignment);
- void verticalAlignmentChanged(VAlignment alignment);
+ void horizontalAlignmentChanged(QQuickTextEdit::HAlignment alignment);
+ void verticalAlignmentChanged(QQuickTextEdit::VAlignment alignment);
void wrapModeChanged();
void lineCountChanged();
- void textFormatChanged(TextFormat textFormat);
+ void textFormatChanged(QQuickTextEdit::TextFormat textFormat);
void readOnlyChanged(bool isReadOnly);
void cursorVisibleChanged(bool isCursorVisible);
void cursorDelegateChanged();
@@ -272,7 +308,7 @@ Q_SIGNALS:
void textMarginChanged(qreal textMargin);
Q_REVISION(1) void selectByKeyboardChanged(bool selectByKeyboard);
void selectByMouseChanged(bool selectByMouse);
- void mouseSelectionModeChanged(SelectionMode mode);
+ void mouseSelectionModeChanged(QQuickTextEdit::SelectionMode mode);
void linkActivated(const QString &link);
Q_REVISION(2) void linkHovered(const QString &link);
void canPasteChanged();
@@ -283,6 +319,12 @@ Q_SIGNALS:
void baseUrlChanged();
void inputMethodHintsChanged();
void renderTypeChanged();
+ Q_REVISION(6) void editingFinished();
+ Q_REVISION(6) void paddingChanged();
+ Q_REVISION(6) void topPaddingChanged();
+ Q_REVISION(6) void leftPaddingChanged();
+ Q_REVISION(6) void rightPaddingChanged();
+ Q_REVISION(6) void bottomPaddingChanged();
public Q_SLOTS:
void selectAll();
@@ -321,6 +363,8 @@ private:
void invalidateFontCaches();
protected:
+ QQuickTextEdit(QQuickTextEditPrivate &dd, QQuickItem *parent = 0);
+
void geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry) Q_DECL_OVERRIDE;
diff --git a/src/quick/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h
index 0cf0f46532..fed0688fd7 100644
--- a/src/quick/items/qquicktextedit_p_p.h
+++ b/src/quick/items/qquicktextedit_p_p.h
@@ -47,18 +47,19 @@
#include "qquicktextedit_p.h"
#include "qquickimplicitsizeitem_p_p.h"
-#include "qquicktextcontrol_p.h"
#include <QtQml/qqml.h>
#include <QtCore/qlist.h>
+#include <private/qlazilyallocated_p.h>
QT_BEGIN_NAMESPACE
class QTextLayout;
class QQuickTextDocumentWithImageResources;
class QQuickTextControl;
class QQuickTextNode;
+class QQuickTextNodeEngine;
-class QQuickTextEditPrivate : public QQuickImplicitSizeItemPrivate
+class Q_QUICK_PRIVATE_EXPORT QQuickTextEditPrivate : public QQuickImplicitSizeItemPrivate
{
public:
Q_DECLARE_PUBLIC(QQuickTextEdit)
@@ -81,10 +82,27 @@ public:
};
typedef QList<Node*>::iterator TextNodeIterator;
+ struct ExtraData {
+ ExtraData();
+
+ qreal padding;
+ qreal topPadding;
+ qreal leftPadding;
+ qreal rightPadding;
+ qreal bottomPadding;
+ bool explicitTopPadding : 1;
+ bool explicitLeftPadding : 1;
+ bool explicitRightPadding : 1;
+ bool explicitBottomPadding : 1;
+ bool implicitResize : 1;
+ };
+ QLazilyAllocated<ExtraData> extra;
+
QQuickTextEditPrivate()
: color(QRgb(0xFF000000)), selectionColor(QRgb(0xFF000080)), selectedTextColor(QRgb(0xFFFFFFFF))
- , textMargin(0.0), xoff(0), yoff(0), font(sourceFont), cursorComponent(0), cursorItem(0), document(0), control(0)
+ , textMargin(0.0), xoff(0), yoff(0)
+ , font(sourceFont), cursorComponent(0), cursorItem(0), document(0), control(0)
, quickDocument(0), lastSelectionStart(0), lastSelectionEnd(0), lineCount(0)
, hAlign(QQuickTextEdit::AlignLeft), vAlign(QQuickTextEdit::AlignTop)
, format(QQuickTextEdit::PlainText), wrapMode(QQuickTextEdit::NoWrap)
@@ -124,13 +142,22 @@ public:
void setNativeCursorEnabled(bool) {}
void handleFocusEvent(QFocusEvent *event);
- void addCurrentTextNodeToRoot(QSGTransformNode *, QQuickTextNode*, TextNodeIterator&, int startPos);
+ void addCurrentTextNodeToRoot(QQuickTextNodeEngine *, QSGTransformNode *, QQuickTextNode*, TextNodeIterator&, int startPos);
QQuickTextNode* createTextNode();
#ifndef QT_NO_IM
Qt::InputMethodHints effectiveInputMethodHints() const;
#endif
+ inline qreal padding() const { return extra.isAllocated() ? extra->padding : 0.0; }
+ void setTopPadding(qreal value, bool reset = false);
+ void setLeftPadding(qreal value, bool reset = false);
+ void setRightPadding(qreal value, bool reset = false);
+ void setBottomPadding(qreal value, bool reset = false);
+
+ bool isImplicitResizeEnabled() const;
+ void setImplicitResizeEnabled(bool enabled);
+
QColor color;
QColor selectionColor;
QColor selectedTextColor;
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index db13a59a4e..ba7142856b 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -90,6 +90,13 @@ QQuickTextInput::QQuickTextInput(QQuickItem* parent)
d->init();
}
+QQuickTextInput::QQuickTextInput(QQuickTextInputPrivate &dd, QQuickItem *parent)
+: QQuickImplicitSizeItem(dd, parent)
+{
+ Q_D(QQuickTextInput);
+ d->init();
+}
+
QQuickTextInput::~QQuickTextInput()
{
}
@@ -222,6 +229,16 @@ QString QQuickTextInputPrivate::realText() const
*/
/*!
+ \qmlproperty string QtQuick::TextInput::font.styleName
+ \since 5.6
+
+ Sets the style name of the font.
+
+ The style name is case insensitive. If set, the font will be matched against style name instead
+ of the font properties \l font.weight, \l font.bold and \l font.italic.
+*/
+
+/*!
\qmlproperty bool QtQuick::TextInput::font.bold
Sets whether the font weight is bold.
@@ -786,8 +803,8 @@ QRectF QQuickTextInput::cursorRectangle() const
QTextLine l = d->m_textLayout.lineForTextPosition(c);
if (!l.isValid())
return QRectF();
- qreal x = l.cursorToX(c) - d->hscroll;
- qreal y = l.y() - d->vscroll;
+ qreal x = l.cursorToX(c) - d->hscroll + leftPadding();
+ qreal y = l.y() - d->vscroll + topPadding();
return QRectF(x, y, 1, l.height());
}
@@ -910,189 +927,6 @@ void QQuickTextInput::setAutoScroll(bool b)
emit autoScrollChanged(d->autoScroll);
}
-#ifndef QT_NO_VALIDATOR
-
-/*!
- \qmltype IntValidator
- \instantiates QIntValidator
- \inqmlmodule QtQuick
- \ingroup qtquick-text-utility
- \brief Defines a validator for integer values
-
- The IntValidator type provides a validator for integer values.
-
- If no \l locale is set IntValidator uses the \l {QLocale::setDefault()}{default locale} to
- interpret the number and will accept locale specific digits, group separators, and positive
- and negative signs. In addition, IntValidator is always guaranteed to accept a number
- formatted according to the "C" locale.
-*/
-
-
-QQuickIntValidator::QQuickIntValidator(QObject *parent)
- : QIntValidator(parent)
-{
-}
-
-/*!
- \qmlproperty string QtQuick::IntValidator::locale
-
- This property holds the name of the locale used to interpret the number.
-
- \sa {QtQml::Qt::locale()}{Qt.locale()}
-*/
-
-QString QQuickIntValidator::localeName() const
-{
- return locale().name();
-}
-
-void QQuickIntValidator::setLocaleName(const QString &name)
-{
- if (locale().name() != name) {
- setLocale(QLocale(name));
- emit localeNameChanged();
- }
-}
-
-void QQuickIntValidator::resetLocaleName()
-{
- QLocale defaultLocale;
- if (locale() != defaultLocale) {
- setLocale(defaultLocale);
- emit localeNameChanged();
- }
-}
-
-/*!
- \qmlproperty int QtQuick::IntValidator::top
-
- This property holds the validator's highest acceptable value.
- By default, this property's value is derived from the highest signed integer available (typically 2147483647).
-*/
-/*!
- \qmlproperty int QtQuick::IntValidator::bottom
-
- This property holds the validator's lowest acceptable value.
- By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
-*/
-
-/*!
- \qmltype DoubleValidator
- \instantiates QDoubleValidator
- \inqmlmodule QtQuick
- \ingroup qtquick-text-utility
- \brief Defines a validator for non-integer numbers
-
- The DoubleValidator type provides a validator for non-integer numbers.
-
- Input is accepted if it contains a double that is within the valid range
- and is in the correct format.
-
- Input is accepected but invalid if it contains a double that is outside
- the range or is in the wrong format; e.g. with too many digits after the
- decimal point or is empty.
-
- Input is rejected if it is not a double.
-
- Note: If the valid range consists of just positive doubles (e.g. 0.0 to
- 100.0) and input is a negative double then it is rejected. If \l notation
- is set to DoubleValidator.StandardNotation, and the input contains more
- digits before the decimal point than a double in the valid range may have,
- it is also rejected. If \l notation is DoubleValidator.ScientificNotation,
- and the input is not in the valid range, it is accecpted but invalid. The
- value may yet become valid by changing the exponent.
-*/
-
-QQuickDoubleValidator::QQuickDoubleValidator(QObject *parent)
- : QDoubleValidator(parent)
-{
-}
-
-/*!
- \qmlproperty string QtQuick::DoubleValidator::locale
-
- This property holds the name of the locale used to interpret the number.
-
- \sa {QtQml::Qt::locale()}{Qt.locale()}
-*/
-
-QString QQuickDoubleValidator::localeName() const
-{
- return locale().name();
-}
-
-void QQuickDoubleValidator::setLocaleName(const QString &name)
-{
- if (locale().name() != name) {
- setLocale(QLocale(name));
- emit localeNameChanged();
- }
-}
-
-void QQuickDoubleValidator::resetLocaleName()
-{
- QLocale defaultLocale;
- if (locale() != defaultLocale) {
- setLocale(defaultLocale);
- emit localeNameChanged();
- }
-}
-
-#endif // QT_NO_VALIDATOR
-
-/*!
- \qmlproperty real QtQuick::DoubleValidator::top
-
- This property holds the validator's maximum acceptable value.
- By default, this property contains a value of infinity.
-*/
-/*!
- \qmlproperty real QtQuick::DoubleValidator::bottom
-
- This property holds the validator's minimum acceptable value.
- By default, this property contains a value of -infinity.
-*/
-/*!
- \qmlproperty int QtQuick::DoubleValidator::decimals
-
- This property holds the validator's maximum number of digits after the decimal point.
- By default, this property contains a value of 1000.
-*/
-/*!
- \qmlproperty enumeration QtQuick::DoubleValidator::notation
- This property holds the notation of how a string can describe a number.
-
- The possible values for this property are:
-
- \list
- \li DoubleValidator.StandardNotation
- \li DoubleValidator.ScientificNotation (default)
- \endlist
-
- If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
-*/
-
-/*!
- \qmltype RegExpValidator
- \instantiates QRegExpValidator
- \inqmlmodule QtQuick
- \ingroup qtquick-text-utility
- \brief Provides a string validator
-
- The RegExpValidator type provides a validator, which counts as valid any string which
- matches a specified regular expression.
-*/
-/*!
- \qmlproperty regExp QtQuick::RegExpValidator::regExp
-
- This property holds the regular expression used for validation.
-
- Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
- matching "a".
-
- By default, this property contains a regular expression with the pattern .* that matches any string.
-*/
-
/*!
\qmlproperty Validator QtQuick::TextInput::validator
@@ -1489,8 +1323,9 @@ void QQuickTextInput::positionAt(QQmlV4Function *args) const
int QQuickTextInputPrivate::positionAt(qreal x, qreal y, QTextLine::CursorPosition position) const
{
- x += hscroll;
- y += vscroll;
+ Q_Q(const QQuickTextInput);
+ x += hscroll - q->leftPadding();
+ y += vscroll - q->topPadding();
QTextLine line = m_textLayout.lineAt(0);
for (int i = 1; i < m_textLayout.lineCount(); ++i) {
QTextLine nextLine = m_textLayout.lineAt(i);
@@ -1701,7 +1536,8 @@ bool QQuickTextInput::event(QEvent* ev)
|| ke == QKeySequence::SelectEndOfBlock
|| ke == QKeySequence::SelectStartOfDocument
|| ke == QKeySequence::SelectAll
- || ke == QKeySequence::SelectEndOfDocument) {
+ || ke == QKeySequence::SelectEndOfDocument
+ || ke == QKeySequence::DeleteCompleteLine) {
ke->accept();
return true;
} else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier
@@ -1748,7 +1584,7 @@ void QQuickTextInputPrivate::ensureVisible(int position, int preeditCursor, int
{
Q_Q(QQuickTextInput);
QTextLine textLine = m_textLayout.lineForTextPosition(position + preeditCursor);
- const qreal width = qMax<qreal>(0, q->width());
+ const qreal width = qMax<qreal>(0, q->width() - q->leftPadding() - q->rightPadding());
qreal cix = 0;
qreal widthUsed = 0;
if (textLine.isValid()) {
@@ -1811,7 +1647,7 @@ void QQuickTextInputPrivate::updateVerticalScroll()
#ifndef QT_NO_IM
const int preeditLength = m_textLayout.preeditAreaText().length();
#endif
- const qreal height = qMax<qreal>(0, q->height());
+ const qreal height = qMax<qreal>(0, q->height() - q->topPadding() - q->bottomPadding());
qreal heightUsed = contentSize.height();
qreal previousScroll = vscroll;
@@ -1879,14 +1715,15 @@ void QQuickTextInput::invalidateFontCaches()
void QQuickTextInput::ensureActiveFocus()
{
- Q_D(QQuickTextInput);
-
bool hadActiveFocus = hasActiveFocus();
forceActiveFocus();
#ifndef QT_NO_IM
+ Q_D(QQuickTextInput);
// re-open input panel on press if already focused
if (hasActiveFocus() && hadActiveFocus && !d->m_readOnly)
qGuiApp->inputMethod()->show();
+#else
+ Q_UNUSED(hadActiveFocus);
#endif
}
@@ -1920,13 +1757,13 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
node->deleteContent();
node->setMatrix(QMatrix4x4());
- QPointF offset(0, 0);
+ QPointF offset(leftPadding(), topPadding());
if (d->autoScroll && d->m_textLayout.lineCount() > 0) {
QFontMetricsF fm(d->font);
// the y offset is there to keep the baseline constant in case we have script changes in the text.
- offset = -QPointF(d->hscroll, d->vscroll + d->m_textLayout.lineAt(0).ascent() - fm.ascent());
+ offset += -QPointF(d->hscroll, d->vscroll + d->m_textLayout.lineAt(0).ascent() - fm.ascent());
} else {
- offset = -QPointF(d->hscroll, d->vscroll);
+ offset += -QPointF(d->hscroll, d->vscroll);
}
if (!d->m_textLayout.text().isEmpty()
@@ -2672,6 +2509,20 @@ bool QQuickTextInput::isInputMethodComposing() const
#endif
}
+QQuickTextInputPrivate::ExtraData::ExtraData()
+ : padding(0)
+ , topPadding(0)
+ , leftPadding(0)
+ , rightPadding(0)
+ , bottomPadding(0)
+ , explicitTopPadding(false)
+ , explicitLeftPadding(false)
+ , explicitRightPadding(false)
+ , explicitBottomPadding(false)
+ , implicitResize(true)
+{
+}
+
void QQuickTextInputPrivate::init()
{
Q_Q(QQuickTextInput);
@@ -2882,7 +2733,7 @@ qreal QQuickTextInputPrivate::getImplicitWidth() const
QTextLine line = layout.createLine();
line.setLineWidth(INT_MAX);
- d->implicitWidth = qCeil(line.naturalTextWidth());
+ d->implicitWidth = qCeil(line.naturalTextWidth()) + q->leftPadding() + q->rightPadding();
layout.endLayout();
}
@@ -2890,6 +2741,75 @@ qreal QQuickTextInputPrivate::getImplicitWidth() const
return implicitWidth;
}
+void QQuickTextInputPrivate::setTopPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickTextInput);
+ qreal oldPadding = q->topPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().topPadding = value;
+ extra.value().explicitTopPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ updateLayout();
+ emit q->topPaddingChanged();
+ }
+}
+
+void QQuickTextInputPrivate::setLeftPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickTextInput);
+ qreal oldPadding = q->leftPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().leftPadding = value;
+ extra.value().explicitLeftPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ updateLayout();
+ emit q->leftPaddingChanged();
+ }
+}
+
+void QQuickTextInputPrivate::setRightPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickTextInput);
+ qreal oldPadding = q->rightPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().rightPadding = value;
+ extra.value().explicitRightPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ updateLayout();
+ emit q->rightPaddingChanged();
+ }
+}
+
+void QQuickTextInputPrivate::setBottomPadding(qreal value, bool reset)
+{
+ Q_Q(QQuickTextInput);
+ qreal oldPadding = q->bottomPadding();
+ if (!reset || extra.isAllocated()) {
+ extra.value().bottomPadding = value;
+ extra.value().explicitBottomPadding = !reset;
+ }
+ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) {
+ updateLayout();
+ emit q->bottomPaddingChanged();
+ }
+}
+
+bool QQuickTextInputPrivate::isImplicitResizeEnabled() const
+{
+ return !extra.isAllocated() || extra->implicitResize;
+}
+
+void QQuickTextInputPrivate::setImplicitResizeEnabled(bool enabled)
+{
+ if (!enabled)
+ extra.value().implicitResize = false;
+ else if (extra.isAllocated())
+ extra->implicitResize = true;
+}
+
void QQuickTextInputPrivate::updateLayout()
{
Q_Q(QQuickTextInput);
@@ -2915,12 +2835,13 @@ void QQuickTextInputPrivate::updateLayout()
line.setLineWidth(INT_MAX);
const bool wasInLayout = inLayout;
inLayout = true;
- q->setImplicitWidth(qCeil(line.naturalTextWidth()));
+ if (isImplicitResizeEnabled())
+ q->setImplicitWidth(qCeil(line.naturalTextWidth()) + q->leftPadding() + q->rightPadding());
inLayout = wasInLayout;
if (inLayout) // probably the result of a binding loop, but by letting it
return; // get this far we'll get a warning to that effect.
}
- qreal lineWidth = q->widthValid() ? q->width() : INT_MAX;
+ qreal lineWidth = q->widthValid() ? q->width() - q->leftPadding() - q->rightPadding() : INT_MAX;
qreal height = 0;
qreal width = 0;
do {
@@ -2946,10 +2867,12 @@ void QQuickTextInputPrivate::updateLayout()
q->polish();
q->update();
- if (!requireImplicitWidth && !q->widthValid())
- q->setImplicitSize(width, height);
- else
- q->setImplicitHeight(height);
+ if (isImplicitResizeEnabled()) {
+ if (!requireImplicitWidth && !q->widthValid())
+ q->setImplicitSize(width + q->leftPadding() + q->rightPadding(), height + q->topPadding() + q->bottomPadding());
+ else
+ q->setImplicitHeight(height + q->topPadding() + q->bottomPadding());
+ }
updateBaselineOffset();
@@ -2971,13 +2894,13 @@ void QQuickTextInputPrivate::updateBaselineOffset()
QFontMetricsF fm(font);
qreal yoff = 0;
if (q->heightValid()) {
- const qreal surplusHeight = q->height() - contentSize.height();
+ const qreal surplusHeight = q->height() - contentSize.height() - q->topPadding() - q->bottomPadding();
if (vAlign == QQuickTextInput::AlignBottom)
yoff = surplusHeight;
else if (vAlign == QQuickTextInput::AlignVCenter)
yoff = surplusHeight/2;
}
- q->setBaselineOffset(fm.ascent() + yoff);
+ q->setBaselineOffset(fm.ascent() + yoff + q->topPadding());
}
#ifndef QT_NO_CLIPBOARD
@@ -3345,7 +3268,7 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
m_preeditCursor = event->preeditString().length();
hasImState = !event->preeditString().isEmpty();
bool cursorVisible = true;
- QList<QTextLayout::FormatRange> formats;
+ QVector<QTextLayout::FormatRange> formats;
for (int i = 0; i < event->attributes().size(); ++i) {
const QInputMethodEvent::Attribute &a = event->attributes().at(i);
if (a.type == QInputMethodEvent::Cursor) {
@@ -3364,7 +3287,7 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
}
}
}
- m_textLayout.setAdditionalFormats(formats);
+ m_textLayout.setFormats(formats);
updateDisplayText(/*force*/ true);
if ((cursorPositionChanged && !emitCursorPositionChanged())
@@ -4273,6 +4196,21 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event)
return;
}
+ if (m_blinkPeriod > 0) {
+ if (m_blinkTimer)
+ q->killTimer(m_blinkTimer);
+
+ m_blinkTimer = q->startTimer(m_blinkPeriod / 2);
+
+ if (m_blinkStatus == 0) {
+ m_blinkStatus = 1;
+
+ updateType = UpdatePaintNode;
+ q->polish();
+ q->update();
+ }
+ }
+
if (m_echoMode == QQuickTextInput::PasswordEchoOnEdit
&& !m_passwordEchoEditing
&& !m_readOnly
@@ -4391,6 +4329,14 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event)
else if (event == QKeySequence::DeleteStartOfWord) {
if (!m_readOnly)
deleteStartOfWord();
+ } else if (event == QKeySequence::DeleteCompleteLine) {
+ if (!m_readOnly) {
+ selectAll();
+#ifndef QT_NO_CLIPBOARD
+ copy();
+#endif
+ del();
+ }
}
#endif // QT_NO_SHORTCUT
else {
@@ -4508,5 +4454,126 @@ void QQuickTextInput::ensureVisible(int position)
updateCursorRectangle(false);
}
+/*!
+ \since 5.6
+ \qmlproperty real QtQuick::TextInput::padding
+ \qmlproperty real QtQuick::TextInput::topPadding
+ \qmlproperty real QtQuick::TextInput::leftPadding
+ \qmlproperty real QtQuick::TextInput::bottomPadding
+ \qmlproperty real QtQuick::TextInput::rightPadding
+
+ These properties hold the padding around the content. This space is reserved
+ in addition to the contentWidth and contentHeight.
+*/
+qreal QQuickTextInput::padding() const
+{
+ Q_D(const QQuickTextInput);
+ return d->padding();
+}
+
+void QQuickTextInput::setPadding(qreal padding)
+{
+ Q_D(QQuickTextInput);
+ if (qFuzzyCompare(d->padding(), padding))
+ return;
+
+ d->extra.value().padding = padding;
+ d->updateLayout();
+ emit paddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitTopPadding)
+ emit topPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitLeftPadding)
+ emit leftPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitRightPadding)
+ emit rightPaddingChanged();
+ if (!d->extra.isAllocated() || !d->extra->explicitBottomPadding)
+ emit bottomPaddingChanged();
+}
+
+void QQuickTextInput::resetPadding()
+{
+ setPadding(0);
+}
+
+qreal QQuickTextInput::topPadding() const
+{
+ Q_D(const QQuickTextInput);
+ if (d->extra.isAllocated() && d->extra->explicitTopPadding)
+ return d->extra->topPadding;
+ return d->padding();
+}
+
+void QQuickTextInput::setTopPadding(qreal padding)
+{
+ Q_D(QQuickTextInput);
+ d->setTopPadding(padding);
+}
+
+void QQuickTextInput::resetTopPadding()
+{
+ Q_D(QQuickTextInput);
+ d->setTopPadding(0, true);
+}
+
+qreal QQuickTextInput::leftPadding() const
+{
+ Q_D(const QQuickTextInput);
+ if (d->extra.isAllocated() && d->extra->explicitLeftPadding)
+ return d->extra->leftPadding;
+ return d->padding();
+}
+
+void QQuickTextInput::setLeftPadding(qreal padding)
+{
+ Q_D(QQuickTextInput);
+ d->setLeftPadding(padding);
+}
+
+void QQuickTextInput::resetLeftPadding()
+{
+ Q_D(QQuickTextInput);
+ d->setLeftPadding(0, true);
+}
+
+qreal QQuickTextInput::rightPadding() const
+{
+ Q_D(const QQuickTextInput);
+ if (d->extra.isAllocated() && d->extra->explicitRightPadding)
+ return d->extra->rightPadding;
+ return d->padding();
+}
+
+void QQuickTextInput::setRightPadding(qreal padding)
+{
+ Q_D(QQuickTextInput);
+ d->setRightPadding(padding);
+}
+
+void QQuickTextInput::resetRightPadding()
+{
+ Q_D(QQuickTextInput);
+ d->setRightPadding(0, true);
+}
+
+qreal QQuickTextInput::bottomPadding() const
+{
+ Q_D(const QQuickTextInput);
+ if (d->extra.isAllocated() && d->extra->explicitBottomPadding)
+ return d->extra->bottomPadding;
+ return d->padding();
+}
+
+void QQuickTextInput::setBottomPadding(qreal padding)
+{
+ Q_D(QQuickTextInput);
+ d->setBottomPadding(padding);
+}
+
+void QQuickTextInput::resetBottomPadding()
+{
+ Q_D(QQuickTextInput);
+ d->setBottomPadding(0, true);
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h
index 3bcbe0fa25..8733b31960 100644
--- a/src/quick/items/qquicktextinput_p.h
+++ b/src/quick/items/qquicktextinput_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKTEXTINPUT_P_H
#define QQUICKTEXTINPUT_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickimplicitsizeitem_p.h"
#include <QtGui/qtextoption.h>
#include <QtGui/qvalidator.h>
@@ -45,13 +56,6 @@ class QValidator;
class Q_QUICK_PRIVATE_EXPORT QQuickTextInput : public QQuickImplicitSizeItem
{
Q_OBJECT
- Q_ENUMS(HAlignment)
- Q_ENUMS(VAlignment)
- Q_ENUMS(WrapMode)
- Q_ENUMS(EchoMode)
- Q_ENUMS(SelectionMode)
- Q_ENUMS(CursorPosition)
- Q_ENUMS(RenderType)
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
Q_PROPERTY(int length READ length NOTIFY textChanged)
@@ -96,6 +100,12 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextInput : public QQuickImplicitSizeItem
Q_PROPERTY(qreal contentHeight READ contentHeight NOTIFY contentSizeChanged)
Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged)
+ Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6)
+ Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6)
+ Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6)
+ Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6)
+ Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6)
+
public:
QQuickTextInput(QQuickItem * parent=0);
~QQuickTextInput();
@@ -108,18 +118,21 @@ public:
Password,
PasswordEchoOnEdit
};
+ Q_ENUM(EchoMode)
enum HAlignment {
AlignLeft = Qt::AlignLeft,
AlignRight = Qt::AlignRight,
AlignHCenter = Qt::AlignHCenter
};
+ Q_ENUM(HAlignment)
enum VAlignment {
AlignTop = Qt::AlignTop,
AlignBottom = Qt::AlignBottom,
AlignVCenter = Qt::AlignVCenter
};
+ Q_ENUM(VAlignment)
enum WrapMode {
NoWrap = QTextOption::NoWrap,
@@ -128,20 +141,24 @@ public:
WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT
Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere
};
+ Q_ENUM(WrapMode)
enum SelectionMode {
SelectCharacters,
SelectWords
};
+ Q_ENUM(SelectionMode)
enum CursorPosition {
CursorBetweenCharacters,
CursorOnCharacter
};
+ Q_ENUM(CursorPosition)
enum RenderType { QtRendering,
NativeRendering
};
+ Q_ENUM(RenderType)
//Auxilliary functions needed to control the TextInput from QML
Q_INVOKABLE void positionAt(QQmlV4Function *args) const;
@@ -260,6 +277,26 @@ public:
qreal contentWidth() const;
qreal contentHeight() const;
+ qreal padding() const;
+ void setPadding(qreal padding);
+ void resetPadding();
+
+ qreal topPadding() const;
+ void setTopPadding(qreal padding);
+ void resetTopPadding();
+
+ qreal leftPadding() const;
+ void setLeftPadding(qreal padding);
+ void resetLeftPadding();
+
+ qreal rightPadding() const;
+ void setRightPadding(qreal padding);
+ void resetRightPadding();
+
+ qreal bottomPadding() const;
+ void setBottomPadding(qreal padding);
+ void resetBottomPadding();
+
Q_SIGNALS:
void textChanged();
void cursorPositionChanged();
@@ -300,12 +337,19 @@ Q_SIGNALS:
void contentSizeChanged();
void inputMethodHintsChanged();
void renderTypeChanged();
+ Q_REVISION(6) void paddingChanged();
+ Q_REVISION(6) void topPaddingChanged();
+ Q_REVISION(6) void leftPaddingChanged();
+ Q_REVISION(6) void rightPaddingChanged();
+ Q_REVISION(6) void bottomPaddingChanged();
private:
void invalidateFontCaches();
void ensureActiveFocus();
protected:
+ QQuickTextInput(QQuickTextInputPrivate &dd, QQuickItem *parent = 0);
+
void geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry) Q_DECL_OVERRIDE;
@@ -360,46 +404,8 @@ private:
Q_DECLARE_PRIVATE(QQuickTextInput)
};
-#ifndef QT_NO_VALIDATOR
-class Q_AUTOTEST_EXPORT QQuickIntValidator : public QIntValidator
-{
- Q_OBJECT
- Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged)
-public:
- QQuickIntValidator(QObject *parent = 0);
-
- QString localeName() const;
- void setLocaleName(const QString &name);
- void resetLocaleName();
-
-Q_SIGNALS:
- void localeNameChanged();
-};
-
-class Q_AUTOTEST_EXPORT QQuickDoubleValidator : public QDoubleValidator
-{
- Q_OBJECT
- Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged)
-public:
- QQuickDoubleValidator(QObject *parent = 0);
-
- QString localeName() const;
- void setLocaleName(const QString &name);
- void resetLocaleName();
-
-Q_SIGNALS:
- void localeNameChanged();
-};
-#endif
-
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickTextInput)
-#ifndef QT_NO_VALIDATOR
-QML_DECLARE_TYPE(QValidator)
-QML_DECLARE_TYPE(QQuickIntValidator)
-QML_DECLARE_TYPE(QQuickDoubleValidator)
-QML_DECLARE_TYPE(QRegExpValidator)
-#endif
#endif // QQUICKTEXTINPUT_P_H
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index 3038573bb3..00d9b2b0fa 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -47,6 +47,7 @@
#include <QtGui/qpalette.h>
#include <QtGui/qtextlayout.h>
#include <QtGui/qstylehints.h>
+#include <private/qlazilyallocated_p.h>
#include "qplatformdefs.h"
@@ -64,13 +65,29 @@ QT_BEGIN_NAMESPACE
class QQuickTextNode;
-class Q_AUTOTEST_EXPORT QQuickTextInputPrivate : public QQuickImplicitSizeItemPrivate
+class Q_QUICK_PRIVATE_EXPORT QQuickTextInputPrivate : public QQuickImplicitSizeItemPrivate
{
public:
Q_DECLARE_PUBLIC(QQuickTextInput)
typedef QQuickTextInput Public;
+ struct ExtraData {
+ ExtraData();
+
+ qreal padding;
+ qreal topPadding;
+ qreal leftPadding;
+ qreal rightPadding;
+ qreal bottomPadding;
+ bool explicitTopPadding : 1;
+ bool explicitLeftPadding : 1;
+ bool explicitRightPadding : 1;
+ bool explicitBottomPadding : 1;
+ bool implicitResize : 1;
+ };
+ QLazilyAllocated<ExtraData> extra;
+
QQuickTextInputPrivate()
: hscroll(0)
, vscroll(0)
@@ -420,6 +437,15 @@ public:
qreal getImplicitWidth() const Q_DECL_OVERRIDE;
+ inline qreal padding() const { return extra.isAllocated() ? extra->padding : 0.0; }
+ void setTopPadding(qreal value, bool reset = false);
+ void setLeftPadding(qreal value, bool reset = false);
+ void setRightPadding(qreal value, bool reset = false);
+ void setBottomPadding(qreal value, bool reset = false);
+
+ bool isImplicitResizeEnabled() const;
+ void setImplicitResizeEnabled(bool enabled);
+
private:
void removeSelectedText();
void internalSetText(const QString &txt, int pos = -1, bool edited = true);
diff --git a/src/quick/items/qquicktextnode.cpp b/src/quick/items/qquicktextnode.cpp
index 010a443d18..d40dedd798 100644
--- a/src/quick/items/qquicktextnode.cpp
+++ b/src/quick/items/qquicktextnode.cpp
@@ -186,17 +186,6 @@ void QQuickTextNode::clearCursor()
m_cursorNode = 0;
}
-void QQuickTextNode::initEngine(const QColor& textColor, const QColor& selectedTextColor, const QColor& selectionColor, const QColor& anchorColor, const QPointF &position)
-{
- m_engine.reset(new QQuickTextNodeEngine);
- m_engine->m_hasContents = false;
- m_engine->setTextColor(textColor);
- m_engine->setSelectedTextColor(selectedTextColor);
- m_engine->setSelectionColor(selectionColor);
- m_engine->setAnchorColor(anchorColor);
- m_engine->setPosition(position);
-}
-
void QQuickTextNode::addRectangleNode(const QRectF &rect, const QColor &color)
{
QSGRenderContext *sg = QQuickItemPrivate::get(m_ownerElement)->sceneGraphRenderContext();
@@ -224,7 +213,12 @@ void QQuickTextNode::addTextDocument(const QPointF &position, QTextDocument *tex
const QColor &selectionColor, const QColor &selectedTextColor,
int selectionStart, int selectionEnd)
{
- initEngine(textColor, selectedTextColor, selectionColor, anchorColor);
+ QQuickTextNodeEngine engine;
+ engine.setTextColor(textColor);
+ engine.setSelectedTextColor(selectedTextColor);
+ engine.setSelectionColor(selectionColor);
+ engine.setAnchorColor(anchorColor);
+ engine.setPosition(position);
QList<QTextFrame *> frames;
frames.append(textDocument->rootFrame());
@@ -232,7 +226,7 @@ void QQuickTextNode::addTextDocument(const QPointF &position, QTextDocument *tex
QTextFrame *textFrame = frames.takeFirst();
frames.append(textFrame->childFrames());
- m_engine->addFrameDecorations(textDocument, textFrame);
+ engine.addFrameDecorations(textDocument, textFrame);
if (textFrame->firstPosition() > textFrame->lastPosition()
&& textFrame->frameFormat().position() != QTextFrameFormat::InFlow) {
@@ -242,23 +236,23 @@ void QQuickTextNode::addTextDocument(const QPointF &position, QTextDocument *tex
QRectF rect = a->frameBoundingRect(textFrame);
QTextBlock block = textFrame->firstCursorPosition().block();
- m_engine->setCurrentLine(block.layout()->lineForTextPosition(pos - block.position()));
- m_engine->addTextObject(rect.topLeft(), format, QQuickTextNodeEngine::Unselected, textDocument,
+ engine.setCurrentLine(block.layout()->lineForTextPosition(pos - block.position()));
+ engine.addTextObject(rect.topLeft(), format, QQuickTextNodeEngine::Unselected, textDocument,
pos, textFrame->frameFormat().position());
} else {
QTextFrame::iterator it = textFrame->begin();
while (!it.atEnd()) {
- Q_ASSERT(!m_engine->currentLine().isValid());
+ Q_ASSERT(!engine.currentLine().isValid());
QTextBlock block = it.currentBlock();
- m_engine->addTextBlock(textDocument, block, position, textColor, anchorColor, selectionStart, selectionEnd);
+ engine.addTextBlock(textDocument, block, position, textColor, anchorColor, selectionStart, selectionEnd);
++it;
}
}
}
- m_engine->addToSceneGraph(this, style, styleColor);
+ engine.addToSceneGraph(this, style, styleColor);
}
void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLayout, const QColor &color,
@@ -268,7 +262,12 @@ void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLay
int selectionStart, int selectionEnd,
int lineStart, int lineCount)
{
- initEngine(color, selectedTextColor, selectionColor, anchorColor, position);
+ QQuickTextNodeEngine engine;
+ engine.setTextColor(color);
+ engine.setSelectedTextColor(selectedTextColor);
+ engine.setSelectionColor(selectionColor);
+ engine.setAnchorColor(anchorColor);
+ engine.setPosition(position);
#ifndef QT_NO_IM
int preeditLength = textLayout->preeditAreaText().length();
@@ -276,7 +275,7 @@ void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLay
#endif
QVarLengthArray<QTextLayout::FormatRange> colorChanges;
- m_engine->mergeFormats(textLayout, &colorChanges);
+ engine.mergeFormats(textLayout, &colorChanges);
lineCount = lineCount >= 0
? qMin(lineStart + lineCount, textLayout->lineCount())
@@ -297,11 +296,11 @@ void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLay
}
#endif
- m_engine->setCurrentLine(line);
- m_engine->addGlyphsForRanges(colorChanges, start, end, selectionStart, selectionEnd);
+ engine.setCurrentLine(line);
+ engine.addGlyphsForRanges(colorChanges, start, end, selectionStart, selectionEnd);
}
- m_engine->addToSceneGraph(this, style, styleColor);
+ engine.addToSceneGraph(this, style, styleColor);
}
void QQuickTextNode::deleteContent()
diff --git a/src/quick/items/qquicktextnode_p.h b/src/quick/items/qquicktextnode_p.h
index c7b9804ea6..c6a1059e8a 100644
--- a/src/quick/items/qquicktextnode_p.h
+++ b/src/quick/items/qquicktextnode_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKTEXTNODE_P_H
#define QQUICKTEXTNODE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuick/qsgnode.h>
#include "qquicktext_p.h"
#include <qglyphrun.h>
@@ -101,14 +112,10 @@ public:
void setUseNativeRenderer(bool on) { m_useNativeRenderer = on; }
private:
- void initEngine(const QColor &textColor, const QColor &selectedTextColor, const QColor &selectionColor, const QColor& anchorColor = QColor()
- , const QPointF &position = QPointF());
-
QSGRectangleNode *m_cursorNode;
QList<QSGTexture *> m_textures;
QQuickItem *m_ownerElement;
bool m_useNativeRenderer;
- QScopedPointer<QQuickTextNodeEngine> m_engine;
friend class QQuickTextEdit;
friend class QQuickTextEditPrivate;
diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp
index efe79b382e..a65b98acd1 100644
--- a/src/quick/items/qquicktextnodeengine.cpp
+++ b/src/quick/items/qquicktextnodeengine.cpp
@@ -42,7 +42,8 @@
#include <QtGui/qtexttable.h>
#include <QtGui/qtextlist.h>
-#include <private/qquicktext_p_p.h>
+#include <private/qquicktext_p.h>
+#include <private/qquicktextdocument_p.h>
#include <private/qtextdocumentlayout_p.h>
#include <private/qtextimagehandler_p.h>
#include <private/qrawfont_p.h>
@@ -882,7 +883,7 @@ void QQuickTextNodeEngine::mergeFormats(QTextLayout *textLayout, QVarLengthArray
if (textLayout == 0)
return;
- QList<QTextLayout::FormatRange> additionalFormats = textLayout->additionalFormats();
+ QVector<QTextLayout::FormatRange> additionalFormats = textLayout->formats();
for (int i=0; i<additionalFormats.size(); ++i) {
QTextLayout::FormatRange additionalFormat = additionalFormats.at(i);
if (additionalFormat.format.hasProperty(QTextFormat::ForegroundBrush)
diff --git a/src/quick/items/qquicktextnodeengine_p.h b/src/quick/items/qquicktextnodeengine_p.h
index 2f6cacf601..2eae950f06 100644
--- a/src/quick/items/qquicktextnodeengine_p.h
+++ b/src/quick/items/qquicktextnodeengine_p.h
@@ -44,6 +44,17 @@
#ifndef QQUICKTEXTNODEENGINE_P_H
#define QQUICKTEXTNODEENGINE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
QT_BEGIN_NAMESPACE
// Engine that takes glyph runs as input, and produces a set of glyph nodes, clip nodes,
@@ -231,8 +242,6 @@ private:
QList<TextDecoration> m_lines;
QVector<BinaryTreeNode> m_processedNodes;
- QList<QPair<QRectF, QImage> > m_images;
-
bool m_hasSelection : 1;
bool m_hasContents : 1;
friend class QQuickTextNode;
diff --git a/src/quick/items/qquicktranslate_p.h b/src/quick/items/qquicktranslate_p.h
index 6dfb5a08b7..09868b5939 100644
--- a/src/quick/items/qquicktranslate_p.h
+++ b/src/quick/items/qquicktranslate_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKTRANSLATE_P_H
#define QQUICKTRANSLATE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickitem.h"
#include <QtGui/qmatrix4x4.h>
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp
index 5b5413a4ba..867f7d9d15 100644
--- a/src/quick/items/qquickview.cpp
+++ b/src/quick/items/qquickview.cpp
@@ -38,8 +38,9 @@
#include "qquickitem_p.h"
#include "qquickitemchangelistener_p.h"
+#include <private/qqmldebugconnector_p.h>
#include <private/qquickprofiler_p.h>
-#include <private/qqmlinspectorservice_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#include <private/qqmlmemoryprofiler_p.h>
#include <QtQml/qqmlengine.h>
@@ -53,7 +54,7 @@ DEFINE_OBJECT_VTABLE(QV4::QQuickRootItemMarker);
QV4::Heap::QQuickRootItemMarker *QV4::QQuickRootItemMarker::create(QQmlEngine *engine, QQuickWindow *window)
{
QV4::ExecutionEngine *e = QQmlEnginePrivate::getV4Engine(engine);
- return e->memoryManager->alloc<QQuickRootItemMarker>(e, window);
+ return e->memoryManager->allocObject<QQuickRootItemMarker>(window);
}
void QV4::QQuickRootItemMarker::markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e)
@@ -86,8 +87,9 @@ void QQuickViewPrivate::init(QQmlEngine* e)
rootItemMarker.set(v4, v);
}
- if (QQmlDebugService::isDebuggingEnabled())
- QQmlInspectorService::instance()->addView(q);
+ QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>();
+ if (service)
+ service->addView(q);
}
QQuickViewPrivate::QQuickViewPrivate()
@@ -97,8 +99,9 @@ QQuickViewPrivate::QQuickViewPrivate()
QQuickViewPrivate::~QQuickViewPrivate()
{
- if (QQmlDebugService::isDebuggingEnabled())
- QQmlInspectorService::instance()->removeView(q_func());
+ QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>();
+ if (service)
+ service->removeView(q_func());
}
void QQuickViewPrivate::execute()
@@ -345,6 +348,9 @@ QQuickView::Status QQuickView::status() const
if (!d->component)
return QQuickView::Null;
+ if (d->component->status() == QQmlComponent::Ready && !d->root)
+ return QQuickView::Error;
+
return QQuickView::Status(d->component->status());
}
@@ -364,6 +370,10 @@ QList<QQmlError> QQuickView::errors() const
QQmlError error;
error.setDescription(QLatin1String("QQuickView: invalid qml engine."));
errs << error;
+ } else if (d->component && d->component->status() == QQmlComponent::Ready && !d->root) {
+ QQmlError error;
+ error.setDescription(QLatin1String("QQuickView: invalid root object."));
+ errs << error;
}
return errs;
@@ -501,14 +511,15 @@ void QQuickViewPrivate::setRootObject(QObject *obj)
if (QQuickItem *sgItem = qobject_cast<QQuickItem *>(obj)) {
root = sgItem;
sgItem->setParentItem(q->QQuickWindow::contentItem());
+ } else if (qobject_cast<QWindow *>(obj)) {
+ qWarning() << "QQuickView does not support using windows as a root item." << endl
+ << endl
+ << "If you wish to create your root window from QML, consider using QQmlApplicationEngine instead." << endl;
} else {
qWarning() << "QQuickView only supports loading of root objects that derive from QQuickItem." << endl
<< endl
- << "If your example is using QML 2, (such as qmlscene) and the .qml file you" << endl
- << "loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur." << endl
- << endl
- << "To load files with 'import QtQuick 1.0' or 'import Qt 4.7', use the" << endl
- << "QDeclarativeView class in the Qt Quick 1 module." << endl;
+ << "Ensure your QML code is written for QtQuick 2, and uses a root that is or" << endl
+ << "inherits from QtQuick's Item (not a Timer, QtObject, etc)." << endl;
delete obj;
root = 0;
}
diff --git a/src/quick/items/qquickview.h b/src/quick/items/qquickview.h
index f094c5a216..80da0ba4f1 100644
--- a/src/quick/items/qquickview.h
+++ b/src/quick/items/qquickview.h
@@ -53,7 +53,6 @@ class Q_QUICK_EXPORT QQuickView : public QQuickWindow
Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(QUrl source READ source WRITE setSource DESIGNABLE true)
- Q_ENUMS(ResizeMode Status)
public:
explicit QQuickView(QWindow *parent = 0);
QQuickView(QQmlEngine* engine, QWindow *parent);
@@ -68,10 +67,12 @@ public:
QQuickItem *rootObject() const;
enum ResizeMode { SizeViewToRootObject, SizeRootObjectToView };
+ Q_ENUM(ResizeMode)
ResizeMode resizeMode() const;
void setResizeMode(ResizeMode);
enum Status { Null, Ready, Loading, Error };
+ Q_ENUM(Status)
Status status() const;
QList<QQmlError> errors() const;
diff --git a/src/quick/items/qquickview_p.h b/src/quick/items/qquickview_p.h
index 6f673368d5..6f970f959d 100644
--- a/src/quick/items/qquickview_p.h
+++ b/src/quick/items/qquickview_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKVIEW_P_H
#define QQUICKVIEW_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickview.h"
#include <QtCore/qurl.h>
@@ -98,7 +109,10 @@ namespace QV4 {
namespace Heap {
struct QQuickRootItemMarker : Object {
- inline QQuickRootItemMarker(QV4::ExecutionEngine *engine, QQuickWindow *window);
+ inline QQuickRootItemMarker(QQuickWindow *window)
+ : window(window)
+ {
+ }
QQuickWindow *window;
};
@@ -115,12 +129,7 @@ struct QQuickRootItemMarker : public Object
};
-inline
-Heap::QQuickRootItemMarker::QQuickRootItemMarker(QV4::ExecutionEngine *engine, QQuickWindow *window)
- : Heap::Object(engine)
- , window(window)
-{
-}
+
}
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 76daa44225..e12b22bb00 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -64,7 +64,6 @@
#include <QtQuick/private/qquickpixmapcache_p.h>
-#include <private/qqmlprofilerservice_p.h>
#include <private/qqmlmemoryprofiler_p.h>
#include <private/qopenglvertexarrayobject_p.h>
@@ -83,8 +82,8 @@ bool QQuickWindowPrivate::defaultAlphaBuffer = false;
void QQuickWindowPrivate::updateFocusItemTransform()
{
- Q_Q(QQuickWindow);
#ifndef QT_NO_IM
+ Q_Q(QQuickWindow);
QQuickItem *focus = q->activeFocusItem();
if (focus && QGuiApplication::focusObject() == focus) {
QQuickItemPrivate *focusPrivate = QQuickItemPrivate::get(focus);
@@ -259,8 +258,7 @@ void QQuickWindowPrivate::polishItems()
// the user.
int recursionSafeguard = INT_MAX;
while (!itemsToPolish.isEmpty() && --recursionSafeguard > 0) {
- QQuickItem *item = *itemsToPolish.begin();
- itemsToPolish.remove(item);
+ QQuickItem *item = itemsToPolish.takeLast();
QQuickItemPrivate::get(item)->polishScheduled = false;
item->updatePolish();
}
@@ -370,12 +368,15 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size)
if (!customRenderStage || !customRenderStage->render()) {
int fboId = 0;
const qreal devicePixelRatio = q->effectiveDevicePixelRatio();
- renderer->setDeviceRect(QRect(QPoint(0, 0), size * devicePixelRatio));
if (renderTargetId) {
+ QRect rect(QPoint(0, 0), renderTargetSize);
fboId = renderTargetId;
- renderer->setViewportRect(QRect(QPoint(0, 0), renderTargetSize));
+ renderer->setDeviceRect(rect);
+ renderer->setViewportRect(rect);
} else {
- renderer->setViewportRect(QRect(QPoint(0, 0), size * devicePixelRatio));
+ QRect rect(QPoint(0, 0), devicePixelRatio * size);
+ renderer->setDeviceRect(rect);
+ renderer->setViewportRect(rect);
}
renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), size));
renderer->setDevicePixelRatio(devicePixelRatio);
@@ -630,6 +631,15 @@ bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *e
if (mouseGrabberItem) {
QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseButtonRelease, p, event, mouseGrabberItem, false));
QCoreApplication::sendEvent(item, me.data());
+
+ if (item->acceptHoverEvents() && p.screenPos() != QGuiApplicationPrivate::lastCursorPosition) {
+ QPointF localMousePos(qInf(), qInf());
+ if (QWindow *w = item->window())
+ localMousePos = item->mapFromScene(w->mapFromGlobal(QGuiApplicationPrivate::lastCursorPosition.toPoint()));
+ QMouseEvent mm(QEvent::MouseMove, localMousePos, QGuiApplicationPrivate::lastCursorPosition,
+ Qt::NoButton, Qt::NoButton, event->modifiers());
+ QCoreApplication::sendEvent(item, &mm);
+ }
if (mouseGrabberItem) // might have ungrabbed due to event
mouseGrabberItem->ungrabMouse();
return me->isAccepted();
@@ -1405,6 +1415,10 @@ bool QQuickWindow::event(QEvent *e)
d->deliverNativeGestureEvent(d->contentItem, static_cast<QNativeGestureEvent*>(e));
break;
#endif
+ case QEvent::ShortcutOverride:
+ if (d->activeFocusItem)
+ sendEvent(d->activeFocusItem, static_cast<QKeyEvent *>(e));
+ return true;
default:
break;
}
@@ -1433,29 +1447,8 @@ void QQuickWindowPrivate::deliverKeyEvent(QKeyEvent *e)
{
Q_Q(QQuickWindow);
-#ifndef QT_NO_SHORTCUT
- // Try looking for a Shortcut before sending key events
- if (e->type() == QEvent::KeyPress
- && QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(q->focusObject(), e))
- return;
-#endif
-
if (activeFocusItem)
q->sendEvent(activeFocusItem, e);
-#ifdef Q_OS_MAC
- else {
- // This is the case for popup windows on Mac, where popup windows get focus
- // in Qt (after exposure) but they are not "key windows" in the Cocoa sense.
- // Therefore, the will never receive key events from Cocoa. Instead, the
- // toplevel non-popup window (the application current "key window") will
- // receive them. (QWidgetWindow does something similar for widgets, by keeping
- // a list of popup windows, and forwarding the key event to the top-most popup.)
- QWindow *focusWindow = QGuiApplication::focusWindow();
- if (focusWindow && focusWindow != q
- && (focusWindow->flags() & Qt::Popup) == Qt::Popup)
- QGuiApplication::sendEvent(focusWindow, e);
- }
-#endif
}
QMouseEvent *QQuickWindowPrivate::cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos)
@@ -2389,7 +2382,9 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem
if (target->childMouseEventFilter(item, targetEvent.data())) {
qCDebug(DBG_TOUCH) << " - first chance intercepted on childMouseEventFilter by " << target;
QVector<int> touchIds;
- for (int i = 0; i < targetEvent->touchPoints().size(); ++i)
+ const int touchPointCount = targetEvent->touchPoints().size();
+ touchIds.reserve(touchPointCount);
+ for (int i = 0; i < touchPointCount; ++i)
touchIds.append(targetEvent->touchPoints().at(i).id());
target->grabTouchPoints(touchIds);
if (mouseGrabberItem) {
@@ -2453,9 +2448,11 @@ bool QQuickWindowPrivate::sendFilteredMouseEvent(QQuickItem *target, QQuickItem
if (!target)
return false;
- bool filtered = false;
-
QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(target);
+ if (targetPrivate->replayingPressEvent)
+ return false;
+
+ bool filtered = false;
if (targetPrivate->filtersChildMouseEvents && !hasFiltered->contains(target)) {
hasFiltered->insert(target);
if (target->childMouseEventFilter(item, event))
@@ -2600,6 +2597,9 @@ bool QQuickWindow::sendEvent(QQuickItem *item, QEvent *e)
QCoreApplication::sendEvent(item, e);
}
break;
+ case QEvent::ShortcutOverride:
+ QCoreApplication::sendEvent(item, e);
+ break;
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
@@ -2733,7 +2733,7 @@ static inline QSGNode *qquickitem_before_paintNode(QQuickItemPrivate *d)
QQuickItem *before = 0;
for (int i=0; i<childItems.size(); ++i) {
QQuickItemPrivate *dd = QQuickItemPrivate::get(childItems.at(i));
- // Perform the same check as the in buildOrderNodeList below.
+ // Perform the same check as the in fetchNextNode below.
if (dd->z() < 0 && (dd->explicitVisible || (dd->extra.isAllocated() && dd->extra->effectRefCount)))
before = childItems.at(i);
else
@@ -2742,13 +2742,9 @@ static inline QSGNode *qquickitem_before_paintNode(QQuickItemPrivate *d)
return Q_UNLIKELY(before) ? QQuickItemPrivate::get(before)->itemNode() : 0;
}
-static QVector<QSGNode *> buildOrderedNodeList(QQuickItemPrivate *itemPriv)
+static QSGNode *fetchNextNode(QQuickItemPrivate *itemPriv, int &ii, bool &returnedPaintNode)
{
QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
- QVector<QSGNode *> desiredNodes;
- desiredNodes.reserve(orderedChildren.size() + 1); // + 1 for the paintNode
-
- int ii = 0;
for (; ii < orderedChildren.count() && orderedChildren.at(ii)->z() < 0; ++ii) {
QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
@@ -2756,11 +2752,14 @@ static QVector<QSGNode *> buildOrderedNodeList(QQuickItemPrivate *itemPriv)
(!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
continue;
- desiredNodes.append(childPrivate->itemNode());
+ ii++;
+ return childPrivate->itemNode();
}
- if (itemPriv->paintNode)
- desiredNodes.append(itemPriv->paintNode);
+ if (itemPriv->paintNode && !returnedPaintNode) {
+ returnedPaintNode = true;
+ return itemPriv->paintNode;
+ }
for (; ii < orderedChildren.count(); ++ii) {
QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
@@ -2768,10 +2767,11 @@ static QVector<QSGNode *> buildOrderedNodeList(QQuickItemPrivate *itemPriv)
(!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
continue;
- desiredNodes.append(childPrivate->itemNode());
+ ii++;
+ return childPrivate->itemNode();
}
- return desiredNodes;
+ return 0;
}
void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
@@ -2874,7 +2874,10 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
}
if (dirty & QQuickItemPrivate::ChildrenUpdateMask) {
- QVector<QSGNode *> desiredNodes = buildOrderedNodeList(itemPriv);
+ int ii = 0;
+ bool fetchedPaintNode = false;
+ QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
+ int desiredNodesSize = orderedChildren.size() + (itemPriv->paintNode ? 1 : 0);
// now start making current state match the promised land of
// desiredNodes. in the case of our current state matching desiredNodes
@@ -2892,14 +2895,9 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
int added = 0;
int removed = 0;
int replaced = 0;
-#if defined(CHILDRENUPDATE_DEBUG)
- // This is slow! Do not do this in a normal/profiling build!
- int initialCount = groupNode->childCount();
-#endif
-
- while (currentNode && desiredNodesProcessed < desiredNodes.size()) {
- QSGNode *desiredNode = desiredNodes.at(desiredNodesProcessed);
+ QSGNode *desiredNode = 0;
+ while (currentNode && (desiredNode = fetchNextNode(itemPriv, ii, fetchedPaintNode))) {
// uh oh... reality and our utopic paradise are diverging!
// we need to reconcile this...
if (currentNode != desiredNode) {
@@ -2923,9 +2921,8 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
// if we didn't process as many nodes as in the new list, then we have
// more nodes at the end of desiredNodes to append to our list.
// this will be the case when adding new nodes, for instance.
- if (desiredNodesProcessed < desiredNodes.size()) {
- for (int i = desiredNodesProcessed; i < desiredNodes.size(); ++i) {
- QSGNode *desiredNode = desiredNodes.at(i);
+ if (desiredNodesProcessed < desiredNodesSize) {
+ while ((desiredNode = fetchNextNode(itemPriv, ii, fetchedPaintNode))) {
if (desiredNode->parent())
desiredNode->parent()->removeChildNode(desiredNode);
groupNode->appendChildNode(desiredNode);
@@ -2942,10 +2939,6 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
removed++;
}
}
-
-#if defined(CHILDRENUPDATE_DEBUG)
- qDebug() << "Done children update for " << itemPriv << "- before:" << initialCount << "after:" << groupNode->childCount() << "added:" << added << "removed:" << removed << "replaced:" << replaced;
-#endif
}
if ((dirty & QQuickItemPrivate::Size) && itemPriv->clipNode()) {
@@ -3311,12 +3304,7 @@ QOpenGLFramebufferObject *QQuickWindow::renderTarget() const
QImage QQuickWindow::grabWindow()
{
Q_D(QQuickWindow);
- if (!isVisible()) {
-
- if (d->context->openglContext()) {
- qWarning("QQuickWindow::grabWindow: scene graph already in use");
- return QImage();
- }
+ if (!isVisible() && !d->context->openglContext()) {
if (!handle() || !size().isValid()) {
qWarning("QQuickWindow::grabWindow: window must be created and have a valid size");
@@ -3334,7 +3322,8 @@ QImage QQuickWindow::grabWindow()
d->syncSceneGraph();
d->renderSceneGraph(size());
- QImage image = qt_gl_read_framebuffer(size() * effectiveDevicePixelRatio(), false, false);
+ bool alpha = format().alphaBufferSize() > 0 && color().alpha() < 255;
+ QImage image = qt_gl_read_framebuffer(size() * effectiveDevicePixelRatio(), alpha, alpha);
d->cleanupNodesOnShutdown();
d->context->invalidate();
context.doneCurrent();
@@ -3386,6 +3375,11 @@ QQmlIncubationController *QQuickWindow::incubationController() const
will delete the GL texture when the texture object is deleted.
\value TextureCanUseAtlas The image can be uploaded into a texture atlas.
+
+ \value TextureIsOpaque The texture will return false for
+ QSGTexture::hasAlphaChannel() and will not be blended. This flag was added
+ in Qt 5.6.
+
*/
/*!
@@ -3590,12 +3584,21 @@ QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image) const
The caller of the function is responsible for deleting the returned texture.
The actual GL texture will be deleted when the texture object is deleted.
- When \a options contains TextureCanUseAtlas the engine may put the image
+ When \a options contains TextureCanUseAtlas, the engine may put the image
into a texture atlas. Textures in an atlas need to rely on
QSGTexture::normalizedTextureSubRect() for their geometry and will not
support QSGTexture::Repeat. Other values from CreateTextureOption are
ignored.
+ When \a options contains TextureIsOpaque, the engine will create an RGB
+ texture which returns false for QSGTexture::hasAlphaChannel(). Opaque
+ textures will in most cases be faster to render. When this flag is not set,
+ the texture will have an alpha channel based on the image's format.
+
+ When \a options contains TextureHasMipmaps, the engine will create a
+ texture which can use mipmap filtering. Mipmapped textures can not be in
+ an atlas.
+
The returned texture will be using \c GL_TEXTURE_2D as texture target and
\c GL_RGBA as internal format. Reimplement QSGTexture to create textures
with different parameters.
@@ -3617,14 +3620,13 @@ QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image) const
QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image, CreateTextureOptions options) const
{
Q_D(const QQuickWindow);
- if (d->context) {
- if (options & TextureCanUseAtlas)
- return d->context->createTexture(image);
- else
- return d->context->createTextureNoAtlas(image);
- }
- else
- return 0;
+ if (!d->context)
+ return 0;
+ uint flags = 0;
+ if (options & TextureCanUseAtlas) flags |= QSGRenderContext::CreateTexture_Atlas;
+ if (options & TextureHasMipmaps) flags |= QSGRenderContext::CreateTexture_Mipmap;
+ if (!(options & TextureIsOpaque)) flags |= QSGRenderContext::CreateTexture_Alpha;
+ return d->context->createTexture(image, flags);
}
@@ -4119,6 +4121,7 @@ void QQuickWindow::resetOpenGLState()
\value BeforeRenderingStage Before rendering.
\value AfterRenderingStage After rendering.
\value AfterSwapStage After the frame is swapped.
+ \value NoStage As soon as possible. This value was added in Qt 5.6.
\sa {Scene Graph and Rendering}
*/
@@ -4144,8 +4147,17 @@ void QQuickWindow::resetOpenGLState()
If the rendering is happening on a different thread, then the job
will happen on the rendering thread.
- \note This function does not trigger rendering; the job
- will be stored run until rendering is triggered elsewhere.
+ If \a stage is \l NoStage, \a job will be run at the earliest opportunity
+ whenever the render thread is not busy rendering a frame. If there is no
+ OpenGL context available or the window is not exposed at the time the job is
+ either posted or handled, it is deleted without executing the run() method.
+ If a non-threaded renderer is in use, the run() method of the job is executed
+ synchronously.
+ The OpenGL context is changed to the renderer context before executing a
+ \l NoStage job.
+
+ \note This function does not trigger rendering; the jobs targeting any other
+ stage than NoStage will be stored run until rendering is triggered elsewhere.
To force the job to run earlier, call QQuickWindow::update();
\sa beforeRendering(), afterRendering(), beforeSynchronizing(),
@@ -4157,16 +4169,22 @@ void QQuickWindow::scheduleRenderJob(QRunnable *job, RenderStage stage)
Q_D(QQuickWindow);
d->renderJobMutex.lock();
- if (stage == BeforeSynchronizingStage)
+ if (stage == BeforeSynchronizingStage) {
d->beforeSynchronizingJobs << job;
- else if (stage == AfterSynchronizingStage)
+ } else if (stage == AfterSynchronizingStage) {
d->afterSynchronizingJobs << job;
- else if (stage == BeforeRenderingStage)
+ } else if (stage == BeforeRenderingStage) {
d->beforeRenderingJobs << job;
- else if (stage == AfterRenderingStage)
+ } else if (stage == AfterRenderingStage) {
d->afterRenderingJobs << job;
- else if (stage == AfterSwapStage)
+ } else if (stage == AfterSwapStage) {
d->afterSwapJobs << job;
+ } else if (stage == NoStage) {
+ if (isExposed())
+ d->windowManager->postJob(this, job);
+ else
+ delete job;
+ }
d->renderJobMutex.unlock();
}
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index f7a1956120..d5bf9fba81 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -69,7 +69,8 @@ public:
TextureHasAlphaChannel = 0x0001,
TextureHasMipmaps = 0x0002,
TextureOwnsGLTexture = 0x0004,
- TextureCanUseAtlas = 0x0008
+ TextureCanUseAtlas = 0x0008,
+ TextureIsOpaque = 0x0010
};
enum RenderStage {
@@ -77,7 +78,8 @@ public:
AfterSynchronizingStage,
BeforeRenderingStage,
AfterRenderingStage,
- AfterSwapStage
+ AfterSwapStage,
+ NoStage
};
Q_DECLARE_FLAGS(CreateTextureOptions, CreateTextureOption)
@@ -85,7 +87,7 @@ public:
enum SceneGraphError {
ContextNotAvailable = 1
};
- Q_ENUMS(SceneGraphError)
+ Q_ENUM(SceneGraphError)
QQuickWindow(QWindow *parent = 0);
explicit QQuickWindow(QQuickRenderControl *renderControl);
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index b63143178b..e475c48b0a 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -202,7 +202,7 @@ public:
QQuickItem *dirtyItemList;
QList<QSGNode *> cleanupNodeList;
- QSet<QQuickItem *> itemsToPolish;
+ QVector<QQuickItem *> itemsToPolish;
void updateDirtyNodes();
void cleanupNodes();
diff --git a/src/quick/items/qquickwindowattached_p.h b/src/quick/items/qquickwindowattached_p.h
index 8138ab216a..98b28430b2 100644
--- a/src/quick/items/qquickwindowattached_p.h
+++ b/src/quick/items/qquickwindowattached_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKWINDOW_ATTACHED_P_H
#define QQUICKWINDOW_ATTACHED_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include <QWindow>
diff --git a/src/quick/items/qquickwindowmodule_p.h b/src/quick/items/qquickwindowmodule_p.h
index bfc51953ca..8396019102 100644
--- a/src/quick/items/qquickwindowmodule_p.h
+++ b/src/quick/items/qquickwindowmodule_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKWINDOWMODULE_H
#define QQUICKWINDOWMODULE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qtquickglobal_p.h>
#include <qquickwindow.h>
#include <qqmlparserstatus.h>
diff --git a/src/quick/qtquick2.cpp b/src/quick/qtquick2.cpp
index 524ee02952..ecf6865895 100644
--- a/src/quick/qtquick2.cpp
+++ b/src/quick/qtquick2.cpp
@@ -38,7 +38,8 @@
#include <private/qquickitemsmodule_p.h>
#include <private/qquickaccessiblefactory_p.h>
-#include <private/qqmlenginedebugservice_p.h>
+#include <private/qqmldebugconnector_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#include <private/qqmldebugstatesdelegate_p.h>
#include <private/qqmlbinding_p.h>
#include <private/qqmlcontext_p.h>
@@ -133,7 +134,6 @@ void QQmlQtQuick2DebugStatesDelegate::updateBinding(QQmlContext *context,
QQmlContextData::get(context), fileName,
line, column);
newBinding->setTarget(property);
- newBinding->setNotifyOnValueChanged(true);
}
state->changeBindingInRevertList(object, propertyName, newBinding);
@@ -187,11 +187,13 @@ void QQmlQtQuick2Module::defineModule()
QAccessible::installFactory(&qQuickAccessibleFactory);
#endif
- if (QQmlDebugService::isDebuggingEnabled()) {
- QQmlEngineDebugService::instance()->setStatesDelegate(
- new QQmlQtQuick2DebugStatesDelegate);
- QQuickProfiler::initialize();
- }
+ QQmlEngineDebugService *debugService = QQmlDebugConnector::service<QQmlEngineDebugService>();
+ if (debugService)
+ debugService->setStatesDelegate(new QQmlQtQuick2DebugStatesDelegate);
+
+ QQmlProfilerService *profilerService = QQmlDebugConnector::service<QQmlProfilerService>();
+ if (profilerService)
+ QQuickProfiler::initialize(profilerService);
}
void QQmlQtQuick2Module::undefineModule()
diff --git a/src/quick/qtquick2_p.h b/src/quick/qtquick2_p.h
index f501323cde..523842a4cd 100644
--- a/src/quick/qtquick2_p.h
+++ b/src/quick/qtquick2_p.h
@@ -34,6 +34,17 @@
#ifndef QTQUICK2_P_H
#define QTQUICK2_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qtquickglobal_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick/scenegraph/coreapi/qsgabstractrenderer_p.h b/src/quick/scenegraph/coreapi/qsgabstractrenderer_p.h
index c5504513f4..17de89bf11 100644
--- a/src/quick/scenegraph/coreapi/qsgabstractrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgabstractrenderer_p.h
@@ -34,6 +34,17 @@
#ifndef QSGABSTRACTRENDERER_P_H
#define QSGABSTRACTRENDERER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qsgabstractrenderer.h"
#include "qsgnode.h"
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index 4b0bc683c2..b1792d27a7 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -61,6 +61,8 @@ QT_BEGIN_NAMESPACE
extern QByteArray qsgShaderRewriter_insertZAttributes(const char *input, QSurfaceFormat::OpenGLContextProfile profile);
+int qt_sg_envInt(const char *name, int defaultValue);
+
namespace QSGBatchRenderer
{
@@ -198,9 +200,9 @@ ShaderManager::Shader *ShaderManager::prepareMaterialNoRewrite(QSGMaterial *mate
void ShaderManager::invalidated()
{
- qDeleteAll(stockShaders.values());
+ qDeleteAll(stockShaders);
stockShaders.clear();
- qDeleteAll(rewrittenShaders.values());
+ qDeleteAll(rewrittenShaders);
rewrittenShaders.clear();
delete blitProgram;
blitProgram = 0;
@@ -487,6 +489,11 @@ void Updater::visitGeometryNode(Node *n)
if (e->batch)
renderer->invalidateBatchAndOverlappingRenderOrders(e->batch);
}
+ if (n->dirtyState & QSGNode::DirtyMaterial) {
+ Element *e = n->element();
+ if (e->batch && e->batch->isMaterialCompatible(e) == BatchBreaksOnCompare)
+ renderer->invalidateBatchAndOverlappingRenderOrders(e->batch);
+ }
}
SHADOWNODE_TRAVERSE(n) visitNode(*child);
@@ -780,30 +787,17 @@ Renderer::Renderer(QSGRenderContext *ctx)
}
m_bufferStrategy = GL_STATIC_DRAW;
- QByteArray strategy = qgetenv("QSG_RENDERER_BUFFER_STRATEGY");
- if (strategy == "dynamic") {
- m_bufferStrategy = GL_DYNAMIC_DRAW;
- } else if (strategy == "stream") {
- m_bufferStrategy = GL_STREAM_DRAW;
- }
-
- m_batchNodeThreshold = 64;
- QByteArray alternateThreshold = qgetenv("QSG_RENDERER_BATCH_NODE_THRESHOLD");
- if (alternateThreshold.length() > 0) {
- bool ok = false;
- int threshold = alternateThreshold.toInt(&ok);
- if (ok)
- m_batchNodeThreshold = threshold;
- }
-
- m_batchVertexThreshold = 1024;
- alternateThreshold = qgetenv("QSG_RENDERER_BATCH_VERTEX_THRESHOLD");
- if (alternateThreshold.length() > 0) {
- bool ok = false;
- int threshold = alternateThreshold.toInt(&ok);
- if (ok)
- m_batchVertexThreshold = threshold;
+ if (Q_UNLIKELY(qEnvironmentVariableIsSet("QSG_RENDERER_BUFFER_STRATEGY"))) {
+ const QByteArray strategy = qgetenv("QSG_RENDERER_BUFFER_STRATEGY");
+ if (strategy == "dynamic")
+ m_bufferStrategy = GL_DYNAMIC_DRAW;
+ else if (strategy == "stream")
+ m_bufferStrategy = GL_STREAM_DRAW;
}
+
+ m_batchNodeThreshold = qt_sg_envInt("QSG_RENDERER_BATCH_NODE_THRESHOLD", 64);
+ m_batchVertexThreshold = qt_sg_envInt("QSG_RENDERER_BATCH_VERTEX_THRESHOLD", 1024);
+
if (Q_UNLIKELY(debug_build() || debug_render())) {
qDebug() << "Batch thresholds: nodes:" << m_batchNodeThreshold << " vertices:" << m_batchVertexThreshold;
qDebug() << "Using buffer strategy:" << (m_bufferStrategy == GL_STATIC_DRAW ? "static" : (m_bufferStrategy == GL_DYNAMIC_DRAW ? "dynamic" : "stream"));
@@ -816,7 +810,8 @@ Renderer::Renderer(QSGRenderContext *ctx)
m_vao->create();
}
- m_useDepthBuffer = ctx->openglContext()->format().depthBufferSize() > 0;
+ bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER");
+ m_useDepthBuffer = useDepth && ctx->openglContext()->format().depthBufferSize() > 0;
}
static void qsg_wipeBuffer(Buffer *buffer, QOpenGLFunctions *funcs)
@@ -1081,6 +1076,11 @@ void Renderer::nodeWasRemoved(Node *node)
if (e) {
e->removed = true;
m_elementsToDelete.add(e);
+
+ if (m_renderNodeElements.isEmpty()) {
+ static bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER");
+ m_useDepthBuffer = useDepth && context()->openglContext()->format().depthBufferSize() > 0;
+ }
}
}
@@ -1213,10 +1213,7 @@ void Renderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state)
if (e->isMaterialBlended != blended) {
m_rebuild |= Renderer::FullRebuild;
e->isMaterialBlended = blended;
- } else if (e->batch) {
- if (e->batch->isMaterialCompatible(e) == BatchBreaksOnCompare)
- invalidateBatchAndOverlappingRenderOrders(e->batch);
- } else {
+ } else if (!e->batch) {
m_rebuild |= Renderer::BuildBatches;
}
}
@@ -2554,8 +2551,15 @@ void Renderer::render()
QSGNodeDumper::dump(rootNode());
}
- if (Q_UNLIKELY(debug_render() || debug_build())) {
+ QElapsedTimer timer;
+ quint64 timeRenderLists = 0;
+ quint64 timePrepareOpaque = 0;
+ quint64 timePrepareAlpha = 0;
+ quint64 timeSorting = 0;
+ quint64 timeUploadOpaque = 0;
+ quint64 timeUploadAlpha = 0;
+ if (Q_UNLIKELY(debug_render() || debug_build())) {
QByteArray type("rebuild:");
if (m_rebuild == 0)
type += " none";
@@ -2571,6 +2575,7 @@ void Renderer::render()
}
qDebug() << "Renderer::render()" << this << type;
+ timer.start();
}
if (m_vao)
@@ -2597,6 +2602,7 @@ void Renderer::render()
}
}
}
+ if (Q_UNLIKELY(debug_render())) timeRenderLists = timer.restart();
for (int i=0; i<m_opaqueBatches.size(); ++i)
m_opaqueBatches.at(i)->cleanupRemovedElements();
@@ -2609,7 +2615,9 @@ void Renderer::render()
if (m_rebuild & BuildBatches) {
prepareOpaqueBatches();
+ if (Q_UNLIKELY(debug_render())) timePrepareOpaque = timer.restart();
prepareAlphaBatches();
+ if (Q_UNLIKELY(debug_render())) timePrepareAlpha = timer.restart();
if (Q_UNLIKELY(debug_build())) {
qDebug() << "Opaque Batches:";
@@ -2629,8 +2637,11 @@ void Renderer::render()
}
}
}
+ } else {
+ if (Q_UNLIKELY(debug_render())) timePrepareOpaque = timePrepareAlpha = timer.restart();
}
+
deleteRemovedElements();
if (m_rebuild != 0) {
@@ -2646,6 +2657,8 @@ void Renderer::render()
m_zRange = 1.0 / (m_nextRenderOrder);
}
+ if (Q_UNLIKELY(debug_render())) timeSorting = timer.restart();
+
int largestVBO = 0;
#ifdef QSG_SEPARATE_INDEX_BUFFER
int largestIBO = 0;
@@ -2660,6 +2673,8 @@ void Renderer::render()
#endif
uploadBatch(b);
}
+ if (Q_UNLIKELY(debug_render())) timeUploadOpaque = timer.restart();
+
if (Q_UNLIKELY(debug_upload())) qDebug() << "Uploading Alpha Batches:";
for (int i=0; i<m_alphaBatches.size(); ++i) {
@@ -2670,6 +2685,7 @@ void Renderer::render()
largestIBO = qMax(b->ibo.size, largestIBO);
#endif
}
+ if (Q_UNLIKELY(debug_render())) timeUploadAlpha = timer.restart();
if (largestVBO * 2 < m_vertexUploadPool.size())
m_vertexUploadPool.resize(largestVBO * 2);
@@ -2680,6 +2696,15 @@ void Renderer::render()
renderBatches();
+ if (Q_UNLIKELY(debug_render())) {
+ qDebug(" -> times: build: %d, prepare(opaque/alpha): %d/%d, sorting: %d, upload(opaque/alpha): %d/%d, render: %d",
+ (int) timeRenderLists,
+ (int) timePrepareOpaque, (int) timePrepareAlpha,
+ (int) timeSorting,
+ (int) timeUploadOpaque, (int) timeUploadAlpha,
+ (int) timer.elapsed());
+ }
+
m_rebuild = 0;
m_renderOrderRebuildLower = -1;
m_renderOrderRebuildUpper = -1;
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index 6b494dbaeb..8cd9e7e3ff 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -34,6 +34,17 @@
#ifndef QSGBATCHRENDERER_P_H
#define QSGBATCHRENDERER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qsgrenderer_p.h>
#include <private/qsgnodeupdater_p.h>
#include <private/qdatabuffer_p.h>
@@ -100,6 +111,7 @@ template <typename Type, int PageSize> class Allocator
{
public:
Allocator()
+ : m_freePage(0)
{
pages.push_back(new AllocatorPage<Type, PageSize>());
}
@@ -112,14 +124,21 @@ public:
Type *allocate()
{
AllocatorPage<Type, PageSize> *p = 0;
- for (int i=0; i<pages.size(); ++i) {
+ for (int i = m_freePage; i < pages.size(); i++) {
if (pages.at(i)->available > 0) {
p = pages.at(i);
+ m_freePage = i;
break;
}
}
+
+ // we couldn't find a free page from m_freePage to the last page.
+ // either there is no free pages, or there weren't any in the area we
+ // scanned: rescanning is expensive, so let's just assume there isn't
+ // one. when an item is released, we'll reset m_freePage anyway.
if (!p) {
p = new AllocatorPage<Type, PageSize>();
+ m_freePage = pages.count();
pages.push_back(p);
}
uint pos = p->blocks[PageSize - p->available];
@@ -151,6 +170,9 @@ public:
delete page;
page = pages.back();
}
+
+ // Reset the free page to force a scan for a new free point.
+ m_freePage = 0;
}
void release(Type *t)
@@ -172,6 +194,7 @@ public:
}
QVector<AllocatorPage<Type, PageSize> *> pages;
+ int m_freePage;
};
@@ -500,8 +523,8 @@ public:
ShaderManager(QSGRenderContext *ctx) : blitProgram(0), visualizeProgram(0), context(ctx) { }
~ShaderManager() {
- qDeleteAll(rewrittenShaders.values());
- qDeleteAll(stockShaders.values());
+ qDeleteAll(rewrittenShaders);
+ qDeleteAll(stockShaders);
}
public Q_SLOTS:
@@ -534,8 +557,8 @@ public:
};
protected:
- void nodeChanged(QSGNode *node, QSGNode::DirtyState state);
- void render();
+ void nodeChanged(QSGNode *node, QSGNode::DirtyState state) Q_DECL_OVERRIDE;
+ void render() Q_DECL_OVERRIDE;
private:
enum ClipTypeBit
@@ -604,7 +627,7 @@ private:
void visualizeOverdraw();
void visualizeOverdraw_helper(Node *node);
void visualizeDrawGeometry(const QSGGeometry *g);
- void setCustomRenderMode(const QByteArray &mode);
+ void setCustomRenderMode(const QByteArray &mode) Q_DECL_OVERRIDE;
QSet<Node *> m_taggedRoots;
QDataBuffer<Element *> m_opaqueRenderList;
diff --git a/src/quick/scenegraph/coreapi/qsggeometry_p.h b/src/quick/scenegraph/coreapi/qsggeometry_p.h
index c52a45b25b..152fcb3427 100644
--- a/src/quick/scenegraph/coreapi/qsggeometry_p.h
+++ b/src/quick/scenegraph/coreapi/qsggeometry_p.h
@@ -34,6 +34,17 @@
#ifndef QSGGEOMETRY_P_H
#define QSGGEOMETRY_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qsggeometry.h"
QT_BEGIN_NAMESPACE
diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.cpp b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
index 367c0b1ee5..5fb0a9867e 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterial.cpp
+++ b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
@@ -64,7 +64,7 @@ const char *QSGMaterialShaderPrivate::loadShaderSource(QOpenGLShader::ShaderType
}
#ifndef QT_NO_DEBUG
-static bool qsg_leak_check = !qgetenv("QML_LEAK_CHECK").isEmpty();
+static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK");
#endif
/*!
diff --git a/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h b/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h
index fab6d00f84..6b31e406ca 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h
+++ b/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h
@@ -34,6 +34,17 @@
#ifndef QSGMATERIALSHADER_P_H
#define QSGMATERIALSHADER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qtquickglobal_p.h>
#include <QOpenGLShader>
diff --git a/src/quick/scenegraph/coreapi/qsgnode.cpp b/src/quick/scenegraph/coreapi/qsgnode.cpp
index 51f3976ed9..c09af7c0a3 100644
--- a/src/quick/scenegraph/coreapi/qsgnode.cpp
+++ b/src/quick/scenegraph/coreapi/qsgnode.cpp
@@ -42,7 +42,7 @@
QT_BEGIN_NAMESPACE
#ifndef QT_NO_DEBUG
-static bool qsg_leak_check = !qgetenv("QML_LEAK_CHECK").isEmpty();
+static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK");
static int qt_node_count = 0;
static void qt_print_node_count()
diff --git a/src/quick/scenegraph/coreapi/qsgnode_p.h b/src/quick/scenegraph/coreapi/qsgnode_p.h
index c455e342c8..7fbb65ef81 100644
--- a/src/quick/scenegraph/coreapi/qsgnode_p.h
+++ b/src/quick/scenegraph/coreapi/qsgnode_p.h
@@ -34,6 +34,17 @@
#ifndef QSGNODE_P_H
#define QSGNODE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qglobal.h>
#include "qsgnode.h"
diff --git a/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp b/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp
index 8293c106b5..f7c9fe7fae 100644
--- a/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp
+++ b/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp
@@ -63,24 +63,6 @@ void QSGNodeUpdater::updateStates(QSGNode *n)
visitNode(n);
}
-/*!
- \fn void QSGNodeUpdater::setToplevelOpacity(qreal opacity)
-
- Sets the toplevel opacity that will be multiplied with the
-
- The default opacity is 1. Any other value will cause artifacts, and is
- primarily useful for debug purposes.
-
- The changing the value during an update pass will have undefined results
- */
-
-/*!
- \fn qreal QSGNodeUpdater::toplevelOpacity() const
-
- Returns the toplevel opacity for the node updater. The default
- value is 1.
- */
-
/*!
Returns true if \a node is has something that blocks it in the chain from
diff --git a/src/quick/scenegraph/coreapi/qsgnodeupdater_p.h b/src/quick/scenegraph/coreapi/qsgnodeupdater_p.h
index e578586a19..2e408d0dbe 100644
--- a/src/quick/scenegraph/coreapi/qsgnodeupdater_p.h
+++ b/src/quick/scenegraph/coreapi/qsgnodeupdater_p.h
@@ -34,6 +34,17 @@
#ifndef QSGNODEUPDATER_P_H
#define QSGNODEUPDATER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qtquickglobal_p.h>
#include <QtGui/private/qdatabuffer_p.h>
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
index a9752cb9a9..775277e588 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
@@ -40,12 +40,21 @@
QT_BEGIN_NAMESPACE
-static bool qsg_sanity_check = qgetenv("QSG_SANITY_CHECK").toInt();
+static const bool qsg_sanity_check = qEnvironmentVariableIntValue("QSG_SANITY_CHECK");
static QElapsedTimer frameTimer;
static qint64 preprocessTime;
static qint64 updatePassTime;
+int qt_sg_envInt(const char *name, int defaultValue)
+{
+ if (Q_LIKELY(!qEnvironmentVariableIsSet(name)))
+ return defaultValue;
+ bool ok = false;
+ int value = qgetenv(name).toInt(&ok);
+ return ok ? value : defaultValue;
+}
+
void QSGBindable::clear(QSGAbstractRenderer::ClearMode mode) const
{
GLuint bits = 0;
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer_p.h b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
index 7e4d52730a..319d0a46b6 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
@@ -34,6 +34,17 @@
#ifndef QSGRENDERER_P_H
#define QSGRENDERER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qsgabstractrenderer.h"
#include "qsgabstractrenderer_p.h"
#include "qsgnode.h"
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index 4f5c4efe14..bf97133e97 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -165,7 +165,9 @@ void QSGDistanceFieldGlyphCache::update()
Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphAdaptationLayerFrame);
QList<QDistanceField> distanceFields;
- for (int i = 0; i < m_pendingGlyphs.size(); ++i) {
+ const int pendingGlyphsSize = m_pendingGlyphs.size();
+ distanceFields.reserve(pendingGlyphsSize);
+ for (int i = 0; i < pendingGlyphsSize; ++i) {
GlyphData &gd = glyphData(m_pendingGlyphs.at(i));
distanceFields.append(QDistanceField(gd.path,
m_pendingGlyphs.at(i),
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index 1253711a94..c7ed398d1b 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -34,6 +34,17 @@
#ifndef QSGADAPTATIONLAYER_P_H
#define QSGADAPTATIONLAYER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuick/qsgnode.h>
#include <QtQuick/qsgtexture.h>
#include <QtCore/qobject.h>
@@ -160,6 +171,7 @@ public:
virtual void setFillColor(const QColor &c) = 0;
virtual void setContentsScale(qreal s) = 0;
virtual void setFastFBOResizing(bool dynamic) = 0;
+ virtual void setTextureSize(const QSize &size) = 0;
virtual QImage toImage() const = 0;
virtual void update() = 0;
@@ -195,6 +207,8 @@ public:
virtual void setFormat(GLenum format) = 0;
virtual void setHasMipmaps(bool mipmap) = 0;
virtual void setDevicePixelRatio(qreal ratio) = 0;
+ virtual void setMirrorHorizontal(bool mirror) = 0;
+ virtual void setMirrorVertical(bool mirror) = 0;
Q_SLOT virtual void markDirtyTexture() = 0;
Q_SLOT virtual void invalidated() = 0;
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 418d571ae6..dd6977e42e 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -41,7 +41,6 @@
#include <QtQuick/private/qsgdefaultglyphnode_p.h>
#include <QtQuick/private/qsgdistancefieldglyphnode_p.h>
#include <QtQuick/private/qsgdistancefieldglyphnode_p_p.h>
-#include <QtQuick/private/qsgshareddistancefieldglyphcache_p.h>
#include <QtQuick/private/qsgatlastexture_p.h>
#include <QtQuick/private/qsgrenderloop_p.h>
#include <QtQuick/private/qsgdefaultlayer_p.h>
@@ -60,15 +59,10 @@
#include <QtQuick/private/qsgtexture_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtCore/private/qabstractanimation_p.h>
-#include <qpa/qplatformintegration.h>
-
-#include <qpa/qplatformsharedgraphicscache.h>
#include <private/qobject_p.h>
#include <qmutex.h>
-#include <private/qqmlprofilerservice_p.h>
-
DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
/*
@@ -140,8 +134,8 @@ static bool qsg_useConsistentTiming()
{
static int use = -1;
if (use < 0) {
- QByteArray fixed = qgetenv("QSG_FIXED_ANIMATION_STEP");
- use = !(fixed.isEmpty() || fixed == "no");
+ use = !qEnvironmentVariableIsEmpty("QSG_FIXED_ANIMATION_STEP") && qgetenv("QSG_FIXED_ANIMATION_STEP") != "no"
+ ? 1 : 0;
qCDebug(QSG_LOG_INFO, "Using %s", bool(use) ? "fixed animation steps" : "sg animation driver");
}
return bool(use);
@@ -303,15 +297,16 @@ QSGContext::QSGContext(QObject *parent) :
QObject(*(new QSGContextPrivate), parent)
{
Q_D(QSGContext);
- QByteArray mode = qgetenv("QSG_DISTANCEFIELD_ANTIALIASING");
- if (!mode.isEmpty())
+ if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QSG_DISTANCEFIELD_ANTIALIASING"))) {
+ const QByteArray mode = qgetenv("QSG_DISTANCEFIELD_ANTIALIASING");
d->distanceFieldAntialiasingDecided = true;
- if (mode == "subpixel")
- d->distanceFieldAntialiasing = QSGGlyphNode::HighQualitySubPixelAntialiasing;
- else if (mode == "subpixel-lowq")
- d->distanceFieldAntialiasing = QSGGlyphNode::LowQualitySubPixelAntialiasing;
- else if (mode == "gray")
- d->distanceFieldAntialiasing = QSGGlyphNode::GrayAntialiasing;
+ if (mode == "subpixel")
+ d->distanceFieldAntialiasing = QSGGlyphNode::HighQualitySubPixelAntialiasing;
+ else if (mode == "subpixel-lowq")
+ d->distanceFieldAntialiasing = QSGGlyphNode::LowQualitySubPixelAntialiasing;
+ else if (mode == "gray")
+ d->distanceFieldAntialiasing = QSGGlyphNode::GrayAntialiasing;
+ }
// Adds compatibility with Qt 5.3 and earlier's QSG_RENDER_TIMING
if (qEnvironmentVariableIsSet("QSG_RENDER_TIMING")) {
@@ -339,12 +334,14 @@ void QSGContext::renderContextInitialized(QSGRenderContext *renderContext)
d->mutex.lock();
if (d->antialiasingMethod == UndecidedAntialiasing) {
- QByteArray aaType = qgetenv("QSG_ANTIALIASING_METHOD");
- if (aaType == "msaa") {
- d->antialiasingMethod = MsaaAntialiasing;
- } else if (aaType == "vertex") {
- d->antialiasingMethod = VertexAntialiasing;
- } else {
+ if (Q_UNLIKELY(qEnvironmentVariableIsSet("QSG_ANTIALIASING_METHOD"))) {
+ const QByteArray aaType = qgetenv("QSG_ANTIALIASING_METHOD");
+ if (aaType == "msaa")
+ d->antialiasingMethod = MsaaAntialiasing;
+ else if (aaType == "vertex")
+ d->antialiasingMethod = VertexAntialiasing;
+ }
+ if (d->antialiasingMethod == UndecidedAntialiasing) {
if (renderContext->openglContext()->format().samples() > 0)
d->antialiasingMethod = MsaaAntialiasing;
else
@@ -572,35 +569,7 @@ QSGDistanceFieldGlyphCache *QSGRenderContext::distanceFieldGlyphCache(const QRaw
QSGDistanceFieldGlyphCache *cache = m_distanceFieldCacheManager->cache(font);
if (!cache) {
- QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
- if (platformIntegration != 0
- && platformIntegration->hasCapability(QPlatformIntegration::SharedGraphicsCache)) {
- QFontEngine *fe = QRawFontPrivate::get(font)->fontEngine;
- if (!fe->faceId().filename.isEmpty()) {
- QByteArray keyName = fe->faceId().filename;
- if (font.style() != QFont::StyleNormal)
- keyName += QByteArray(" I");
- if (font.weight() != QFont::Normal)
- keyName += ' ' + QByteArray::number(font.weight());
- keyName += QByteArray(" DF");
- QPlatformSharedGraphicsCache *sharedGraphicsCache =
- platformIntegration->createPlatformSharedGraphicsCache(keyName);
-
- if (sharedGraphicsCache != 0) {
- sharedGraphicsCache->ensureCacheInitialized(keyName,
- QPlatformSharedGraphicsCache::OpenGLTexture,
- QPlatformSharedGraphicsCache::Alpha8);
-
- cache = new QSGSharedDistanceFieldGlyphCache(keyName,
- sharedGraphicsCache,
- m_distanceFieldCacheManager,
- openglContext(),
- font);
- }
- }
- }
- if (!cache)
- cache = new QSGDefaultDistanceFieldGlyphCache(m_distanceFieldCacheManager, openglContext(), font);
+ cache = new QSGDefaultDistanceFieldGlyphCache(m_distanceFieldCacheManager, openglContext(), font);
m_distanceFieldCacheManager->insertCache(font, cache);
}
@@ -676,7 +645,7 @@ void QSGRenderContext::invalidate()
qDeleteAll(m_texturesToDelete);
m_texturesToDelete.clear();
- qDeleteAll(m_textures.values());
+ qDeleteAll(m_textures);
m_textures.clear();
/* The cleanup of the atlas textures is a bit intriguing.
@@ -767,22 +736,26 @@ QSGDepthStencilBufferManager *QSGRenderContext::depthStencilBufferManager()
will be called with \a image as argument.
*/
-QSGTexture *QSGRenderContext::createTexture(const QImage &image) const
+QSGTexture *QSGRenderContext::createTexture(const QImage &image, uint flags) const
{
- if (!openglContext())
- return 0;
- QSGTexture *t = m_atlasManager->create(image);
- if (t)
- return t;
- return createTextureNoAtlas(image);
-}
+ bool atlas = flags & CreateTexture_Atlas;
+ bool mipmap = flags & CreateTexture_Mipmap;
+ bool alpha = flags & CreateTexture_Alpha;
-QSGTexture *QSGRenderContext::createTextureNoAtlas(const QImage &image) const
-{
- QSGPlainTexture *t = new QSGPlainTexture();
- if (!image.isNull())
- t->setImage(image);
- return t;
+ // The atlas implementation is only supported from the render thread and
+ // does not support mipmaps.
+ if (!mipmap && atlas && openglContext() && QThread::currentThread() == openglContext()->thread()) {
+ QSGTexture *t = m_atlasManager->create(image, alpha);
+ if (t)
+ return t;
+ }
+
+ QSGPlainTexture *texture = new QSGPlainTexture();
+ texture->setImage(image);
+ if (texture->hasAlphaChannel() && !alpha)
+ texture->setHasAlphaChannel(false);
+
+ return texture;
}
/*!
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index d1897f20f9..b1900cba76 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -34,6 +34,17 @@
#ifndef QSGCONTEXT_H
#define QSGCONTEXT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/QObject>
#include <QtCore/qabstractanimation.h>
@@ -88,6 +99,12 @@ class Q_QUICK_PRIVATE_EXPORT QSGRenderContext : public QObject
{
Q_OBJECT
public:
+ enum CreateTextureFlags {
+ CreateTexture_Alpha = 0x1,
+ CreateTexture_Atlas = 0x2,
+ CreateTexture_Mipmap = 0x4
+ };
+
QSGRenderContext(QSGContext *context);
~QSGRenderContext();
@@ -107,8 +124,8 @@ public:
virtual QSGDistanceFieldGlyphCache *distanceFieldGlyphCache(const QRawFont &font);
QSGTexture *textureForFactory(QQuickTextureFactory *factory, QQuickWindow *window);
- virtual QSGTexture *createTexture(const QImage &image) const;
- virtual QSGTexture *createTextureNoAtlas(const QImage &image) const;
+ virtual QSGTexture *createTexture(const QImage &image, uint flags = CreateTexture_Alpha) const;
+
virtual QSGRenderer *createRenderer();
virtual void compile(QSGMaterialShader *shader, QSGMaterial *material, const char *vertexCode = 0, const char *fragmentCode = 0);
diff --git a/src/quick/scenegraph/qsgcontextplugin_p.h b/src/quick/scenegraph/qsgcontextplugin_p.h
index 66f28f3ac0..eb30ed18a4 100644
--- a/src/quick/scenegraph/qsgcontextplugin_p.h
+++ b/src/quick/scenegraph/qsgcontextplugin_p.h
@@ -34,6 +34,17 @@
#ifndef QSGCONTEXTPLUGIN_H
#define QSGCONTEXTPLUGIN_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qtquickglobal_p.h>
#include <QtQuick/qquickimageprovider.h>
#include <QtCore/qplugin.h>
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
index cffe02330a..59fa9850bc 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
@@ -34,6 +34,17 @@
#ifndef QSGDEFAULTDISTANCEFIELDGLYPHCACHE_H
#define QSGDEFAULTDISTANCEFIELDGLYPHCACHE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qsgadaptationlayer_p.h"
#include <QtGui/qopenglfunctions.h>
#include <qopenglshaderprogram.h>
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
index c84e6628a5..9f8788123b 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
@@ -73,7 +73,7 @@ static inline int qsg_device_pixel_ratio(QOpenGLContext *ctx)
else
devicePixelRatio = w->devicePixelRatio();
} else {
- devicePixelRatio = ctx->screen()->devicePixelRatio();
+ devicePixelRatio = ctx->screen() ? ctx->screen()->devicePixelRatio() : qGuiApp->devicePixelRatio();
}
return devicePixelRatio;
}
@@ -104,8 +104,11 @@ char const *const *QSGTextMaskShader::attributeNames() const
}
QSGTextMaskShader::QSGTextMaskShader(QFontEngine::GlyphFormat glyphFormat)
- : QSGMaterialShader(*new QSGMaterialShaderPrivate),
- m_glyphFormat(glyphFormat)
+ : QSGMaterialShader(*new QSGMaterialShaderPrivate)
+ , m_matrix_id(-1)
+ , m_color_id(-1)
+ , m_textureScale_id(-1)
+ , m_glyphFormat(glyphFormat)
{
setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/textmask.vert"));
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/textmask.frag"));
@@ -435,7 +438,9 @@ void QSGTextMaskMaterial::populate(const QPointF &p,
{
Q_ASSERT(m_font.isValid());
QVector<QFixedPoint> fixedPointPositions;
- for (int i=0; i<glyphPositions.size(); ++i)
+ const int glyphPositionsSize = glyphPositions.size();
+ fixedPointPositions.reserve(glyphPositionsSize);
+ for (int i=0; i < glyphPositionsSize; ++i)
fixedPointPositions.append(QFixedPoint::fromPointF(glyphPositions.at(i)));
QTextureGlyphCache *cache = glyphCache();
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.h b/src/quick/scenegraph/qsgdefaultglyphnode_p.h
index 157c5f480c..cd178b932d 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.h
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.h
@@ -34,6 +34,17 @@
#ifndef QSGDEFAULTGLYPHNODE_P_H
#define QSGDEFAULTGLYPHNODE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qsgadaptationlayer_p.h>
#include <QtQuick/qsgnode.h>
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h b/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h
index 736b2de9ea..64d7116bbd 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h
@@ -34,6 +34,17 @@
#ifndef QSGDEFAULTGLYPHNODE_P_P_H
#define QSGDEFAULTGLYPHNODE_P_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qcolor.h>
#include <QtGui/private/qopengltextureglyphcache_p.h>
#include <QtQuick/qsgmaterial.h>
diff --git a/src/quick/scenegraph/qsgdefaultimagenode.cpp b/src/quick/scenegraph/qsgdefaultimagenode.cpp
index db79804908..1f0b0fa9da 100644
--- a/src/quick/scenegraph/qsgdefaultimagenode.cpp
+++ b/src/quick/scenegraph/qsgdefaultimagenode.cpp
@@ -284,10 +284,11 @@ void QSGDefaultImageNode::update()
void QSGDefaultImageNode::preprocess()
{
bool doDirty = false;
- QSGLayer *t = qobject_cast<QSGLayer *>(m_material.texture());
+ QSGDynamicTexture *t = qobject_cast<QSGDynamicTexture *>(m_material.texture());
if (t) {
doDirty = t->updateTexture();
- updateGeometry();
+ if (doDirty)
+ updateGeometry();
}
bool alpha = m_material.flags() & QSGMaterial::Blending;
if (m_material.texture() && alpha != m_material.texture()->hasAlphaChannel()) {
diff --git a/src/quick/scenegraph/qsgdefaultimagenode_p.h b/src/quick/scenegraph/qsgdefaultimagenode_p.h
index c77321ae51..ff611e102b 100644
--- a/src/quick/scenegraph/qsgdefaultimagenode_p.h
+++ b/src/quick/scenegraph/qsgdefaultimagenode_p.h
@@ -35,6 +35,17 @@
#ifndef QSGDEFAULTIMAGENODE_P_H
#define QSGDEFAULTIMAGENODE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qsgadaptationlayer_p.h>
#include <QtQuick/qsgtexturematerial.h>
diff --git a/src/quick/scenegraph/qsgdefaultlayer.cpp b/src/quick/scenegraph/qsgdefaultlayer.cpp
index cca0712ece..fa69f911dd 100644
--- a/src/quick/scenegraph/qsgdefaultlayer.cpp
+++ b/src/quick/scenegraph/qsgdefaultlayer.cpp
@@ -97,6 +97,8 @@ QSGDefaultLayer::QSGDefaultLayer(QSGRenderContext *context)
, m_multisamplingChecked(false)
, m_multisampling(false)
, m_grab(false)
+ , m_mirrorHorizontal(false)
+ , m_mirrorVertical(true)
{
}
@@ -259,6 +261,16 @@ void QSGDefaultLayer::setRecursive(bool recursive)
m_recursive = recursive;
}
+void QSGDefaultLayer::setMirrorHorizontal(bool mirror)
+{
+ m_mirrorHorizontal = mirror;
+}
+
+void QSGDefaultLayer::setMirrorVertical(bool mirror)
+{
+ m_mirrorVertical = mirror;
+}
+
void QSGDefaultLayer::markDirtyTexture()
{
m_dirtyTexture = true;
@@ -365,7 +377,10 @@ void QSGDefaultLayer::grab()
m_renderer->setDeviceRect(m_size);
m_renderer->setViewportRect(m_size);
- QRectF mirrored(m_rect.left(), m_rect.bottom(), m_rect.width(), -m_rect.height());
+ QRectF mirrored(m_mirrorHorizontal ? m_rect.right() : m_rect.left(),
+ m_mirrorVertical ? m_rect.bottom() : m_rect.top(),
+ m_mirrorHorizontal ? -m_rect.width() : m_rect.width(),
+ m_mirrorVertical ? -m_rect.height() : m_rect.height());
m_renderer->setProjectionMatrixToRect(mirrored);
m_renderer->setClearColor(Qt::transparent);
@@ -428,3 +443,11 @@ QImage QSGDefaultLayer::toImage() const
return QImage();
}
+
+QRectF QSGDefaultLayer::normalizedTextureSubRect() const
+{
+ return QRectF(m_mirrorHorizontal ? 1 : 0,
+ m_mirrorVertical ? 0 : 1,
+ m_mirrorHorizontal ? -1 : 1,
+ m_mirrorVertical ? 1 : -1);
+}
diff --git a/src/quick/scenegraph/qsgdefaultlayer_p.h b/src/quick/scenegraph/qsgdefaultlayer_p.h
index 0ba7109ef6..7fb30436d1 100644
--- a/src/quick/scenegraph/qsgdefaultlayer_p.h
+++ b/src/quick/scenegraph/qsgdefaultlayer_p.h
@@ -33,6 +33,17 @@
#ifndef QSGDEFAULTLAYER_P_H
#define QSGDEFAULTLAYER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qsgadaptationlayer_p.h>
#include <private/qsgcontext_p.h>
#include <qsgsimplerectnode.h>
@@ -78,10 +89,18 @@ public:
void setDevicePixelRatio(qreal ratio) Q_DECL_OVERRIDE { m_device_pixel_ratio = ratio; }
+ bool mirrorHorizontal() const { return bool(m_mirrorHorizontal); }
+ void setMirrorHorizontal(bool mirror) Q_DECL_OVERRIDE;
+
+ bool mirrorVertical() const { return bool(m_mirrorVertical); }
+ void setMirrorVertical(bool mirror) Q_DECL_OVERRIDE;
+
void scheduleUpdate() Q_DECL_OVERRIDE;
QImage toImage() const Q_DECL_OVERRIDE;
+ QRectF normalizedTextureSubRect() const Q_DECL_OVERRIDE;
+
public Q_SLOTS:
void markDirtyTexture() Q_DECL_OVERRIDE;
void invalidated() Q_DECL_OVERRIDE;
@@ -115,6 +134,8 @@ private:
uint m_multisamplingChecked : 1;
uint m_multisampling : 1;
uint m_grab : 1;
+ uint m_mirrorHorizontal : 1;
+ uint m_mirrorVertical : 1;
};
#endif // QSGDEFAULTLAYER_P_H
diff --git a/src/quick/scenegraph/qsgdefaultrectanglenode_p.h b/src/quick/scenegraph/qsgdefaultrectanglenode_p.h
index 18e679d8b4..0987b1f9b4 100644
--- a/src/quick/scenegraph/qsgdefaultrectanglenode_p.h
+++ b/src/quick/scenegraph/qsgdefaultrectanglenode_p.h
@@ -35,6 +35,17 @@
#ifndef QSGDEFAULTRECTANGLENODE_P_H
#define QSGDEFAULTRECTANGLENODE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qsgadaptationlayer_p.h>
#include <QtQuick/qsgvertexcolormaterial.h>
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
index 7e602fc0bd..4630e45ecf 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
@@ -200,9 +200,11 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
const QVector<QPointF> positions = m_glyphs.positions();
qreal fontPixelSize = m_glyphs.rawFont().pixelSize();
- QVector<QSGGeometry::TexturedPoint2D> vp;
+ // The template parameters here are assuming that most strings are short, 64
+ // characters or less.
+ QVarLengthArray<QSGGeometry::TexturedPoint2D, 256> vp;
vp.reserve(indexes.size() * 4);
- QVector<ushort> ip;
+ QVarLengthArray<ushort, 384> ip;
ip.reserve(indexes.size() * 6);
qreal maxTexMargin = m_glyph_cache->distanceFieldRadius();
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
index 422e31ad96..6f4b85a5b9 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
@@ -80,6 +80,11 @@ QSGDistanceFieldTextMaterialShader::QSGDistanceFieldTextMaterialShader()
: QSGMaterialShader(),
m_fontScale(1.0)
, m_matrixScale(1.0)
+ , m_matrix_id(-1)
+ , m_textureScale_id(-1)
+ , m_alphaMin_id(-1)
+ , m_alphaMax_id(-1)
+ , m_color_id(-1)
, m_lastAlphaMin(-1)
, m_lastAlphaMax(-1)
{
@@ -260,6 +265,7 @@ protected:
DistanceFieldStyledTextMaterialShader::DistanceFieldStyledTextMaterialShader()
: QSGDistanceFieldTextMaterialShader()
+ , m_styleColor_id(-1)
{
}
@@ -330,6 +336,8 @@ protected:
DistanceFieldOutlineTextMaterialShader::DistanceFieldOutlineTextMaterialShader()
: DistanceFieldStyledTextMaterialShader()
+ , m_outlineAlphaMax0_id(-1)
+ , m_outlineAlphaMax1_id(-1)
{
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/distancefieldoutlinetext.frag"));
}
@@ -411,6 +419,7 @@ protected:
DistanceFieldShiftedStyleTextMaterialShader::DistanceFieldShiftedStyleTextMaterialShader()
: DistanceFieldStyledTextMaterialShader()
+ , m_shift_id(-1)
{
setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/distancefieldshiftedtext.vert"));
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/distancefieldshiftedtext.frag"));
@@ -489,6 +498,8 @@ private:
QSGHiQSubPixelDistanceFieldTextMaterialShader::QSGHiQSubPixelDistanceFieldTextMaterialShader()
: QSGDistanceFieldTextMaterialShader()
+ , m_fontScale_id(-1)
+ , m_vecDelta_id(-1)
{
setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/hiqsubpixeldistancefieldtext.vert"));
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/hiqsubpixeldistancefieldtext.frag"));
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
index bce9379bee..ab171c4fb8 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
@@ -34,6 +34,17 @@
#ifndef QSGDISTANCEFIELDGLYPHNODE_P_H
#define QSGDISTANCEFIELDGLYPHNODE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qsgadaptationlayer_p.h>
#include <QtQuick/qsgtexture.h>
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h
index 9aba26e5f0..d6538a39ed 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h
@@ -34,6 +34,17 @@
#ifndef QSGDISTANCEFIELDGLYPHNODE_P_P_H
#define QSGDISTANCEFIELDGLYPHNODE_P_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuick/qsgmaterial.h>
#include "qsgdistancefieldglyphnode_p.h"
#include "qsgadaptationlayer_p.h"
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index 4d3f34c71c..68947d3a3c 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -102,6 +102,22 @@ void QSGRenderLoop::cleanup()
s_instance = 0;
}
+/*!
+ * Non-threaded render loops immediately run the job if there is a context.
+ */
+void QSGRenderLoop::postJob(QQuickWindow *window, QRunnable *job)
+{
+ Q_ASSERT(window);
+ Q_ASSERT(job);
+
+ if (window->openglContext()) {
+ window->openglContext()->makeCurrent(window);
+ job->run();
+ }
+
+ delete job;
+}
+
class QSGGuiThreadRenderLoop : public QSGRenderLoop
{
Q_OBJECT
@@ -183,13 +199,15 @@ QSGRenderLoop *QSGRenderLoop::instance()
else if (qmlForceThreadedRenderer())
loopType = ThreadedRenderLoop;
- const QByteArray loopName = qgetenv("QSG_RENDER_LOOP");
- if (loopName == QByteArrayLiteral("windows"))
- loopType = WindowsRenderLoop;
- else if (loopName == QByteArrayLiteral("basic"))
- loopType = BasicRenderLoop;
- else if (loopName == QByteArrayLiteral("threaded"))
- loopType = ThreadedRenderLoop;
+ if (Q_UNLIKELY(qEnvironmentVariableIsSet("QSG_RENDER_LOOP"))) {
+ const QByteArray loopName = qgetenv("QSG_RENDER_LOOP");
+ if (loopName == QByteArrayLiteral("windows"))
+ loopType = WindowsRenderLoop;
+ else if (loopName == QByteArrayLiteral("basic"))
+ loopType = BasicRenderLoop;
+ else if (loopName == QByteArrayLiteral("threaded"))
+ loopType = ThreadedRenderLoop;
+ }
switch (loopType) {
case ThreadedRenderLoop:
@@ -382,7 +400,8 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
if (data.grabOnly) {
- grabContent = qt_gl_read_framebuffer(window->size() * window->effectiveDevicePixelRatio(), false, false);
+ bool alpha = window->format().alphaBufferSize() > 0 && window->color().alpha() != 255;
+ grabContent = qt_gl_read_framebuffer(window->size() * window->effectiveDevicePixelRatio(), alpha, alpha);
data.grabOnly = false;
}
diff --git a/src/quick/scenegraph/qsgrenderloop_p.h b/src/quick/scenegraph/qsgrenderloop_p.h
index 4293015b96..1292e7ad9b 100644
--- a/src/quick/scenegraph/qsgrenderloop_p.h
+++ b/src/quick/scenegraph/qsgrenderloop_p.h
@@ -34,6 +34,17 @@
#ifndef QSGRenderLoop_P_H
#define QSGRenderLoop_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtGui/QImage>
#include <QtGui/QSurface>
#include <private/qtquickglobal_p.h>
@@ -45,6 +56,7 @@ class QQuickWindow;
class QSGContext;
class QSGRenderContext;
class QAnimationDriver;
+class QRunnable;
class Q_QUICK_PRIVATE_EXPORT QSGRenderLoop : public QObject
{
@@ -72,6 +84,7 @@ public:
virtual QSGRenderContext *createRenderContext(QSGContext *) const = 0;
virtual void releaseResources(QQuickWindow *window) = 0;
+ virtual void postJob(QQuickWindow *window, QRunnable *job);
void addWindow(QQuickWindow *win) { m_windows.insert(win); }
void removeWindow(QQuickWindow *win) { m_windows.remove(win); }
diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
deleted file mode 100644
index f1cc9d1a86..0000000000
--- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
+++ /dev/null
@@ -1,655 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQuick module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#define EGL_EGLEXT_PROTOTYPES
-#define GL_GLEXT_PROTOTYPES
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#endif
-
-#include "qsgshareddistancefieldglyphcache_p.h"
-
-#include <QtCore/qhash.h>
-#include <QtCore/qthread.h>
-#include <QtCore/qcoreapplication.h>
-
-#include <qpa/qplatformsharedgraphicscache.h>
-
-#include <QtQuick/qquickwindow.h>
-
-// #define QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG
-
-QT_BEGIN_NAMESPACE
-
-namespace {
-
- class QSGInvokeEvent: public QEvent
- {
- public:
- QSGInvokeEvent(QPlatformSharedGraphicsCache *cache,
- const QByteArray &cacheId = QByteArray(),
- const QVector<quint32> &glyphIds = QVector<quint32>(),
- bool inSceneGraphUpdate = false)
- : QEvent(User)
- , m_cache(cache)
- , m_cacheId(cacheId)
- , m_glyphIds(glyphIds)
- , m_inSceneGraphUpdate(inSceneGraphUpdate)
- {}
-
- bool inSceneGraphUpdate() const { return m_inSceneGraphUpdate; }
- QPlatformSharedGraphicsCache *cache() const { return m_cache; }
-
- virtual void invoke() = 0;
- protected:
- QPlatformSharedGraphicsCache *m_cache;
- QByteArray m_cacheId;
- QVector<quint32> m_glyphIds;
- bool m_inSceneGraphUpdate;
- };
-
- class QSGReleaseItemsEvent: public QSGInvokeEvent
- {
- public:
- QSGReleaseItemsEvent(QPlatformSharedGraphicsCache *cache,
- const QByteArray &cacheId,
- const QVector<quint32> &glyphIds,
- bool inSceneGraphUpdate)
- : QSGInvokeEvent(cache, cacheId, glyphIds, inSceneGraphUpdate)
- {
- }
-
- void invoke()
- {
- m_cache->releaseItems(m_cacheId, m_glyphIds);
- }
- };
-
- class QSGRequestItemsEvent: public QSGInvokeEvent
- {
- public:
- QSGRequestItemsEvent(QPlatformSharedGraphicsCache *cache,
- const QByteArray &cacheId,
- const QVector<quint32> &glyphIds,
- bool inSceneGraphUpdate)
- : QSGInvokeEvent(cache, cacheId, glyphIds, inSceneGraphUpdate)
- {
- }
-
- void invoke()
- {
- m_cache->requestItems(m_cacheId, m_glyphIds);
- }
- };
-
- class QSGInsertItemsEvent: public QSGInvokeEvent
- {
- public:
- QSGInsertItemsEvent(QPlatformSharedGraphicsCache *cache,
- const QByteArray &cacheId,
- const QVector<quint32> &glyphIds,
- const QVector<QImage> &images,
- bool inSceneGraphUpdate)
- : QSGInvokeEvent(cache, cacheId, glyphIds, inSceneGraphUpdate)
- , m_images(images)
- {
- }
-
- void invoke()
- {
- m_cache->insertItems(m_cacheId, m_glyphIds, m_images);
- }
-
- private:
- QVector<QImage> m_images;
- };
-
- class QSGEndRequestBatchEvent: public QSGInvokeEvent
- {
- public:
- QSGEndRequestBatchEvent(QPlatformSharedGraphicsCache *cache)
- : QSGInvokeEvent(cache)
- {
- }
-
- void invoke()
- {
- if (m_cache->requestBatchStarted())
- m_cache->endRequestBatch();
- }
- };
-
- class QSGMainThreadInvoker: public QObject
- {
- public:
- bool event(QEvent *e)
- {
- if (e->type() == QEvent::User) {
- Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread());
-
- QSGInvokeEvent *invokeEvent = static_cast<QSGInvokeEvent *>(e);
- if (invokeEvent->inSceneGraphUpdate()) {
- QPlatformSharedGraphicsCache *cache = invokeEvent->cache();
- if (!cache->requestBatchStarted())
- cache->beginRequestBatch();
- }
-
- static_cast<QSGInvokeEvent *>(e)->invoke();
- return true;
- }
- return QObject::event(e);
- }
-
- static QSGMainThreadInvoker *instance()
- {
- if (m_invoker == 0) {
- m_invoker = new QSGMainThreadInvoker;
- m_invoker->moveToThread(QCoreApplication::instance()->thread());
- }
-
- return m_invoker;
- }
-
- private:
- static QSGMainThreadInvoker *m_invoker;
- };
-
- QSGMainThreadInvoker* QSGMainThreadInvoker::m_invoker = 0;
-}
-
-QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteArray &cacheId,
- QPlatformSharedGraphicsCache *sharedGraphicsCache,
- QSGDistanceFieldGlyphCacheManager *man,
- QOpenGLContext *c,
- const QRawFont &font)
- : QSGDistanceFieldGlyphCache(man, c, font)
- , m_cacheId(cacheId)
- , m_sharedGraphicsCache(sharedGraphicsCache)
- , m_isInSceneGraphUpdate(false)
- , m_hasPostedEvents(false)
-{
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
- qDebug("QSGSharedDistanceFieldGlyphCache with id %s created in thread %p",
- cacheId.constData(), QThread::currentThreadId());
-#endif
-
- Q_ASSERT(sizeof(glyph_t) == sizeof(quint32));
- Q_ASSERT(sharedGraphicsCache != 0);
-
- connect(sharedGraphicsCache, SIGNAL(itemsMissing(QByteArray,QVector<quint32>)),
- this, SLOT(reportItemsMissing(QByteArray,QVector<quint32>)),
- Qt::DirectConnection);
- connect(sharedGraphicsCache, SIGNAL(itemsAvailable(QByteArray,void*,QVector<quint32>,QVector<QPoint>)),
- this, SLOT(reportItemsAvailable(QByteArray,void*,QVector<quint32>,QVector<QPoint>)),
- Qt::DirectConnection);
- connect(sharedGraphicsCache, SIGNAL(itemsUpdated(QByteArray,void*,QVector<quint32>,QVector<QPoint>)),
- this, SLOT(reportItemsUpdated(QByteArray,void*,QVector<quint32>,QVector<QPoint>)),
- Qt::DirectConnection);
- connect(sharedGraphicsCache, SIGNAL(itemsInvalidated(QByteArray,QVector<quint32>)),
- this, SLOT(reportItemsInvalidated(QByteArray,QVector<quint32>)),
- Qt::DirectConnection);
-
- Q_ASSERT(c);
- QQuickWindow *window = static_cast<QQuickWindow *>(c->surface());
- Q_ASSERT(window != 0);
-
- connect(window, SIGNAL(beforeSynchronizing()), this, SLOT(sceneGraphUpdateStarted()),
- Qt::DirectConnection);
- connect(window, SIGNAL(beforeRendering()), this, SLOT(sceneGraphUpdateDone()),
- Qt::DirectConnection);
-}
-
-QSGSharedDistanceFieldGlyphCache::~QSGSharedDistanceFieldGlyphCache()
-{
- {
- QHash<glyph_t, void *>::const_iterator it = m_bufferForGlyph.constBegin();
- while (it != m_bufferForGlyph.constEnd()) {
- m_sharedGraphicsCache->dereferenceBuffer(it.value());
- ++it;
- }
- }
-
- {
- QHash<quint32, PendingGlyph>::const_iterator it = m_pendingReadyGlyphs.constBegin();
- while (it != m_pendingReadyGlyphs.constEnd()) {
- m_sharedGraphicsCache->dereferenceBuffer(it.value().buffer);
- ++it;
- }
- }
-}
-
-void QSGSharedDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyphs)
-{
- typedef QSet<glyph_t>::const_iterator GlyphSetConstIt;
-
- QMutexLocker locker(&m_pendingGlyphsMutex);
-
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
- qDebug("QSGSharedDistanceFieldGlyphCache::requestGlyphs() called for %s (%d glyphs)",
- m_cacheId.constData(), glyphs.size());
-#endif
-
- m_requestedGlyphsThatHaveNotBeenReturned.unite(glyphs);
- m_requestedGlyphs.unite(glyphs);
-
- QVector<quint32> glyphsVector;
- glyphsVector.reserve(glyphs.size());
-
- for (GlyphSetConstIt it = glyphs.constBegin(), cend = glyphs.constEnd(); it != cend; ++it) {
- Q_ASSERT(!m_bufferForGlyph.contains(*it));
- glyphsVector.append(*it);
- }
-
- m_hasPostedEvents = true;
- QSGMainThreadInvoker *invoker = QSGMainThreadInvoker::instance();
- QCoreApplication::postEvent(invoker, new QSGRequestItemsEvent(m_sharedGraphicsCache,
- m_cacheId,
- glyphsVector,
- m_isInSceneGraphUpdate));
-}
-
-void QSGSharedDistanceFieldGlyphCache::waitForGlyphs()
-{
- Q_ASSERT(!m_isInSceneGraphUpdate);
- if (m_isInSceneGraphUpdate) {
- qWarning("QSGSharedDistanceFieldGlyphCache::waitForGlyphs: Called from inside "
- "scenegraph update. Will freeze.");
- }
-
- {
- QMutexLocker locker(&m_pendingGlyphsMutex);
- while (!m_requestedGlyphsThatHaveNotBeenReturned.isEmpty())
- m_pendingGlyphsCondition.wait(&m_pendingGlyphsMutex);
- }
-}
-
-void QSGSharedDistanceFieldGlyphCache::storeGlyphs(const QList<QDistanceField> &glyphs)
-{
- {
- QMutexLocker locker(&m_pendingGlyphsMutex);
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
- qDebug("QSGSharedDistanceFieldGlyphCache::storeGlyphs() called for %s (%d glyphs)",
- m_cacheId.constData(), glyphs.size());
-#endif
-
- int glyphCount = glyphs.size();
- QVector<quint32> glyphIds(glyphCount);
- QVector<QImage> images(glyphCount);
- for (int i = 0; i < glyphs.size(); ++i) {
- const QDistanceField &df = glyphs.at(i);
- m_requestedGlyphsThatHaveNotBeenReturned.insert(df.glyph());
- glyphIds[i] = df.glyph();
- // ### TODO: Handle QDistanceField in QPlatformSharedGraphicsCache
- images[i] = df.toImage(QImage::Format_Indexed8);
- }
-
- m_hasPostedEvents = true;
- QSGMainThreadInvoker *invoker = QSGMainThreadInvoker::instance();
- QCoreApplication::postEvent(invoker, new QSGInsertItemsEvent(m_sharedGraphicsCache,
- m_cacheId,
- glyphIds,
- images,
- m_isInSceneGraphUpdate));
- }
-
- processPendingGlyphs();
-}
-
-void QSGSharedDistanceFieldGlyphCache::referenceGlyphs(const QSet<glyph_t> &glyphs)
-{
- Q_UNUSED(glyphs);
-
- // Intentionally empty. Not required in this implementation, since the glyphs are reference
- // counted outside and releaseGlyphs() will only be called when there are no more references.
-}
-
-void QSGSharedDistanceFieldGlyphCache::releaseGlyphs(const QSet<glyph_t> &glyphs)
-{
- typedef QSet<glyph_t>::const_iterator GlyphSetConstIt;
-
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
- qDebug("QSGSharedDistanceFieldGlyphCache::releaseGlyphs() called for %s (%d glyphs)",
- m_cacheId.constData(), glyphs.size());
-#endif
-
- m_requestedGlyphs.subtract(glyphs);
-
- QVector<quint32> glyphsVector;
- glyphsVector.reserve(glyphs.size());
-
- for (GlyphSetConstIt glyphsIt = glyphs.constBegin(), cend = glyphs.constEnd(); glyphsIt != cend; ++glyphsIt) {
- QHash<glyph_t, void *>::iterator bufferIt = m_bufferForGlyph.find(*glyphsIt);
- if (bufferIt != m_bufferForGlyph.end()) {
- void *buffer = bufferIt.value();
- removeGlyph(*glyphsIt);
- m_bufferForGlyph.erase(bufferIt);
- Q_ASSERT(!m_bufferForGlyph.contains(*glyphsIt));
-
- if (!m_sharedGraphicsCache->dereferenceBuffer(buffer)) {
-#if !defined(QT_NO_DEBUG)
- bufferIt = m_bufferForGlyph.begin();
- while (bufferIt != m_bufferForGlyph.end()) {
- Q_ASSERT(bufferIt.value() != buffer);
- ++bufferIt;
- }
-#endif
- }
- }
-
- glyphsVector.append(*glyphsIt);
- }
-
- m_hasPostedEvents = true;
- QSGMainThreadInvoker *mainThreadInvoker = QSGMainThreadInvoker::instance();
- QCoreApplication::postEvent(mainThreadInvoker, new QSGReleaseItemsEvent(m_sharedGraphicsCache,
- m_cacheId,
- glyphsVector,
- m_isInSceneGraphUpdate));
-}
-
-void QSGSharedDistanceFieldGlyphCache::registerOwnerElement(QQuickItem *ownerElement)
-{
- Owner &owner = m_registeredOwners[ownerElement];
- if (owner.ref == 0) {
- owner.item = ownerElement;
-
- bool ok = connect(this, SIGNAL(glyphsPending()), ownerElement, SLOT(triggerPreprocess()));
- Q_ASSERT_X(ok, Q_FUNC_INFO, "QML element that owns a glyph node must have triggerPreprocess() slot");
- Q_UNUSED(ok);
- }
- ++owner.ref;
-}
-
-void QSGSharedDistanceFieldGlyphCache::unregisterOwnerElement(QQuickItem *ownerElement)
-{
- QHash<QQuickItem *, Owner>::iterator it = m_registeredOwners.find(ownerElement);
- if (it != m_registeredOwners.end() && --it->ref <= 0) {
- if (it->item)
- disconnect(this, SIGNAL(glyphsPending()), ownerElement, SLOT(triggerPreprocess()));
- m_registeredOwners.erase(it);
- }
-}
-
-namespace {
- struct TextureContent {
- QSize size;
- QVector<glyph_t> glyphs;
- };
-}
-
-void QSGSharedDistanceFieldGlyphCache::processPendingGlyphs()
-{
- Q_ASSERT(QThread::currentThread() == thread());
-
- waitForGlyphs();
-
- {
- QMutexLocker locker(&m_pendingGlyphsMutex);
- if (m_pendingMissingGlyphs.isEmpty()
- && m_pendingReadyGlyphs.isEmpty()
- && m_pendingInvalidatedGlyphs.isEmpty()) {
- return;
- }
-
- {
- QVector<glyph_t> pendingMissingGlyphs;
- pendingMissingGlyphs.reserve(m_pendingMissingGlyphs.size());
-
- QSet<glyph_t>::const_iterator it = m_pendingMissingGlyphs.constBegin();
- while (it != m_pendingMissingGlyphs.constEnd()) {
- pendingMissingGlyphs.append(*it);
- ++it;
- }
-
- markGlyphsToRender(pendingMissingGlyphs);
- }
-
- {
- QVector<glyph_t> filteredPendingInvalidatedGlyphs;
- filteredPendingInvalidatedGlyphs.reserve(m_pendingInvalidatedGlyphs.size());
-
- QSet<glyph_t>::const_iterator it = m_pendingInvalidatedGlyphs.constBegin();
- while (it != m_pendingInvalidatedGlyphs.constEnd()) {
- bool rerequestGlyph = false;
-
- // The glyph was invalidated right after being posted as ready, we throw away
- // the ready glyph and rerequest it to be certain
- QHash<quint32, PendingGlyph>::iterator pendingGlyphIt = m_pendingReadyGlyphs.find(*it);
- if (pendingGlyphIt != m_pendingReadyGlyphs.end()) {
- m_sharedGraphicsCache->dereferenceBuffer(pendingGlyphIt.value().buffer);
- pendingGlyphIt = m_pendingReadyGlyphs.erase(pendingGlyphIt);
- rerequestGlyph = true;
- }
-
- void *bufferId = m_bufferForGlyph.value(*it, 0);
- if (bufferId != 0) {
- m_sharedGraphicsCache->dereferenceBuffer(bufferId);
- m_bufferForGlyph.remove(*it);
- rerequestGlyph = true;
- }
-
- if (rerequestGlyph)
- filteredPendingInvalidatedGlyphs.append(*it);
-
- ++it;
- }
-
- // If this cache is still using the glyphs, reset the texture held by them, and mark them
- // to be rendered again since they are still needed.
- if (!filteredPendingInvalidatedGlyphs.isEmpty()) {
- setGlyphsTexture(filteredPendingInvalidatedGlyphs, Texture());
- markGlyphsToRender(filteredPendingInvalidatedGlyphs);
- }
- }
-
- {
- QList<GlyphPosition> glyphPositions;
-
- QHash<void *, TextureContent> textureContentForBuffer;
- {
- QHash<quint32, PendingGlyph>::iterator it = m_pendingReadyGlyphs.begin();
- while (it != m_pendingReadyGlyphs.end()) {
- void *currentGlyphBuffer = m_bufferForGlyph.value(it.key(), 0);
- if (currentGlyphBuffer != 0) {
- if (!m_sharedGraphicsCache->dereferenceBuffer(currentGlyphBuffer)) {
- Q_ASSERT(!textureContentForBuffer.contains(currentGlyphBuffer));
- }
- }
-
- PendingGlyph &pendingGlyph = it.value();
-
- // We don't ref or deref the buffer here, since it was already referenced when
- // added to the pending ready glyphs
- m_bufferForGlyph[it.key()] = pendingGlyph.buffer;
-
- textureContentForBuffer[pendingGlyph.buffer].size = pendingGlyph.bufferSize;
- textureContentForBuffer[pendingGlyph.buffer].glyphs.append(it.key());
-
- GlyphPosition glyphPosition;
- glyphPosition.glyph = it.key();
- glyphPosition.position = pendingGlyph.position;
-
- glyphPositions.append(glyphPosition);
-
- ++it;
- }
- }
-
- setGlyphsPosition(glyphPositions);
-
- {
- QHash<void *, TextureContent>::const_iterator it = textureContentForBuffer.constBegin();
- while (it != textureContentForBuffer.constEnd()) {
- Texture texture;
- texture.textureId = m_sharedGraphicsCache->textureIdForBuffer(it.key());
- texture.size = m_sharedGraphicsCache->sizeOfBuffer(it.key());
-
- setGlyphsTexture(it.value().glyphs, texture);
-
- ++it;
- }
- }
- }
-
- m_pendingMissingGlyphs.clear();
- m_pendingInvalidatedGlyphs.clear();
- m_pendingReadyGlyphs.clear();
- }
-}
-
-void QSGSharedDistanceFieldGlyphCache::reportItemsAvailable(const QByteArray &cacheId,
- void *bufferId,
- const QVector<quint32> &itemIds,
- const QVector<QPoint> &positions)
-{
- bool requestedItemsInList = false;
- {
- QMutexLocker locker(&m_pendingGlyphsMutex);
- if (m_cacheId != cacheId)
- return;
-
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
- qDebug("QSGSharedDistanceFieldGlyphCache::reportItemsAvailable() called for %s (%d glyphs)",
- cacheId.constData(), itemIds.size());
-#endif
-
- for (int i=0; i<itemIds.size(); ++i) {
- if (m_requestedGlyphsThatHaveNotBeenReturned.contains(itemIds.at(i))) {
- requestedItemsInList = true;
- break;
- }
- }
- }
-
- if (requestedItemsInList)
- reportItemsUpdated(cacheId, bufferId,itemIds, positions);
-}
-
-void QSGSharedDistanceFieldGlyphCache::reportItemsUpdated(const QByteArray &cacheId,
- void *bufferId,
- const QVector<quint32> &itemIds,
- const QVector<QPoint> &positions)
-{
- {
- QMutexLocker locker(&m_pendingGlyphsMutex);
- if (m_cacheId != cacheId)
- return;
-
- Q_ASSERT(itemIds.size() == positions.size());
-
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
- qDebug("QSGSharedDistanceFieldGlyphCache::reportItemsUpdated() called for %s (%d glyphs)",
- cacheId.constData(), itemIds.size());
-#endif
-
- for (int i=0; i<itemIds.size(); ++i) {
- if (m_requestedGlyphs.contains(itemIds.at(i))) {
- PendingGlyph &pendingGlyph = m_pendingReadyGlyphs[itemIds.at(i)];
- void *oldBuffer = pendingGlyph.buffer;
-
- pendingGlyph.buffer = bufferId;
- pendingGlyph.position = positions.at(i);
-
- m_sharedGraphicsCache->referenceBuffer(bufferId);
- if (oldBuffer != 0)
- m_sharedGraphicsCache->dereferenceBuffer(oldBuffer);
-
- m_requestedGlyphsThatHaveNotBeenReturned.remove(itemIds.at(i));
- }
- }
- }
-
- m_pendingGlyphsCondition.wakeAll();
- emit glyphsPending();
-}
-
-void QSGSharedDistanceFieldGlyphCache::reportItemsInvalidated(const QByteArray &cacheId,
- const QVector<quint32> &itemIds)
-{
- {
- QMutexLocker locker(&m_pendingGlyphsMutex);
- if (m_cacheId != cacheId)
- return;
-
- for (int i=0; i<itemIds.size(); ++i) {
- if (m_requestedGlyphs.contains(itemIds.at(i)))
- m_pendingInvalidatedGlyphs.insert(itemIds.at(i));
- }
- }
-
- emit glyphsPending();
-}
-
-
-void QSGSharedDistanceFieldGlyphCache::reportItemsMissing(const QByteArray &cacheId,
- const QVector<quint32> &itemIds)
-{
- {
- QMutexLocker locker(&m_pendingGlyphsMutex);
- if (m_cacheId != cacheId)
- return;
-
-#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
- qDebug("QSGSharedDistanceFieldGlyphCache::reportItemsMissing() called for %s (%d glyphs)",
- cacheId.constData(), itemIds.size());
-#endif
-
- for (int i=0; i<itemIds.size(); ++i) {
- if (m_requestedGlyphsThatHaveNotBeenReturned.remove(itemIds.at(i)))
- m_pendingMissingGlyphs.insert(itemIds.at(i));
- }
- }
-
- m_pendingGlyphsCondition.wakeAll();
- emit glyphsPending();
-}
-
-void QSGSharedDistanceFieldGlyphCache::sceneGraphUpdateStarted()
-{
- m_isInSceneGraphUpdate = true;
- m_hasPostedEvents = false;
-}
-
-void QSGSharedDistanceFieldGlyphCache::sceneGraphUpdateDone()
-{
- m_isInSceneGraphUpdate = false;
-
- if (m_hasPostedEvents) {
- QSGMainThreadInvoker *invoker = QSGMainThreadInvoker::instance();
- QCoreApplication::postEvent(invoker, new QSGEndRequestBatchEvent(m_sharedGraphicsCache));
- m_hasPostedEvents = false;
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h
deleted file mode 100644
index aee77c49c6..0000000000
--- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQuick module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSGSHAREDDISTANCEFIELDGLYPHCACHE_H
-#define QSGSHAREDDISTANCEFIELDGLYPHCACHE_H
-
-#include <QtCore/qwaitcondition.h>
-#include <private/qsgadaptationlayer_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QPlatformSharedGraphicsCache;
-class QSGSharedDistanceFieldGlyphCache : public QObject, public QSGDistanceFieldGlyphCache
-{
- Q_OBJECT
-public:
- explicit QSGSharedDistanceFieldGlyphCache(const QByteArray &cacheId,
- QPlatformSharedGraphicsCache *sharedGraphicsCache,
- QSGDistanceFieldGlyphCacheManager *man,
- QOpenGLContext *c,
- const QRawFont &font);
- ~QSGSharedDistanceFieldGlyphCache();
-
- void registerOwnerElement(QQuickItem *ownerElement);
- void unregisterOwnerElement(QQuickItem *ownerElement);
- void processPendingGlyphs();
-
- void requestGlyphs(const QSet<glyph_t> &glyphs);
- void referenceGlyphs(const QSet<glyph_t> &glyphs);
- void storeGlyphs(const QList<QDistanceField> &glyphs);
- void releaseGlyphs(const QSet<glyph_t> &glyphs);
-
-Q_SIGNALS:
- void glyphsPending();
-
-private Q_SLOTS:
- void reportItemsMissing(const QByteArray &cacheId, const QVector<quint32> &itemIds);
- void reportItemsAvailable(const QByteArray &cacheId,
- void *bufferId,
- const QVector<quint32> &itemIds,
- const QVector<QPoint> &positions);
- void reportItemsUpdated(const QByteArray &cacheId,
- void *bufferId,
- const QVector<quint32> &itemIds,
- const QVector<QPoint> &positions);
- void reportItemsInvalidated(const QByteArray &cacheId, const QVector<quint32> &itemIds);
-
- void sceneGraphUpdateStarted();
- void sceneGraphUpdateDone();
-
-private:
- void waitForGlyphs();
- void saveTexture(GLuint textureId, int width, int height);
-
- QSet<quint32> m_requestedGlyphsThatHaveNotBeenReturned;
- QSet<quint32> m_requestedGlyphs;
- QWaitCondition m_pendingGlyphsCondition;
- QByteArray m_cacheId;
- QPlatformSharedGraphicsCache *m_sharedGraphicsCache;
- QMutex m_pendingGlyphsMutex;
-
- QSet<glyph_t> m_pendingInvalidatedGlyphs;
- QSet<glyph_t> m_pendingMissingGlyphs;
-
- struct PendingGlyph
- {
- PendingGlyph() : buffer(0) {}
-
- void *buffer;
- QSize bufferSize;
- QPoint position;
- };
-
- struct Owner
- {
- Owner() : ref(0) {}
- Owner(const Owner &o) : item(o.item), ref(o.ref) {}
- Owner &operator =(const Owner &o) { item = o.item; ref = o.ref; return *this; }
-
- QPointer<QQuickItem> item;
- int ref;
- };
-
- QHash<quint32, PendingGlyph> m_pendingReadyGlyphs;
- QHash<glyph_t, void *> m_bufferForGlyph;
- QHash<QQuickItem *, Owner> m_registeredOwners;
-
- bool m_isInSceneGraphUpdate;
- bool m_hasPostedEvents;
-};
-
-QT_END_NAMESPACE
-
-#endif // QSGSHAREDDISTANCEFIELDGLYPHCACHE_H
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 2cebbaf484..8d6bea9e67 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -54,7 +54,8 @@
#include <private/qquickanimatorcontroller_p.h>
#include <private/qquickprofiler_p.h>
-#include <private/qqmldebugservice_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qqmldebugconnector_p.h>
#include <private/qquickshadereffectnode_p.h>
@@ -147,6 +148,9 @@ const QEvent::Type WM_TryRelease = QEvent::Type(QEvent::User + 4);
// called.
const QEvent::Type WM_Grab = QEvent::Type(QEvent::User + 5);
+// Passed by the window when there is a render job to run
+const QEvent::Type WM_PostJob = QEvent::Type(QEvent::User + 6);
+
template <typename T> T *windowFor(const QList<T> &list, QQuickWindow *window)
{
for (int i=0; i<list.size(); ++i) {
@@ -200,6 +204,14 @@ public:
QImage *image;
};
+class WMJobEvent : public WMWindowEvent
+{
+public:
+ WMJobEvent(QQuickWindow *c, QRunnable *postedJob)
+ : WMWindowEvent(c, WM_PostJob), job(postedJob) {}
+ ~WMJobEvent() { delete job; }
+ QRunnable *job;
+};
class QSGRenderThreadEventQueue : public QQueue<QEvent *>
{
@@ -345,7 +357,6 @@ bool QSGRenderThread::event(QEvent *e)
if (window) {
QQuickWindowPrivate::get(window)->fireAboutToStop();
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- window removed";
- gl->doneCurrent();
window = 0;
}
waitCondition.wakeOne();
@@ -396,20 +407,22 @@ bool QSGRenderThread::event(QEvent *e)
case WM_Grab: {
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_Grab";
WMGrabEvent *ce = static_cast<WMGrabEvent *>(e);
- Q_ASSERT(ce->window == window);
+ Q_ASSERT(ce->window);
+ Q_ASSERT(ce->window == window || !window);
mutex.lock();
- if (window) {
- gl->makeCurrent(window);
+ if (ce->window) {
+ gl->makeCurrent(ce->window);
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- sync scene graph";
- QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
+ QQuickWindowPrivate *d = QQuickWindowPrivate::get(ce->window);
d->syncSceneGraph();
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- rendering scene graph";
- QQuickWindowPrivate::get(window)->renderSceneGraph(windowSize);
+ QQuickWindowPrivate::get(ce->window)->renderSceneGraph(ce->window->size());
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- grabbing result";
- *ce->image = qt_gl_read_framebuffer(windowSize * window->effectiveDevicePixelRatio(), false, false);
+ bool alpha = ce->window->format().alphaBufferSize() > 0 && ce->window->color().alpha() != 255;
+ *ce->image = qt_gl_read_framebuffer(windowSize * ce->window->effectiveDevicePixelRatio(), alpha, alpha);
}
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- waking gui to handle result";
waitCondition.wakeOne();
@@ -417,6 +430,20 @@ bool QSGRenderThread::event(QEvent *e)
return true;
}
+ case WM_PostJob: {
+ qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_PostJob";
+ WMJobEvent *ce = static_cast<WMJobEvent *>(e);
+ Q_ASSERT(ce->window == window);
+ if (window) {
+ gl->makeCurrent(window);
+ ce->job->run();
+ delete ce->job;
+ ce->job = 0;
+ qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- job done";
+ }
+ return true;
+ }
+
case WM_RequestRepaint:
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_RequestPaint";
// When GUI posts this event, it is followed by a polishAndSync, so we mustn't
@@ -666,7 +693,7 @@ void QSGRenderThread::run()
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "run()";
animatorDriver = sgrc->sceneGraphContext()->createAnimationDriver(0);
animatorDriver->install();
- if (QQmlDebugService::isDebuggingEnabled())
+ if (QQmlDebugConnector::service<QQmlProfilerService>())
QQuickProfiler::registerAnimationCallback();
while (active) {
@@ -993,20 +1020,20 @@ void QSGThreadedRenderLoop::maybeUpdate(Window *w)
if (!QCoreApplication::instance())
return;
+ if (!w || !w->thread->isRunning())
+ return;
+
QThread *current = QThread::currentThread();
if (current != QCoreApplication::instance()->thread() && (current != w->thread || !m_lockedForSync)) {
qWarning() << "Updates can only be scheduled from GUI thread or from QQuickItem::updatePaintNode()";
return;
}
- if (!w || !w->thread->isRunning()) {
- return;
- }
qCDebug(QSG_LOG_RENDERLOOP) << "update from item" << w->window;
// Call this function from the Gui thread later as startTimer cannot be
// called from the render thread.
- if (QThread::currentThread() == w->thread) {
+ if (current == w->thread) {
qCDebug(QSG_LOG_RENDERLOOP) << "- on render thread";
w->updateDuringSync = true;
return;
@@ -1242,6 +1269,18 @@ QImage QSGThreadedRenderLoop::grab(QQuickWindow *window)
return result;
}
+/*!
+ * Posts a new job event to the render thread.
+ * Returns true if posting succeeded.
+ */
+void QSGThreadedRenderLoop::postJob(QQuickWindow *window, QRunnable *job)
+{
+ Window *w = windowFor(m_windows, window);
+ if (w && w->thread && w->thread->window)
+ w->thread->postEvent(new WMJobEvent(window, job));
+ else
+ delete job;
+}
#include "qsgthreadedrenderloop.moc"
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop_p.h b/src/quick/scenegraph/qsgthreadedrenderloop_p.h
index d5ffbf10a3..3fef6a0a88 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop_p.h
+++ b/src/quick/scenegraph/qsgthreadedrenderloop_p.h
@@ -34,6 +34,17 @@
#ifndef QSGTHREADEDRENDERLOOP_P_H
#define QSGTHREADEDRENDERLOOP_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/QThread>
#include <QtGui/QOpenGLContext>
#include <private/qsgcontext_p.h>
@@ -71,6 +82,7 @@ public:
void releaseResources(QQuickWindow *window);
bool event(QEvent *);
+ void postJob(QQuickWindow *window, QRunnable *job);
bool interleaveIncubation() const;
diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
index 7fd9651618..04a46bf929 100644
--- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp
+++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
@@ -312,7 +312,8 @@ QImage QSGWindowsRenderLoop::grab(QQuickWindow *window)
d->syncSceneGraph();
d->renderSceneGraph(window->size());
- QImage image = qt_gl_read_framebuffer(window->size() * window->effectiveDevicePixelRatio(), false, false);
+ bool alpha = window->format().alphaBufferSize() > 0 && window->color().alpha() != 255;
+ QImage image = qt_gl_read_framebuffer(window->size() * window->effectiveDevicePixelRatio(), alpha, alpha);
return image;
}
diff --git a/src/quick/scenegraph/qsgwindowsrenderloop_p.h b/src/quick/scenegraph/qsgwindowsrenderloop_p.h
index fd2dde6f2f..654a0ebbfd 100644
--- a/src/quick/scenegraph/qsgwindowsrenderloop_p.h
+++ b/src/quick/scenegraph/qsgwindowsrenderloop_p.h
@@ -34,6 +34,17 @@
#ifndef QSGWINDOWSRENDERLOOP_P_H
#define QSGWINDOWSRENDERLOOP_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/QObject>
#include <QtCore/QElapsedTimer>
diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri
index 480ac5e569..84cc2ba135 100644
--- a/src/quick/scenegraph/scenegraph.pri
+++ b/src/quick/scenegraph/scenegraph.pri
@@ -79,7 +79,6 @@ HEADERS += \
$$PWD/qsgdefaultglyphnode_p_p.h \
$$PWD/qsgdefaultimagenode_p.h \
$$PWD/qsgdefaultrectanglenode_p.h \
- $$PWD/qsgshareddistancefieldglyphcache_p.h \
$$PWD/qsgrenderloop_p.h \
$$PWD/qsgthreadedrenderloop_p.h \
$$PWD/qsgwindowsrenderloop_p.h \
@@ -96,7 +95,6 @@ SOURCES += \
$$PWD/qsgdistancefieldglyphnode_p.cpp \
$$PWD/qsgdefaultimagenode.cpp \
$$PWD/qsgdefaultrectanglenode.cpp \
- $$PWD/qsgshareddistancefieldglyphcache.cpp \
$$PWD/qsgrenderloop.cpp \
$$PWD/qsgthreadedrenderloop.cpp \
$$PWD/qsgwindowsrenderloop.cpp \
diff --git a/src/quick/scenegraph/shaders/rendernode_core.frag b/src/quick/scenegraph/shaders/rendernode_core.frag
index 7c187265df..b29301b058 100644
--- a/src/quick/scenegraph/shaders/rendernode_core.frag
+++ b/src/quick/scenegraph/shaders/rendernode_core.frag
@@ -4,9 +4,9 @@ uniform sampler2D tex;
in vec2 t;
-out vec4 color;
+out vec4 fragColor;
void main()
{
fragColor = texture(tex, t);
-} \ No newline at end of file
+}
diff --git a/src/quick/scenegraph/shaders/styledtext_core.frag b/src/quick/scenegraph/shaders/styledtext_core.frag
index 50f64c64a2..5480e95a42 100644
--- a/src/quick/scenegraph/shaders/styledtext_core.frag
+++ b/src/quick/scenegraph/shaders/styledtext_core.frag
@@ -3,7 +3,7 @@
in vec2 sampleCoord;
in vec2 shiftedSampleCoord;
-out vec4 color;
+out vec4 fragColor;
uniform sampler2D _qt_texture;
uniform vec4 color;
@@ -11,8 +11,8 @@ uniform vec4 styleColor;
void main()
{
- float glyph = texture(_qt_texture, sampleCoord).a;
+ float glyph = texture(_qt_texture, sampleCoord).r;
float style = clamp(texture(_qt_texture, shiftedSampleCoord).r - glyph,
0.0, 1.0);
fragColor = style * styleColor + glyph * color;
-} \ No newline at end of file
+}
diff --git a/src/quick/scenegraph/util/qsgareaallocator_p.h b/src/quick/scenegraph/util/qsgareaallocator_p.h
index d2823ce3ac..f7f753bb9c 100644
--- a/src/quick/scenegraph/util/qsgareaallocator_p.h
+++ b/src/quick/scenegraph/util/qsgareaallocator_p.h
@@ -34,6 +34,17 @@
#ifndef QSGAREAALLOCATOR_P_H
#define QSGAREAALLOCATOR_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qtquickglobal_p.h>
#include <QtCore/qsize.h>
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index b862fa6a2b..8e8e870505 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -54,21 +54,13 @@ QT_BEGIN_NAMESPACE
#define GL_BGRA 0x80E1
#endif
+int qt_sg_envInt(const char *name, int defaultValue);
static QElapsedTimer qsg_renderer_timer;
namespace QSGAtlasTexture
{
-static int qsg_envInt(const char *name, int defaultValue)
-{
- QByteArray content = qgetenv(name);
-
- bool ok = false;
- int value = content.toInt(&ok);
- return ok ? value : defaultValue;
-}
-
Manager::Manager()
: m_atlas(0)
{
@@ -79,8 +71,8 @@ Manager::Manager()
int max;
gl->functions()->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max);
- int w = qMin(max, qsg_envInt("QSG_ATLAS_WIDTH", qMax(512U, qNextPowerOfTwo(surfaceSize.width() - 1))));
- int h = qMin(max, qsg_envInt("QSG_ATLAS_HEIGHT", qMax(512U, qNextPowerOfTwo(surfaceSize.height() - 1))));
+ int w = qMin(max, qt_sg_envInt("QSG_ATLAS_WIDTH", qMax(512U, qNextPowerOfTwo(surfaceSize.width() - 1))));
+ int h = qMin(max, qt_sg_envInt("QSG_ATLAS_HEIGHT", qMax(512U, qNextPowerOfTwo(surfaceSize.height() - 1))));
if (surface->surfaceClass() == QSurface::Window) {
QWindow *window = static_cast<QWindow *>(surface);
@@ -91,7 +83,7 @@ Manager::Manager()
}
}
- m_atlas_size_limit = qsg_envInt("QSG_ATLAS_SIZE_LIMIT", qMax(w, h) / 2);
+ m_atlas_size_limit = qt_sg_envInt("QSG_ATLAS_SIZE_LIMIT", qMax(w, h) / 2);
m_atlas_size = QSize(w, h);
qCDebug(QSG_LOG_INFO, "texture atlas dimensions: %dx%d", w, h);
@@ -112,13 +104,15 @@ void Manager::invalidate()
}
}
-QSGTexture *Manager::create(const QImage &image)
+QSGTexture *Manager::create(const QImage &image, bool hasAlphaChannel)
{
- QSGTexture *t = 0;
+ Texture *t = 0;
if (image.width() < m_atlas_size_limit && image.height() < m_atlas_size_limit) {
if (!m_atlas)
m_atlas = new Atlas(m_atlas_size);
t = m_atlas->create(image);
+ if (!hasAlphaChannel && t->hasAlphaChannel())
+ t->setHasAlphaChannel(false);
}
return t;
}
diff --git a/src/quick/scenegraph/util/qsgatlastexture_p.h b/src/quick/scenegraph/util/qsgatlastexture_p.h
index 399d5fd669..e77e0fa104 100644
--- a/src/quick/scenegraph/util/qsgatlastexture_p.h
+++ b/src/quick/scenegraph/util/qsgatlastexture_p.h
@@ -34,6 +34,17 @@
#ifndef QSGATLASTEXTURE_P_H
#define QSGATLASTEXTURE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/QSize>
#include <QtGui/qopengl.h>
@@ -58,7 +69,7 @@ public:
Manager();
~Manager();
- QSGTexture *create(const QImage &image);
+ QSGTexture *create(const QImage &image, bool hasAlphaChannel);
void invalidate();
private:
@@ -114,6 +125,7 @@ public:
int textureId() const { return m_atlas->textureId(); }
QSize textureSize() const { return atlasSubRectWithoutPadding().size(); }
+ void setHasAlphaChannel(bool alpha) { m_has_alpha = alpha; }
bool hasAlphaChannel() const { return m_has_alpha; }
bool hasMipmaps() const { return false; }
bool isAtlasTexture() const { return true; }
diff --git a/src/quick/scenegraph/util/qsgdefaultpainternode.cpp b/src/quick/scenegraph/util/qsgdefaultpainternode.cpp
index be8deb2aa3..38bcc7a3f3 100644
--- a/src/quick/scenegraph/util/qsgdefaultpainternode.cpp
+++ b/src/quick/scenegraph/util/qsgdefaultpainternode.cpp
@@ -76,6 +76,8 @@ QSGDefaultPainterNode::QSGDefaultPainterNode(QQuickPaintedItem *item)
, m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
, m_texture(0)
, m_gl_device(0)
+ , m_fillColor(Qt::transparent)
+ , m_contentsScale(1.0)
, m_dirtyContents(false)
, m_opaquePainting(false)
, m_linear_filtering(false)
@@ -84,8 +86,6 @@ QSGDefaultPainterNode::QSGDefaultPainterNode(QQuickPaintedItem *item)
, m_extensionsChecked(false)
, m_multisamplingSupported(false)
, m_fastFBOResizing(false)
- , m_fillColor(Qt::transparent)
- , m_contentsScale(1.0)
, m_dirtyGeometry(false)
, m_dirtyRenderTarget(false)
, m_dirtyTexture(false)
@@ -136,18 +136,35 @@ void QSGDefaultPainterNode::paint()
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
}
- painter.scale(m_contentsScale, m_contentsScale);
-
- QRect sclip(qFloor(dirtyRect.x()/m_contentsScale),
- qFloor(dirtyRect.y()/m_contentsScale),
- qCeil(dirtyRect.width()/m_contentsScale+dirtyRect.x()/m_contentsScale-qFloor(dirtyRect.x()/m_contentsScale)),
- qCeil(dirtyRect.height()/m_contentsScale+dirtyRect.y()/m_contentsScale-qFloor(dirtyRect.y()/m_contentsScale)));
+ QRect clipRect;
+ QRect dirtyTextureRect;
+
+ if (m_contentsScale == 1) {
+ qreal scaleX = m_textureSize.width() / (qreal) m_size.width();
+ qreal scaleY = m_textureSize.height() / (qreal) m_size.height();
+ painter.scale(scaleX, scaleY);
+ clipRect = dirtyRect;
+ dirtyTextureRect = QRectF(dirtyRect.x() * scaleX,
+ dirtyRect.y() * scaleY,
+ dirtyRect.width() * scaleX,
+ dirtyRect.height() * scaleY).toAlignedRect();
+ } else {
+ painter.scale(m_contentsScale, m_contentsScale);
+ QRect sclip(qFloor(dirtyRect.x()/m_contentsScale),
+ qFloor(dirtyRect.y()/m_contentsScale),
+ qCeil(dirtyRect.width()/m_contentsScale+dirtyRect.x()/m_contentsScale-qFloor(dirtyRect.x()/m_contentsScale)),
+ qCeil(dirtyRect.height()/m_contentsScale+dirtyRect.y()/m_contentsScale-qFloor(dirtyRect.y()/m_contentsScale)));
+ clipRect = sclip;
+ dirtyTextureRect = dirtyRect;
+ }
- if (!m_dirtyRect.isNull())
- painter.setClipRect(sclip);
+ // only clip if we were originally updating only a subrect
+ if (!m_dirtyRect.isNull()) {
+ painter.setClipRect(clipRect);
+ }
painter.setCompositionMode(QPainter::CompositionMode_Source);
- painter.fillRect(sclip, m_fillColor);
+ painter.fillRect(clipRect, m_fillColor);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
m_item->paint(&painter);
@@ -155,9 +172,9 @@ void QSGDefaultPainterNode::paint()
if (m_actualRenderTarget == QQuickPaintedItem::Image) {
m_texture->setImage(m_image);
- m_texture->setDirtyRect(dirtyRect);
+ m_texture->setDirtyRect(dirtyTextureRect);
} else if (m_multisampledFbo) {
- QOpenGLFramebufferObject::blitFramebuffer(m_fbo, dirtyRect, m_multisampledFbo, dirtyRect);
+ QOpenGLFramebufferObject::blitFramebuffer(m_fbo, dirtyTextureRect, m_multisampledFbo, dirtyTextureRect);
}
if (m_multisampledFbo)
@@ -276,7 +293,7 @@ void QSGDefaultPainterNode::updateRenderTarget()
if (!m_image.isNull() && !m_dirtyGeometry)
return;
- m_image = QImage(m_size, QImage::Format_ARGB32_Premultiplied);
+ m_image = QImage(m_textureSize, QImage::Format_ARGB32_Premultiplied);
m_image.fill(Qt::transparent);
}
@@ -302,12 +319,12 @@ void QSGDefaultPainterNode::updateFBOSize()
int fboWidth;
int fboHeight;
if (m_fastFBOResizing) {
- fboWidth = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qNextPowerOfTwo(m_size.width() - 1));
- fboHeight = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qNextPowerOfTwo(m_size.height() - 1));
+ fboWidth = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qNextPowerOfTwo(m_textureSize.width() - 1));
+ fboHeight = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qNextPowerOfTwo(m_textureSize.height() - 1));
} else {
QSize minimumFBOSize = m_context->sceneGraphContext()->minimumFBOSize();
- fboWidth = qMax(minimumFBOSize.width(), m_size.width());
- fboHeight = qMax(minimumFBOSize.height(), m_size.height());
+ fboWidth = qMax(minimumFBOSize.width(), m_textureSize.width());
+ fboHeight = qMax(minimumFBOSize.height(), m_textureSize.height());
}
m_fboSize = QSize(fboWidth, fboHeight);
@@ -331,6 +348,15 @@ void QSGDefaultPainterNode::setSize(const QSize &size)
return;
m_size = size;
+ m_dirtyGeometry = true;
+}
+
+void QSGDefaultPainterNode::setTextureSize(const QSize &size)
+{
+ if (size == m_textureSize)
+ return;
+
+ m_textureSize = size;
updateFBOSize();
if (m_fbo)
diff --git a/src/quick/scenegraph/util/qsgdefaultpainternode_p.h b/src/quick/scenegraph/util/qsgdefaultpainternode_p.h
index 62daa54432..6b6f485915 100644
--- a/src/quick/scenegraph/util/qsgdefaultpainternode_p.h
+++ b/src/quick/scenegraph/util/qsgdefaultpainternode_p.h
@@ -34,6 +34,17 @@
#ifndef QSGDEFAULTPAINTERNODE_P_H
#define QSGDEFAULTPAINTERNODE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qsgadaptationlayer_p.h>
#include "qsgtexturematerial.h"
#include "qsgtexture_p.h"
@@ -94,6 +105,9 @@ public:
void setFastFBOResizing(bool dynamic);
bool fastFBOResizing() const { return m_fastFBOResizing; }
+ void setTextureSize(const QSize &textureSize);
+ QSize textureSize() const { return m_textureSize; }
+
QImage toImage() const;
void update();
@@ -126,21 +140,25 @@ private:
QSize m_size;
QSize m_fboSize;
- bool m_dirtyContents;
+ QSize m_textureSize;
QRect m_dirtyRect;
- bool m_opaquePainting;
- bool m_linear_filtering;
- bool m_mipmapping;
- bool m_smoothPainting;
- bool m_extensionsChecked;
- bool m_multisamplingSupported;
- bool m_fastFBOResizing;
QColor m_fillColor;
+#if QT_VERSION >= 0x060000
+#warning "Remove m_contentsScale and assume 1 everywhere"
+#endif
qreal m_contentsScale;
- bool m_dirtyGeometry;
- bool m_dirtyRenderTarget;
- bool m_dirtyTexture;
+ bool m_dirtyContents : 1;
+ bool m_opaquePainting : 1;
+ bool m_linear_filtering : 1;
+ bool m_mipmapping : 1;
+ bool m_smoothPainting : 1;
+ bool m_extensionsChecked : 1;
+ bool m_multisamplingSupported : 1;
+ bool m_fastFBOResizing : 1;
+ bool m_dirtyGeometry : 1;
+ bool m_dirtyRenderTarget : 1;
+ bool m_dirtyTexture : 1;
};
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgdepthstencilbuffer_p.h b/src/quick/scenegraph/util/qsgdepthstencilbuffer_p.h
index e9d07ae605..c6d0de4435 100644
--- a/src/quick/scenegraph/util/qsgdepthstencilbuffer_p.h
+++ b/src/quick/scenegraph/util/qsgdepthstencilbuffer_p.h
@@ -34,6 +34,17 @@
#ifndef QSGDEPTHSTENCILBUFFER_P_H
#define QSGDEPTHSTENCILBUFFER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qsize.h>
#include <QtGui/private/qopenglcontext_p.h>
#include <QtGui/private/qopenglextensions_p.h>
diff --git a/src/quick/scenegraph/util/qsgdistancefieldutil.cpp b/src/quick/scenegraph/util/qsgdistancefieldutil.cpp
index 8e02681703..883657da24 100644
--- a/src/quick/scenegraph/util/qsgdistancefieldutil.cpp
+++ b/src/quick/scenegraph/util/qsgdistancefieldutil.cpp
@@ -39,18 +39,27 @@
QT_BEGIN_NAMESPACE
+static float qt_sg_envFloat(const char *name, float defaultValue)
+{
+ if (Q_LIKELY(!qEnvironmentVariableIsSet(name)))
+ return defaultValue;
+ bool ok = false;
+ const float value = qgetenv(name).toFloat(&ok);
+ return ok ? value : defaultValue;
+}
+
static float defaultThresholdFunc(float glyphScale)
{
- static float base = qgetenv("QT_DF_BASE").isEmpty() ? 0.5f : qgetenv("QT_DF_BASE").toFloat();
- static float baseDev = qgetenv("QT_DF_BASEDEVIATION").isEmpty() ? 0.065f : qgetenv("QT_DF_BASEDEVIATION").toFloat();
- static float devScaleMin = qgetenv("QT_DF_SCALEFORMAXDEV").isEmpty() ? 0.15f : qgetenv("QT_DF_SCALEFORMAXDEV").toFloat();
- static float devScaleMax = qgetenv("QT_DF_SCALEFORNODEV").isEmpty() ? 0.3f : qgetenv("QT_DF_SCALEFORNODEV").toFloat();
+ static const float base = qt_sg_envFloat("QT_DF_BASE", 0.5f);
+ static const float baseDev = qt_sg_envFloat("QT_DF_BASEDEVIATION", 0.065f);
+ static const float devScaleMin = qt_sg_envFloat("QT_DF_SCALEFORMAXDEV", 0.15f);
+ static const float devScaleMax = qt_sg_envFloat("QT_DF_SCALEFORNODEV", 0.3f);
return base - ((qBound(devScaleMin, glyphScale, devScaleMax) - devScaleMin) / (devScaleMax - devScaleMin) * -baseDev + baseDev);
}
static float defaultAntialiasingSpreadFunc(float glyphScale)
{
- static float range = qgetenv("QT_DF_RANGE").isEmpty() ? 0.06f : qgetenv("QT_DF_RANGE").toFloat();
+ static const float range = qt_sg_envFloat("QT_DF_RANGE", 0.06f);
return range / glyphScale;
}
@@ -62,7 +71,7 @@ QSGDistanceFieldGlyphCacheManager::QSGDistanceFieldGlyphCacheManager()
QSGDistanceFieldGlyphCacheManager::~QSGDistanceFieldGlyphCacheManager()
{
- qDeleteAll(m_caches.values());
+ qDeleteAll(m_caches);
}
QSGDistanceFieldGlyphCache *QSGDistanceFieldGlyphCacheManager::cache(const QRawFont &font)
diff --git a/src/quick/scenegraph/util/qsgdistancefieldutil_p.h b/src/quick/scenegraph/util/qsgdistancefieldutil_p.h
index 7ed4b44a6d..3ee29230d5 100644
--- a/src/quick/scenegraph/util/qsgdistancefieldutil_p.h
+++ b/src/quick/scenegraph/util/qsgdistancefieldutil_p.h
@@ -34,6 +34,17 @@
#ifndef QSGDISTANCEFIELDUTIL_H
#define QSGDISTANCEFIELDUTIL_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qrawfont.h>
#include <private/qfontengine_p.h>
#include <private/qsgadaptationlayer_p.h>
diff --git a/src/quick/scenegraph/util/qsgengine.cpp b/src/quick/scenegraph/util/qsgengine.cpp
index c0ddf25765..8622f8edc1 100644
--- a/src/quick/scenegraph/util/qsgengine.cpp
+++ b/src/quick/scenegraph/util/qsgengine.cpp
@@ -150,7 +150,7 @@ QSGAbstractRenderer *QSGEngine::createRenderer() const
/*!
Creates a texture using the data of \a image
- Valid \a options are TextureCanUseAtlas
+ Valid \a options are TextureCanUseAtlas and TextureIsOpaque.
The caller takes ownership of the texture and the
texture should only be used with this engine.
@@ -160,13 +160,12 @@ QSGAbstractRenderer *QSGEngine::createRenderer() const
QSGTexture *QSGEngine::createTextureFromImage(const QImage &image, CreateTextureOptions options) const
{
Q_D(const QSGEngine);
- if (!d->sgRenderContext->isValid())
- return 0;
-
- if (options & TextureCanUseAtlas)
- return d->sgRenderContext->createTexture(image);
- else
- return d->sgRenderContext->createTextureNoAtlas(image);
+ if (!d->sgRenderContext->isValid())
+ return 0;
+ uint flags = 0;
+ if (options & TextureCanUseAtlas) flags |= QSGRenderContext::CreateTexture_Atlas;
+ if (!(options & TextureIsOpaque)) flags |= QSGRenderContext::CreateTexture_Alpha;
+ return d->sgRenderContext->createTexture(image, flags);
}
/*!
diff --git a/src/quick/scenegraph/util/qsgengine.h b/src/quick/scenegraph/util/qsgengine.h
index 9a74a02aa1..325d3a9ca2 100644
--- a/src/quick/scenegraph/util/qsgengine.h
+++ b/src/quick/scenegraph/util/qsgengine.h
@@ -52,7 +52,8 @@ public:
enum CreateTextureOption {
TextureHasAlphaChannel = 0x0001,
TextureOwnsGLTexture = 0x0004,
- TextureCanUseAtlas = 0x0008
+ TextureCanUseAtlas = 0x0008,
+ TextureIsOpaque = 0x0010
};
Q_DECLARE_FLAGS(CreateTextureOptions, CreateTextureOption)
diff --git a/src/quick/scenegraph/util/qsgengine_p.h b/src/quick/scenegraph/util/qsgengine_p.h
index 770c4a536c..9bae09ea71 100644
--- a/src/quick/scenegraph/util/qsgengine_p.h
+++ b/src/quick/scenegraph/util/qsgengine_p.h
@@ -34,6 +34,17 @@
#ifndef QSGENGINE_P_H
#define QSGENGINE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qsgengine.h"
#include <private/qobject_p.h>
diff --git a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp
index 93a9c98ffb..0d6375de1e 100644
--- a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp
+++ b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp
@@ -373,7 +373,7 @@ QString QSGShaderSourceBuilder::resolveShaderPath(const QString &path) const
if (contextProfile() != QSurfaceFormat::CoreProfile) {
return path;
} else {
- int idx = path.lastIndexOf(QStringLiteral("."));
+ int idx = path.lastIndexOf(QLatin1Char('.'));
QString resolvedPath;
if (idx != -1)
resolvedPath = path.left(idx)
diff --git a/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h b/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h
index a270acb6ab..180ced7990 100644
--- a/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h
+++ b/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h
@@ -34,6 +34,17 @@
#ifndef QSGSHADERSOURCEBUILDER_P_H
#define QSGSHADERSOURCEBUILDER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qtquickglobal_p.h>
#include <QtGui/qsurfaceformat.h>
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index c89ad7a608..df9e569ca3 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -65,7 +65,7 @@
static QElapsedTimer qsg_renderer_timer;
#ifndef QT_NO_DEBUG
-static bool qsg_leak_check = !qgetenv("QML_LEAK_CHECK").isEmpty();
+static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK");
#endif
diff --git a/src/quick/scenegraph/util/qsgtexture_p.h b/src/quick/scenegraph/util/qsgtexture_p.h
index c4edee6d29..221b85c2f7 100644
--- a/src/quick/scenegraph/util/qsgtexture_p.h
+++ b/src/quick/scenegraph/util/qsgtexture_p.h
@@ -34,6 +34,17 @@
#ifndef QSGTEXTURE_P_H
#define QSGTEXTURE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtQuick/qtquickglobal.h>
#include <private/qobject_p.h>
diff --git a/src/quick/scenegraph/util/qsgtexturematerial_p.h b/src/quick/scenegraph/util/qsgtexturematerial_p.h
index 7146ea95ec..5abd25977c 100644
--- a/src/quick/scenegraph/util/qsgtexturematerial_p.h
+++ b/src/quick/scenegraph/util/qsgtexturematerial_p.h
@@ -34,6 +34,17 @@
#ifndef TEXTUREMATERIAL_P_H
#define TEXTUREMATERIAL_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qsgtexturematerial.h"
#include <private/qtquickglobal_p.h>
diff --git a/src/quick/scenegraph/util/qsgtextureprovider.cpp b/src/quick/scenegraph/util/qsgtextureprovider.cpp
index 2d05e736fe..f2c8eaa54e 100644
--- a/src/quick/scenegraph/util/qsgtextureprovider.cpp
+++ b/src/quick/scenegraph/util/qsgtextureprovider.cpp
@@ -45,12 +45,12 @@ QT_BEGIN_NAMESPACE
\sa {Scene Graph - Two Texture Providers}
*/
/*!
- \fn QSGTexture *QSGTextureProvider::texture();
+ \fn QSGTexture *QSGTextureProvider::texture() const
Returns a pointer to the texture object.
*/
/*!
- \fn void QSGTextureProvider::textureChanged();
+ \fn void QSGTextureProvider::textureChanged()
This signal is emitted when the texture changes.
*/
diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp
index ec3abf7090..22bfd7aef1 100644
--- a/src/quick/util/qquickanimation.cpp
+++ b/src/quick/util/qquickanimation.cpp
@@ -178,14 +178,22 @@ void QQuickAbstractAnimationPrivate::commence()
}
}
-QQmlProperty QQuickAbstractAnimationPrivate::createProperty(QObject *obj, const QString &str, QObject *infoObj)
+QQmlProperty QQuickAbstractAnimationPrivate::createProperty(QObject *obj, const QString &str, QObject *infoObj, QString *errorMessage)
{
QQmlProperty prop(obj, str, qmlContext(infoObj));
if (!prop.isValid()) {
- qmlInfo(infoObj) << QQuickAbstractAnimation::tr("Cannot animate non-existent property \"%1\"").arg(str);
+ const QString message = QQuickAbstractAnimation::tr("Cannot animate non-existent property \"%1\"").arg(str);
+ if (errorMessage)
+ *errorMessage = message;
+ else
+ qmlInfo(infoObj) << message;
return QQmlProperty();
} else if (!prop.isWritable()) {
- qmlInfo(infoObj) << QQuickAbstractAnimation::tr("Cannot animate read-only property \"%1\"").arg(str);
+ const QString message = QQuickAbstractAnimation::tr("Cannot animate read-only property \"%1\"").arg(str);
+ if (errorMessage)
+ *errorMessage = message;
+ else
+ qmlInfo(infoObj) << message;
return QQmlProperty();
}
return prop;
@@ -2179,7 +2187,7 @@ void QQuickPropertyAnimation::setTo(const QVariant &t)
\li \inlineimage qeasingcurve-incubic.png
\row
\li \c Easing.OutCubic
- \li Easing curve for a cubic (t^3) function: decelerating from zero velocity.
+ \li Easing curve for a cubic (t^3) function: decelerating to zero velocity.
\li \inlineimage qeasingcurve-outcubic.png
\row
\li \c Easing.InOutCubic
@@ -2195,7 +2203,7 @@ void QQuickPropertyAnimation::setTo(const QVariant &t)
\li \inlineimage qeasingcurve-inquart.png
\row
\li \c Easing.OutQuart
- \li Easing curve for a quartic (t^4) function: decelerating from zero velocity.
+ \li Easing curve for a quartic (t^4) function: decelerating to zero velocity.
\li \inlineimage qeasingcurve-outquart.png
\row
\li \c Easing.InOutQuart
@@ -2211,7 +2219,7 @@ void QQuickPropertyAnimation::setTo(const QVariant &t)
\li \inlineimage qeasingcurve-inquint.png
\row
\li \c Easing.OutQuint
- \li Easing curve for a quintic (t^5) function: decelerating from zero velocity.
+ \li Easing curve for a quintic (t^5) function: decelerating to zero velocity.
\li \inlineimage qeasingcurve-outquint.png
\row
\li \c Easing.InOutQuint
@@ -2227,7 +2235,7 @@ void QQuickPropertyAnimation::setTo(const QVariant &t)
\li \inlineimage qeasingcurve-insine.png
\row
\li \c Easing.OutSine
- \li Easing curve for a sinusoidal (sin(t)) function: decelerating from zero velocity.
+ \li Easing curve for a sinusoidal (sin(t)) function: decelerating to zero velocity.
\li \inlineimage qeasingcurve-outsine.png
\row
\li \c Easing.InOutSine
@@ -2243,7 +2251,7 @@ void QQuickPropertyAnimation::setTo(const QVariant &t)
\li \inlineimage qeasingcurve-inexpo.png
\row
\li \c Easing.OutExpo
- \li Easing curve for an exponential (2^t) function: decelerating from zero velocity.
+ \li Easing curve for an exponential (2^t) function: decelerating to zero velocity.
\li \inlineimage qeasingcurve-outexpo.png
\row
\li \c Easing.InOutExpo
@@ -2259,7 +2267,7 @@ void QQuickPropertyAnimation::setTo(const QVariant &t)
\li \inlineimage qeasingcurve-incirc.png
\row
\li \c Easing.OutCirc
- \li Easing curve for a circular (sqrt(1-t^2)) function: decelerating from zero velocity.
+ \li Easing curve for a circular (sqrt(1-t^2)) function: decelerating to zero velocity.
\li \inlineimage qeasingcurve-outcirc.png
\row
\li \c Easing.InOutCirc
@@ -2276,7 +2284,7 @@ void QQuickPropertyAnimation::setTo(const QVariant &t)
\li \inlineimage qeasingcurve-inelastic.png
\row
\li \c Easing.OutElastic
- \li Easing curve for an elastic (exponentially decaying sine wave) function: decelerating from zero velocity.
+ \li Easing curve for an elastic (exponentially decaying sine wave) function: decelerating to zero velocity.
\br The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter.
\li \inlineimage qeasingcurve-outelastic.png
\row
@@ -2309,7 +2317,7 @@ void QQuickPropertyAnimation::setTo(const QVariant &t)
\li \inlineimage qeasingcurve-inbounce.png
\row
\li \c Easing.OutBounce
- \li Easing curve for a bounce (exponentially decaying parabolic bounce) function: decelerating from zero velocity.
+ \li Easing curve for a bounce (exponentially decaying parabolic bounce) function: decelerating to zero velocity.
\li \inlineimage qeasingcurve-outbounce.png
\row
\li \c Easing.InOutBounce
@@ -2584,18 +2592,28 @@ QQuickStateActions QQuickPropertyAnimation::createTransitionActions(QQuickStateA
if (defaultTarget && targets.isEmpty())
targets << defaultTarget;
+ bool usingDefaultProperties = false;
if (props.isEmpty() && !d->defaultProperties.isEmpty()) {
props << d->defaultProperties.split(QLatin1Char(','));
+ usingDefaultProperties = true;
}
bool hasExplicit = false;
//an explicit animation has been specified
if (d->toIsDefined) {
+ QVector<QString> errorMessages;
+ bool successfullyCreatedDefaultProperty = false;
+
for (int i = 0; i < props.count(); ++i) {
for (int j = 0; j < targets.count(); ++j) {
QQuickStateAction myAction;
- myAction.property = d->createProperty(targets.at(j), props.at(i), this);
+ QString errorMessage;
+ const QString propertyName = props.at(i);
+ myAction.property = d->createProperty(targets.at(j), propertyName, this, &errorMessage);
if (myAction.property.isValid()) {
+ if (usingDefaultProperties)
+ successfullyCreatedDefaultProperty = true;
+
if (d->fromIsDefined) {
myAction.fromValue = d->from;
d->convertVariant(myAction.fromValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
@@ -2612,9 +2630,16 @@ QQuickStateActions QQuickPropertyAnimation::createTransitionActions(QQuickStateA
break; //### any chance there could be multiples?
}
}
+ } else {
+ errorMessages.append(errorMessage);
}
}
}
+
+ if (!successfullyCreatedDefaultProperty) {
+ foreach (const QString &errorMessage, errorMessages)
+ qmlInfo(this) << errorMessage;
+ }
}
if (!hasExplicit)
diff --git a/src/quick/util/qquickanimation_p.h b/src/quick/util/qquickanimation_p.h
index 0f6224a831..4d3532ce84 100644
--- a/src/quick/util/qquickanimation_p.h
+++ b/src/quick/util/qquickanimation_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKANIMATION_H
#define QQUICKANIMATION_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickstate_p.h"
#include <QtGui/qvector3d.h>
@@ -57,7 +68,6 @@ class Q_QUICK_PRIVATE_EXPORT QQuickAbstractAnimation : public QObject, public QQ
Q_INTERFACES(QQmlParserStatus)
Q_INTERFACES(QQmlPropertyValueSource)
- Q_ENUMS(Loops)
Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
Q_PROPERTY(bool alwaysRunToEnd READ alwaysRunToEnd WRITE setAlwaysRunToEnd NOTIFY alwaysRunToEndChanged)
@@ -75,6 +85,7 @@ public:
virtual ~QQuickAbstractAnimation();
enum Loops { Infinite = -2 };
+ Q_ENUM(Loops)
bool isRunning() const;
void setRunning(bool);
@@ -367,7 +378,6 @@ class Q_QUICK_PRIVATE_EXPORT QQuickRotationAnimation : public QQuickPropertyAnim
{
Q_OBJECT
Q_DECLARE_PRIVATE(QQuickRotationAnimation)
- Q_ENUMS(RotationDirection)
Q_PROPERTY(qreal from READ from WRITE setFrom)
Q_PROPERTY(qreal to READ to WRITE setTo)
@@ -384,6 +394,7 @@ public:
void setTo(qreal);
enum RotationDirection { Numerical, Shortest, Clockwise, Counterclockwise };
+ Q_ENUM(RotationDirection)
RotationDirection direction() const;
void setDirection(RotationDirection direction);
diff --git a/src/quick/util/qquickanimation_p_p.h b/src/quick/util/qquickanimation_p_p.h
index 4224c6d9ed..a5960f5696 100644
--- a/src/quick/util/qquickanimation_p_p.h
+++ b/src/quick/util/qquickanimation_p_p.h
@@ -164,7 +164,7 @@ private:
T *m_instance;
};
-class QQuickAbstractAnimationPrivate : public QObjectPrivate, public QAnimationJobChangeListener
+class Q_QUICK_PRIVATE_EXPORT QQuickAbstractAnimationPrivate : public QObjectPrivate, public QAnimationJobChangeListener
{
Q_DECLARE_PUBLIC(QQuickAbstractAnimation)
public:
@@ -193,7 +193,7 @@ public:
QQuickAnimationGroup *group;
QAbstractAnimationJob* animationInstance;
- static QQmlProperty createProperty(QObject *obj, const QString &str, QObject *infoObj);
+ static QQmlProperty createProperty(QObject *obj, const QString &str, QObject *infoObj, QString *errorMessage = Q_NULLPTR);
};
class QQuickPauseAnimationPrivate : public QQuickAbstractAnimationPrivate
diff --git a/src/quick/util/qquickanimationcontroller_p.h b/src/quick/util/qquickanimationcontroller_p.h
index 171090b6a7..efd1dbafc4 100644
--- a/src/quick/util/qquickanimationcontroller_p.h
+++ b/src/quick/util/qquickanimationcontroller_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKANIMATIONCONTROLLER_H
#define QQUICKANIMATIONCONTROLLER_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include "qquickanimation_p.h"
diff --git a/src/quick/util/qquickanimator.cpp b/src/quick/util/qquickanimator.cpp
index 61fb7481d9..8a5cad4011 100644
--- a/src/quick/util/qquickanimator.cpp
+++ b/src/quick/util/qquickanimator.cpp
@@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
directly on Qt Quick's scene graph, rather than the QML objects and their
properties like regular Animation types do. This has the benefit that
Animator based animations can animate on the \l
- {Threaded Render Loop}{scene graph's rendering thread} even when the
+ {Threaded Render Loop ("threaded")}{scene graph's rendering thread} even when the
UI thread is blocked.
The value of the QML property will be updated after the animation has
diff --git a/src/quick/util/qquickanimator_p.h b/src/quick/util/qquickanimator_p.h
index 4d3a8e9e4f..1ba0367839 100644
--- a/src/quick/util/qquickanimator_p.h
+++ b/src/quick/util/qquickanimator_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKANIMATOR_P_H
#define QQUICKANIMATOR_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickanimation_p.h"
QT_BEGIN_NAMESPACE
@@ -136,10 +147,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickRotationAnimator : public QQuickAnimator
Q_DECLARE_PRIVATE(QQuickRotationAnimator)
Q_PROPERTY(RotationDirection direction READ direction WRITE setDirection NOTIFY directionChanged)
- Q_ENUMS(RotationDirection)
-
public:
enum RotationDirection { Numerical, Shortest, Clockwise, Counterclockwise };
+ Q_ENUM(RotationDirection)
QQuickRotationAnimator(QObject *parent = 0);
diff --git a/src/quick/util/qquickanimator_p_p.h b/src/quick/util/qquickanimator_p_p.h
index ad16b1c361..f5f0295f74 100644
--- a/src/quick/util/qquickanimator_p_p.h
+++ b/src/quick/util/qquickanimator_p_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKANIMATOR_P_P_H
#define QQUICKANIMATOR_P_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickanimator_p.h"
#include "qquickanimation_p_p.h"
#include <QtQuick/qquickitem.h>
diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp
index c875e18978..74930fb373 100644
--- a/src/quick/util/qquickanimatorcontroller.cpp
+++ b/src/quick/util/qquickanimatorcontroller.cpp
@@ -140,6 +140,11 @@ static void qquick_initialize_helper(QAbstractAnimationJob *job, QQuickAnimatorC
{
if (job->isRenderThreadJob()) {
QQuickAnimatorJob *j = static_cast<QQuickAnimatorJob *>(job);
+ // Note: since a QQuickAnimatorJob::m_target is a QPointer,
+ // if m_target is destroyed between the time it was set
+ // as the target of the animator job and before this step,
+ // (e.g a Loader being set inactive just after starting the animator)
+ // we are sure it will be NULL and won't be dangling around
if (!j->target()) {
return;
} else if (c->m_deletedSinceLastFrame.contains(j->target())) {
@@ -217,8 +222,8 @@ void QQuickAnimatorController::beforeNodeSync()
void QQuickAnimatorController::afterNodeSync()
{
foreach (QQuickAnimatorJob *job, m_activeLeafAnimations) {
- if (job->isUniform() && job->target())
- static_cast<QQuickUniformAnimatorJob *>(job)->afterNodeSync();
+ if (job->target())
+ job->afterNodeSync();
}
}
diff --git a/src/quick/util/qquickanimatorcontroller_p.h b/src/quick/util/qquickanimatorcontroller_p.h
index 4de485c37c..5dd9b09e0b 100644
--- a/src/quick/util/qquickanimatorcontroller_p.h
+++ b/src/quick/util/qquickanimatorcontroller_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKANIMATORCONTROLLER_P_H
#define QQUICKANIMATORCONTROLLER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickanimatorjob_p.h"
#include <QtQuick/qsgnode.h>
#include <QtQuick/qquickitem.h>
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
index 2a8e3c281c..eb627609bf 100644
--- a/src/quick/util/qquickanimatorjob.cpp
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -126,9 +126,8 @@ void QQuickAnimatorProxyJob::updateState(QAbstractAnimationJob::State newState,
m_controller->startJob(this, m_job);
} else if (newState == Stopped) {
syncBackCurrentValues();
- if (m_internalState == State_Starting)
- m_internalState = State_Stopped;
- else if (m_controller) {
+ m_internalState = State_Stopped;
+ if (m_controller) {
m_controller->stopJob(this, m_job);
}
}
@@ -161,6 +160,8 @@ void QQuickAnimatorProxyJob::setWindow(QQuickWindow *window)
// Upon leaving a window, we reset the controller. This means that
// animators will only enter the Starting phase and won't be making
// calls to QQuickAnimatorController::startjob().
+ if (m_controller)
+ m_controller->proxyWasDestroyed(this);
m_controller = 0;
} else if (!m_controller && m_job) {
diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h
index f8f40b4705..35057d6278 100644
--- a/src/quick/util/qquickanimatorjob_p.h
+++ b/src/quick/util/qquickanimatorjob_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKANIMATORJOB_P_H
#define QQUICKANIMATORJOB_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qabstractanimationjob_p.h>
#include <private/qquickanimator_p.h>
#include <private/qtquickglobal_p.h>
@@ -125,6 +136,7 @@ public:
virtual void initialize(QQuickAnimatorController *controller);
virtual void writeBack() = 0;
virtual void nodeWasDestroyed() = 0;
+ virtual void afterNodeSync() { }
bool isTransform() const { return m_isTransform; }
bool isUniform() const { return m_isUniform; }
@@ -140,7 +152,7 @@ protected:
QQuickAnimatorJob();
void debugAnimation(QDebug d) const Q_DECL_OVERRIDE;
- QQuickItem *m_target;
+ QPointer<QQuickItem> m_target;
QQuickAnimatorController *m_controller;
qreal m_from;
@@ -151,7 +163,6 @@ protected:
int m_duration;
- uint m_feedback : 1;
uint m_isTransform : 1;
uint m_isUniform : 1;
uint m_hasBeenRunning : 1;
@@ -212,22 +223,22 @@ protected:
class Q_QUICK_PRIVATE_EXPORT QQuickScaleAnimatorJob : public QQuickTransformAnimatorJob
{
public:
- void updateCurrentTime(int time);
- void writeBack();
+ void updateCurrentTime(int time) Q_DECL_OVERRIDE;
+ void writeBack() Q_DECL_OVERRIDE;
};
class Q_QUICK_PRIVATE_EXPORT QQuickXAnimatorJob : public QQuickTransformAnimatorJob
{
public:
- void updateCurrentTime(int time);
- void writeBack();
+ void updateCurrentTime(int time) Q_DECL_OVERRIDE;
+ void writeBack() Q_DECL_OVERRIDE;
};
class Q_QUICK_PRIVATE_EXPORT QQuickYAnimatorJob : public QQuickTransformAnimatorJob
{
public:
- void updateCurrentTime(int time);
- void writeBack();
+ void updateCurrentTime(int time) Q_DECL_OVERRIDE;
+ void writeBack() Q_DECL_OVERRIDE;
};
class Q_QUICK_PRIVATE_EXPORT QQuickRotationAnimatorJob : public QQuickTransformAnimatorJob
@@ -235,8 +246,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickRotationAnimatorJob : public QQuickTransformA
public:
QQuickRotationAnimatorJob();
- void updateCurrentTime(int time);
- void writeBack();
+ void updateCurrentTime(int time) Q_DECL_OVERRIDE;
+ void writeBack() Q_DECL_OVERRIDE;
void setDirection(QQuickRotationAnimator::RotationDirection direction) { m_direction = direction; }
QQuickRotationAnimator::RotationDirection direction() const { return m_direction; }
@@ -250,10 +261,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickOpacityAnimatorJob : public QQuickAnimatorJob
public:
QQuickOpacityAnimatorJob();
- void initialize(QQuickAnimatorController *controller);
- void updateCurrentTime(int time);
- void writeBack();
- void nodeWasDestroyed();
+ void initialize(QQuickAnimatorController *controller) Q_DECL_OVERRIDE;
+ void updateCurrentTime(int time) Q_DECL_OVERRIDE;
+ void writeBack() Q_DECL_OVERRIDE;
+ void nodeWasDestroyed() Q_DECL_OVERRIDE;
private:
QSGOpacityNode *m_opacityNode;
@@ -264,16 +275,16 @@ class Q_QUICK_PRIVATE_EXPORT QQuickUniformAnimatorJob : public QQuickAnimatorJob
public:
QQuickUniformAnimatorJob();
- void setTarget(QQuickItem *target);
+ void setTarget(QQuickItem *target) Q_DECL_OVERRIDE;
void setUniform(const QByteArray &uniform) { m_uniform = uniform; }
QByteArray uniform() const { return m_uniform; }
- void afterNodeSync();
+ void afterNodeSync() Q_DECL_OVERRIDE;
- void updateCurrentTime(int time);
- void writeBack();
- void nodeWasDestroyed();
+ void updateCurrentTime(int time) Q_DECL_OVERRIDE;
+ void writeBack() Q_DECL_OVERRIDE;
+ void nodeWasDestroyed() Q_DECL_OVERRIDE;
private:
QByteArray m_uniform;
diff --git a/src/quick/util/qquickapplication_p.h b/src/quick/util/qquickapplication_p.h
index c22d8cfe6b..082f68101a 100644
--- a/src/quick/util/qquickapplication_p.h
+++ b/src/quick/util/qquickapplication_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKAPPLICATION_P_H
#define QQUICKAPPLICATION_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/QObject>
#include <qqml.h>
#include <QtQml/private/qqmlglobal_p.h>
diff --git a/src/quick/util/qquickbehavior_p.h b/src/quick/util/qquickbehavior_p.h
index d566ca8ba1..a8bff1511b 100644
--- a/src/quick/util/qquickbehavior_p.h
+++ b/src/quick/util/qquickbehavior_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKBEHAVIOR_H
#define QQUICKBEHAVIOR_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qtquickglobal_p.h>
#include <private/qqmlpropertyvalueinterceptor_p.h>
diff --git a/src/quick/util/qquickfontloader.cpp b/src/quick/util/qquickfontloader.cpp
index 67df47fb37..496acaa8e3 100644
--- a/src/quick/util/qquickfontloader.cpp
+++ b/src/quick/util/qquickfontloader.cpp
@@ -47,6 +47,8 @@
#include <qqmlinfo.h>
#include <qqmlfile.h>
+#include <QtCore/QCoreApplication>
+
QT_BEGIN_NAMESPACE
#define FONTLOADER_MAXIMUM_REDIRECT_RECURSION 16
@@ -132,10 +134,50 @@ public:
QUrl url;
QString name;
QQuickFontLoader::Status status;
- static QHash<QUrl, QQuickFontObject*> fonts;
};
-QHash<QUrl, QQuickFontObject*> QQuickFontLoaderPrivate::fonts;
+static void q_QFontLoaderFontsStaticReset();
+static void q_QFontLoaderFontsAddReset()
+{
+ qAddPostRoutine(q_QFontLoaderFontsStaticReset);
+}
+class QFontLoaderFonts
+{
+public:
+ QFontLoaderFonts()
+ {
+ qAddPostRoutine(q_QFontLoaderFontsStaticReset);
+ qAddPreRoutine(q_QFontLoaderFontsAddReset);
+ }
+
+ ~QFontLoaderFonts()
+ {
+ qRemovePostRoutine(q_QFontLoaderFontsStaticReset);
+ reset();
+ }
+
+
+ void reset()
+ {
+ QVector<QQuickFontObject *> deleted;
+ QHash<QUrl, QQuickFontObject*>::iterator it;
+ for (it = map.begin(); it != map.end(); ++it) {
+ if (!deleted.contains(it.value())) {
+ deleted.append(it.value());
+ delete it.value();
+ }
+ }
+ map.clear();
+ }
+
+ QHash<QUrl, QQuickFontObject *> map;
+};
+Q_GLOBAL_STATIC(QFontLoaderFonts, fontLoaderFonts);
+
+static void q_QFontLoaderFontsStaticReset()
+{
+ fontLoaderFonts()->reset();
+}
/*!
\qmltype FontLoader
@@ -193,29 +235,29 @@ void QQuickFontLoader::setSource(const QUrl &url)
QString localFile = QQmlFile::urlToLocalFileOrQrc(d->url);
if (!localFile.isEmpty()) {
- if (!d->fonts.contains(d->url)) {
+ if (!fontLoaderFonts()->map.contains(d->url)) {
int id = QFontDatabase::addApplicationFont(localFile);
if (id != -1) {
updateFontInfo(QFontDatabase::applicationFontFamilies(id).at(0), Ready);
QQuickFontObject *fo = new QQuickFontObject(id);
- d->fonts[d->url] = fo;
+ fontLoaderFonts()->map[d->url] = fo;
} else {
updateFontInfo(QString(), Error);
}
} else {
- updateFontInfo(QFontDatabase::applicationFontFamilies(d->fonts[d->url]->id).at(0), Ready);
+ updateFontInfo(QFontDatabase::applicationFontFamilies(fontLoaderFonts()->map[d->url]->id).at(0), Ready);
}
} else {
- if (!d->fonts.contains(d->url)) {
+ if (!fontLoaderFonts()->map.contains(d->url)) {
QQuickFontObject *fo = new QQuickFontObject;
- d->fonts[d->url] = fo;
+ fontLoaderFonts()->map[d->url] = fo;
fo->download(d->url, qmlEngine(this)->networkAccessManager());
d->status = Loading;
emit statusChanged();
QObject::connect(fo, SIGNAL(fontDownloaded(QString,QQuickFontLoader::Status)),
this, SLOT(updateFontInfo(QString,QQuickFontLoader::Status)));
} else {
- QQuickFontObject *fo = d->fonts[d->url];
+ QQuickFontObject *fo = fontLoaderFonts()->map[d->url];
if (fo->id == -1) {
d->status = Loading;
emit statusChanged();
diff --git a/src/quick/util/qquickfontloader_p.h b/src/quick/util/qquickfontloader_p.h
index b6ca0b3c94..1e2a70be7d 100644
--- a/src/quick/util/qquickfontloader_p.h
+++ b/src/quick/util/qquickfontloader_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKFONTLOADER_H
#define QQUICKFONTLOADER_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include <QtCore/qobject.h>
@@ -46,7 +57,6 @@ class Q_AUTOTEST_EXPORT QQuickFontLoader : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QQuickFontLoader)
- Q_ENUMS(Status)
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
@@ -54,6 +64,7 @@ class Q_AUTOTEST_EXPORT QQuickFontLoader : public QObject
public:
enum Status { Null = 0, Ready, Loading, Error };
+ Q_ENUM(Status)
QQuickFontLoader(QObject *parent = 0);
~QQuickFontLoader();
diff --git a/src/quick/util/qquickfontmetrics.cpp b/src/quick/util/qquickfontmetrics.cpp
index a87ec7d60a..0e3556be86 100644
--- a/src/quick/util/qquickfontmetrics.cpp
+++ b/src/quick/util/qquickfontmetrics.cpp
@@ -319,8 +319,7 @@ QRectF QQuickFontMetrics::tightBoundingRect(const QString &text) const
}
/*!
- \qmlmethod string QtQuick::FontMetrics::elidedText(string text, enum mode,
- qreal width, int flags)
+ \qmlmethod string QtQuick::FontMetrics::elidedText(string text, enumeration mode, real width, int flags)
This method returns a returns an elided version of the string (i.e., a
string with "..." in it) if the string \a text is wider than \a width.
diff --git a/src/quick/util/qquickfontmetrics_p.h b/src/quick/util/qquickfontmetrics_p.h
index 88880a2be8..37aaef7345 100644
--- a/src/quick/util/qquickfontmetrics_p.h
+++ b/src/quick/util/qquickfontmetrics_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKFONTMETRICS_H
#define QQUICKFONTMETRICS_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include <QtGui/QFontMetricsF>
diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp
index 6aa7bedc5b..2ea1a062d8 100644
--- a/src/quick/util/qquickglobal.cpp
+++ b/src/quick/util/qquickglobal.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 BasysKom GmbH.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
@@ -285,6 +286,7 @@ public:
QV4::ScopedValue vbold(scope, obj->get((s = v4->newString(QStringLiteral("bold")))));
QV4::ScopedValue vcap(scope, obj->get((s = v4->newString(QStringLiteral("capitalization")))));
QV4::ScopedValue vfam(scope, obj->get((s = v4->newString(QStringLiteral("family")))));
+ QV4::ScopedValue vstyle(scope, obj->get((s = v4->newString(QStringLiteral("styleName")))));
QV4::ScopedValue vital(scope, obj->get((s = v4->newString(QStringLiteral("italic")))));
QV4::ScopedValue vlspac(scope, obj->get((s = v4->newString(QStringLiteral("letterSpacing")))));
QV4::ScopedValue vpixsz(scope, obj->get((s = v4->newString(QStringLiteral("pixelSize")))));
@@ -307,6 +309,10 @@ public:
retn.setFamily(vfam->toQString());
if (ok) *ok = true;
}
+ if (vstyle->isString()) {
+ retn.setStyleName(vstyle->toQString());
+ if (ok) *ok = true;
+ }
if (vital->isBoolean()) {
retn.setItalic(vital->booleanValue());
if (ok) *ok = true;
@@ -368,7 +374,7 @@ public:
return QMatrix4x4(matVals);
}
- const QMetaObject *getMetaObjectForMetaType(int type)
+ const QMetaObject *getMetaObjectForMetaType(int type) Q_DECL_OVERRIDE
{
switch (type) {
case QMetaType::QColor:
@@ -392,132 +398,37 @@ public:
return 0;
}
- template<typename T>
- bool typedInit(void *data, size_t dataSize)
- {
- ASSERT_VALID_SIZE(dataSize, sizeof(T));
- T *t = reinterpret_cast<T *>(data);
- new (t) T();
- return true;
- }
-
- bool init(int type, void *data, size_t dataSize)
+ bool init(int type, QVariant& dst) Q_DECL_OVERRIDE
{
switch (type) {
case QMetaType::QColor:
- return typedInit<QColor>(data, dataSize);
- case QMetaType::QFont:
- return typedInit<QFont>(data, dataSize);
- case QMetaType::QVector2D:
- return typedInit<QVector2D>(data, dataSize);
- case QMetaType::QVector3D:
- return typedInit<QVector3D>(data, dataSize);
- case QMetaType::QVector4D:
- return typedInit<QVector4D>(data, dataSize);
- case QMetaType::QQuaternion:
- return typedInit<QQuaternion>(data, dataSize);
- case QMetaType::QMatrix4x4:
- {
- if (dataSize >= sizeof(QMatrix4x4))
- return typedInit<QMatrix4x4>(data, dataSize);
-
- // special case: init matrix-containing qvariant.
- Q_ASSERT(dataSize >= sizeof(QVariant));
- QVariant *matvar = reinterpret_cast<QVariant *>(data);
- new (matvar) QVariant(QMatrix4x4());
+ dst.setValue<QColor>(QColor());
return true;
- }
- default: break;
- }
-
- return false;
- }
-
- template<typename T>
- bool typedDestroy(void *data, size_t dataSize)
- {
- ASSERT_VALID_SIZE(dataSize, sizeof(T));
- T *t = reinterpret_cast<T *>(data);
- t->~T();
- return true;
- }
-
- bool destroy(int type, void *data, size_t dataSize)
- {
- switch (type) {
- case QMetaType::QColor:
- return typedDestroy<QColor>(data, dataSize);
case QMetaType::QFont:
- return typedDestroy<QFont>(data, dataSize);
- case QMetaType::QVector2D:
- return typedDestroy<QVector2D>(data, dataSize);
- case QMetaType::QVector3D:
- return typedDestroy<QVector3D>(data, dataSize);
- case QMetaType::QVector4D:
- return typedDestroy<QVector4D>(data, dataSize);
- case QMetaType::QQuaternion:
- return typedDestroy<QQuaternion>(data, dataSize);
- case QMetaType::QMatrix4x4:
- {
- if (dataSize >= sizeof(QMatrix4x4))
- return typedDestroy<QMatrix4x4>(data, dataSize);
-
- // special case: destroying matrix-containing qvariant.
- Q_ASSERT(dataSize >= sizeof(QVariant));
- QVariant *matvar = reinterpret_cast<QVariant *>(data);
- matvar->~QVariant();
+ dst.setValue<QFont>(QFont());
return true;
- }
- default: break;
- }
-
- return false;
- }
-
- template<typename T>
- bool typedCopyConstruct(const void *src, void *dst, size_t dstSize)
- {
- ASSERT_VALID_SIZE(dstSize, sizeof(T));
- const T *srcT = reinterpret_cast<const T *>(src);
- T *destT = reinterpret_cast<T *>(dst);
- new (destT) T(*srcT);
- return true;
- }
-
- bool copy(int type, const void *src, void *dst, size_t dstSize)
- {
- switch (type) {
- case QMetaType::QColor:
- return typedCopyConstruct<QColor>(src, dst, dstSize);
- case QMetaType::QFont:
- return typedCopyConstruct<QFont>(src, dst, dstSize);
case QMetaType::QVector2D:
- return typedCopyConstruct<QVector2D>(src, dst, dstSize);
+ dst.setValue<QVector2D>(QVector2D());
+ return true;
case QMetaType::QVector3D:
- return typedCopyConstruct<QVector3D>(src, dst, dstSize);
+ dst.setValue<QVector3D>(QVector3D());
+ return true;
case QMetaType::QVector4D:
- return typedCopyConstruct<QVector4D>(src, dst, dstSize);
+ dst.setValue<QVector4D>(QVector4D());
+ return true;
case QMetaType::QQuaternion:
- return typedCopyConstruct<QQuaternion>(src, dst, dstSize);
+ dst.setValue<QQuaternion>(QQuaternion());
+ return true;
case QMetaType::QMatrix4x4:
- {
- if (dstSize >= sizeof(QMatrix4x4))
- return typedCopyConstruct<QMatrix4x4>(src, dst, dstSize);
-
- // special case: copying matrix into variant.
- Q_ASSERT(dstSize >= sizeof(QVariant));
- const QMatrix4x4 *srcMatrix = reinterpret_cast<const QMatrix4x4 *>(src);
- QVariant *dstMatrixVar = reinterpret_cast<QVariant *>(dst);
- new (dstMatrixVar) QVariant(*srcMatrix);
+ dst.setValue<QMatrix4x4>(QMatrix4x4());
return true;
- }
default: break;
}
return false;
}
- bool create(int type, int argc, const void *argv[], QVariant *v)
+ bool create(int type, int argc, const void *argv[], QVariant *v) Q_DECL_OVERRIDE
{
switch (type) {
case QMetaType::QFont: // must specify via js-object.
@@ -555,7 +466,11 @@ public:
}
break;
case QMetaType::QMatrix4x4:
- if (argc == 1) {
+ if (argc == 0) {
+ QMatrix4x4 m;
+ *v = QVariant(m);
+ return true;
+ } else if (argc == 1) {
const qreal *vals = reinterpret_cast<const qreal*>(argv[0]);
QMatrix4x4 m(vals[0], vals[1], vals[2], vals[3],
vals[4], vals[5], vals[6], vals[7],
@@ -580,7 +495,7 @@ public:
return true;
}
- bool createFromString(int type, const QString &s, void *data, size_t dataSize)
+ bool createFromString(int type, const QString &s, void *data, size_t dataSize) Q_DECL_OVERRIDE
{
bool ok = false;
@@ -596,22 +511,14 @@ public:
case QMetaType::QQuaternion:
return createFromStringTyped<QQuaternion>(data, dataSize, quaternionFromString(s, &ok));
case QMetaType::QMatrix4x4:
- {
- if (dataSize >= sizeof(QMatrix4x4))
- return createFromStringTyped<QMatrix4x4>(data, dataSize, matrix4x4FromString(s, &ok));
-
- Q_ASSERT(dataSize >= sizeof(QVariant));
- QVariant *matVar = reinterpret_cast<QVariant *>(data);
- new (matVar) QVariant(matrix4x4FromString(s, &ok));
- return true;
- }
+ return createFromStringTyped<QMatrix4x4>(data, dataSize, matrix4x4FromString(s, &ok));
default: break;
}
return false;
}
- bool createStringFrom(int type, const void *data, QString *s)
+ bool createStringFrom(int type, const void *data, QString *s) Q_DECL_OVERRIDE
{
if (type == QMetaType::QColor) {
const QColor *color = reinterpret_cast<const QColor *>(data);
@@ -622,7 +529,7 @@ public:
return false;
}
- bool variantFromString(const QString &s, QVariant *v)
+ bool variantFromString(const QString &s, QVariant *v) Q_DECL_OVERRIDE
{
QColor c(s);
if (c.isValid()) {
@@ -665,7 +572,7 @@ public:
return false;
}
- bool variantFromString(int type, const QString &s, QVariant *v)
+ bool variantFromString(int type, const QString &s, QVariant *v) Q_DECL_OVERRIDE
{
bool ok = false;
@@ -708,7 +615,7 @@ public:
return false;
}
- bool variantFromJsObject(int type, QQmlV4Handle object, QV4::ExecutionEngine *v4, QVariant *v)
+ bool variantFromJsObject(int type, QQmlV4Handle object, QV4::ExecutionEngine *v4, QVariant *v) Q_DECL_OVERRIDE
{
QV4::Scope scope(v4);
#ifndef QT_NO_DEBUG
@@ -729,12 +636,12 @@ public:
}
template<typename T>
- bool typedEqual(const void *lhs, const void *rhs)
+ bool typedEqual(const void *lhs, const QVariant& rhs)
{
- return (*(reinterpret_cast<const T *>(lhs)) == *(reinterpret_cast<const T *>(rhs)));
+ return (*(reinterpret_cast<const T *>(lhs)) == rhs.value<T>());
}
- bool equal(int type, const void *lhs, const void *rhs, size_t rhsSize)
+ bool equal(int type, const void *lhs, const QVariant &rhs) Q_DECL_OVERRIDE
{
switch (type) {
case QMetaType::QColor:
@@ -750,14 +657,7 @@ public:
case QMetaType::QQuaternion:
return typedEqual<QQuaternion>(lhs, rhs);
case QMetaType::QMatrix4x4:
- {
- if (rhsSize >= sizeof(QMatrix4x4))
- return typedEqual<QMatrix4x4>(lhs, rhs);
-
- Q_ASSERT(rhsSize >= sizeof(QVariant));
- QMatrix4x4 rhsmat = reinterpret_cast<const QVariant *>(rhs)->value<QMatrix4x4>();
- return typedEqual<QMatrix4x4>(lhs, &rhsmat);
- }
+ return typedEqual<QMatrix4x4>(lhs, rhs);
default: break;
}
@@ -774,8 +674,9 @@ public:
return true;
}
- bool store(int type, const void *src, void *dst, size_t dstSize)
+ bool store(int type, const void *src, void *dst, size_t dstSize) Q_DECL_OVERRIDE
{
+ Q_UNUSED(dstSize);
switch (type) {
case QMetaType::QColor:
{
@@ -785,81 +686,41 @@ public:
new (color) QColor(QColor::fromRgba(*rgb));
return true;
}
- case QMetaType::QFont:
- return typedStore<QFont>(src, dst, dstSize);
- case QMetaType::QVector2D:
- return typedStore<QVector2D>(src, dst, dstSize);
- case QMetaType::QVector3D:
- return typedStore<QVector3D>(src, dst, dstSize);
- case QMetaType::QVector4D:
- return typedStore<QVector4D>(src, dst, dstSize);
- case QMetaType::QQuaternion:
- return typedStore<QQuaternion>(src, dst, dstSize);
- case QMetaType::QMatrix4x4:
- {
- if (dstSize >= sizeof(QMatrix4x4))
- return typedStore<QMatrix4x4>(src, dst, dstSize);
-
- // special case: storing matrix into variant
- // eg, QVMEMO QVMEVariant data cell is big enough to store
- // QVariant, but not large enough to store QMatrix4x4.
- Q_ASSERT(dstSize >= sizeof(QVariant));
- const QMatrix4x4 *srcMat = reinterpret_cast<const QMatrix4x4 *>(src);
- QVariant *dstMatVar = reinterpret_cast<QVariant *>(dst);
- new (dstMatVar) QVariant(*srcMat);
- return true;
- }
- default: break;
+ default: break;
}
return false;
}
template<typename T>
- bool typedRead(int srcType, const void *src, size_t srcSize, int dstType, void *dst)
+ bool typedRead(const QVariant& src, int dstType, void *dst)
{
T *dstT = reinterpret_cast<T *>(dst);
- if (srcType == dstType) {
- ASSERT_VALID_SIZE(srcSize, sizeof(T));
- const T *srcT = reinterpret_cast<const T *>(src);
- *dstT = *srcT;
+ if (src.type() == static_cast<uint>(dstType)) {
+ *dstT = src.value<T>();
} else {
*dstT = T();
}
return true;
}
- bool read(int srcType, const void *src, size_t srcSize, int dstType, void *dst)
+ bool read(const QVariant &src, void *dst, int dstType) Q_DECL_OVERRIDE
{
switch (dstType) {
case QMetaType::QColor:
- return typedRead<QColor>(srcType, src, srcSize, dstType, dst);
+ return typedRead<QColor>(src, dstType, dst);
case QMetaType::QFont:
- return typedRead<QFont>(srcType, src, srcSize, dstType, dst);
+ return typedRead<QFont>(src, dstType, dst);
case QMetaType::QVector2D:
- return typedRead<QVector2D>(srcType, src, srcSize, dstType, dst);
+ return typedRead<QVector2D>(src, dstType, dst);
case QMetaType::QVector3D:
- return typedRead<QVector3D>(srcType, src, srcSize, dstType, dst);
+ return typedRead<QVector3D>(src, dstType, dst);
case QMetaType::QVector4D:
- return typedRead<QVector4D>(srcType, src, srcSize, dstType, dst);
+ return typedRead<QVector4D>(src, dstType, dst);
case QMetaType::QQuaternion:
- return typedRead<QQuaternion>(srcType, src, srcSize, dstType, dst);
+ return typedRead<QQuaternion>(src, dstType, dst);
case QMetaType::QMatrix4x4:
- {
- if (srcSize >= sizeof(QMatrix4x4))
- return typedRead<QMatrix4x4>(srcType, src, srcSize, dstType, dst);
-
- // the source data may be stored in a QVariant.
- QMatrix4x4 *dstMat = reinterpret_cast<QMatrix4x4 *>(dst);
- if (srcType == dstType) {
- Q_ASSERT(srcSize >= sizeof(QVariant));
- const QVariant *srcMatVar = reinterpret_cast<const QVariant *>(src);
- *dstMat = srcMatVar->value<QMatrix4x4>();
- } else {
- *dstMat = QMatrix4x4();
- }
- return true;
- }
+ return typedRead<QMatrix4x4>(src, dstType, dst);
default: break;
}
@@ -867,51 +728,33 @@ public:
}
template<typename T>
- bool typedWrite(const void *src, void *dst, size_t dstSize)
+ bool typedWrite(const void *src, QVariant& dst)
{
- ASSERT_VALID_SIZE(dstSize, sizeof(T));
const T *srcT = reinterpret_cast<const T *>(src);
- T *dstT = reinterpret_cast<T *>(dst);
- if (*dstT != *srcT) {
- *dstT = *srcT;
+ if (dst.value<T>() != *srcT) {
+ dst = *srcT;
return true;
}
return false;
}
- bool write(int type, const void *src, void *dst, size_t dstSize)
+ bool write(int type, const void *src, QVariant& dst) Q_DECL_OVERRIDE
{
switch (type) {
case QMetaType::QColor:
- return typedWrite<QColor>(src, dst, dstSize);
+ return typedWrite<QColor>(src, dst);
case QMetaType::QFont:
- return typedWrite<QFont>(src, dst, dstSize);
+ return typedWrite<QFont>(src, dst);
case QMetaType::QVector2D:
- return typedWrite<QVector2D>(src, dst, dstSize);
+ return typedWrite<QVector2D>(src, dst);
case QMetaType::QVector3D:
- return typedWrite<QVector3D>(src, dst, dstSize);
+ return typedWrite<QVector3D>(src, dst);
case QMetaType::QVector4D:
- return typedWrite<QVector4D>(src, dst, dstSize);
+ return typedWrite<QVector4D>(src, dst);
case QMetaType::QQuaternion:
- return typedWrite<QQuaternion>(src, dst, dstSize);
+ return typedWrite<QQuaternion>(src, dst);
case QMetaType::QMatrix4x4:
- {
- if (dstSize >= sizeof(QMatrix4x4))
- return typedWrite<QMatrix4x4>(src, dst, dstSize);
-
- // special case: storing matrix into variant
- // eg, QVMEMO QVMEVariant data cell is big enough to store
- // QVariant, but not large enough to store QMatrix4x4.
- Q_ASSERT(dstSize >= sizeof(QVariant));
- const QMatrix4x4 *srcMat = reinterpret_cast<const QMatrix4x4 *>(src);
- QVariant *dstMatVar = reinterpret_cast<QVariant *>(dst);
- QMatrix4x4 dstMatVal = dstMatVar->value<QMatrix4x4>();
- if (dstMatVal != *srcMat) {
- *dstMatVar = QVariant(*srcMat);
- return true;
- }
- return false;
- }
+ return typedWrite<QMatrix4x4>(src, dst);
default: break;
}
diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp
index 6038967e18..d11229717a 100644
--- a/src/quick/util/qquickimageprovider.cpp
+++ b/src/quick/util/qquickimageprovider.cpp
@@ -33,6 +33,9 @@
#include "qquickimageprovider.h"
+#include "qquickpixmapcache_p.h"
+#include <QtQuick/private/qsgcontext_p.h>
+
QT_BEGIN_NAMESPACE
class QQuickImageProviderPrivate
@@ -95,6 +98,25 @@ QImage QQuickTextureFactory::image() const
return QImage();
}
+/*!
+ Returns a QQuickTextureFactory holding the given image.
+
+ This is typically used as a helper in QQuickImageResponse::textureFactory.
+
+ \since 5.6
+ */
+
+QQuickTextureFactory *QQuickTextureFactory::textureFactoryForImage(const QImage &image)
+{
+ if (image.isNull())
+ return 0;
+ QQuickTextureFactory *texture = QSGContext::createTextureFactoryFromImage(image);
+ if (texture)
+ return texture;
+ return new QQuickDefaultTextureFactory(image);
+}
+
+
/*!
\fn QSGTexture *QQuickTextureFactory::createTexture(QQuickWindow *window) const
@@ -118,6 +140,71 @@ QImage QQuickTextureFactory::image() const
/*!
+ \class QQuickImageResponse
+ \since 5.6
+ \brief The QQuickImageResponse class provides an interface for asynchronous image loading in QQuickAsyncImageProvider.
+ \inmodule QtQuick
+
+ The purpose of an image response is to provide a way for image provider jobs to be executed
+ in an asynchronous way.
+
+ Responses are deleted via \l deleteLater once the finished() signal has been emitted.
+ If you are using QRunnable as base for your QQuickImageResponse
+ ensure automatic deletion is disabled.
+
+ \sa QQuickImageProvider
+*/
+
+/*!
+ Constructs the image response
+*/
+QQuickImageResponse::QQuickImageResponse()
+{
+}
+
+/*!
+ Destructs the image response
+*/
+QQuickImageResponse::~QQuickImageResponse()
+{
+}
+
+/*!
+ Returns the error string for the job execution. An empty string means no error.
+*/
+QString QQuickImageResponse::errorString() const
+{
+ return QString();
+}
+
+/*!
+ This method is used to communicate that the response is no longer required by the engine.
+
+ It may be reimplemented to cancel a request in the provider side, however, it is not mandatory.
+*/
+void QQuickImageResponse::cancel()
+{
+}
+
+/*!
+ \fn void QQuickImageResponse::finished()
+
+ Signals that the job execution has finished (be it successfully, because an error happened or because it was cancelled).
+ */
+
+/*!
+ \fn QQuickTextureFactory *QQuickImageResponse::textureFactory() const
+
+ Returns the texture factory for the job. You can use QQuickTextureFactory::textureFactoryForImage
+ if your provider works with QImage. The engine takes ownership of the returned QQuickTextureFactory.
+
+ \note This method will be called only when needed. For example, it may not be called if there is an
+ error or the job is cancelled. Therefore, allocate the QQuickTextureFactory instance only in this
+ method or otherwise ensure its deletion.
+ */
+
+
+/*!
\class QQuickImageProvider
\since 5.0
\inmodule QtQuick
@@ -213,7 +300,7 @@ QImage QQuickTextureFactory::image() const
To force asynchronous image loading, even for image sources that do not
have the \c asynchronous property set to \c true, you may pass the
- \c QQuickImageProvider::ForceAsynchronousImageLoading flag to the image
+ \c QQmlImageProviderBase::ForceAsynchronousImageLoading flag to the image
provider constructor. This ensures that all image requests for the
provider are handled in a separate thread.
@@ -223,6 +310,12 @@ QImage QQuickTextureFactory::image() const
if \l {Image::}{asynchronous} is set to \c true, the value is ignored
and the image is loaded synchronously.
+ Asynchronous image loading for providers of type other than ImageResponse are
+ executed on a single thread per engine basis. That means that a slow image provider
+ will block the loading of any other request. To avoid that we suggest using QQuickAsyncImageProvider
+ and implement threading on the provider side via a \c QThreadPool or similar.
+ See the \l {imageresponseprovider}{Image Response Provider Example} for a complete implementation.
+
\section2 Image caching
@@ -366,6 +459,42 @@ QQuickTextureFactory *QQuickImageProvider::requestTexture(const QString &id, QSi
}
/*!
+ \class QQuickAsyncImageProvider
+ \since 5.6
+ \inmodule QtQuick
+ \brief The QQuickAsyncImageProvider class provides an interface for for asynchronous control of QML image requests.
+
+ \sa QQuickImageProvider
+*/
+QQuickAsyncImageProvider::QQuickAsyncImageProvider()
+ : QQuickImageProvider(ImageResponse, ForceAsynchronousImageLoading)
+ , d(0) // just as a placeholder in case we need it for the future
+{
+ Q_UNUSED(d);
+}
+
+QQuickAsyncImageProvider::~QQuickAsyncImageProvider()
+{
+}
+
+/*!
+ \fn QQuickImageResponse *QQuickAsyncImageProvider::requestImageResponse(const QString &id, const QSize &requestedSize)
+
+ Implement this method to return the job that will provide the texture with \a id.
+
+ The \a id is the requested image source, with the "image:" scheme and
+ provider identifier removed. For example, if the image \l{Image::}{source}
+ was "image://myprovider/icons/home", the given \a id would be "icons/home".
+
+ The \a requestedSize corresponds to the \l {Image::sourceSize} requested by
+ an Image item. If \a requestedSize is a valid size, the image
+ returned should be of that size.
+
+ \note this method may be called by multiple threads, so ensure the
+ implementation of this method is reentrant.
+*/
+
+/*!
\fn QImage QQuickImageProvider::requestImage(const QString &id, QSize *size, const QSize& requestedSize, bool requestedAutoTransform);
\internal
diff --git a/src/quick/util/qquickimageprovider.h b/src/quick/util/qquickimageprovider.h
index a2b510f606..cc03eb0fa0 100644
--- a/src/quick/util/qquickimageprovider.h
+++ b/src/quick/util/qquickimageprovider.h
@@ -43,6 +43,7 @@ QT_BEGIN_NAMESPACE
class QQuickImageProviderPrivate;
+class QQuickAsyncImageProviderPrivate;
class QSGTexture;
class QQuickWindow;
@@ -56,6 +57,25 @@ public:
virtual QSize textureSize() const = 0;
virtual int textureByteCount() const = 0;
virtual QImage image() const;
+
+ static QQuickTextureFactory *textureFactoryForImage(const QImage &image);
+};
+
+class Q_QUICK_EXPORT QQuickImageResponse : public QObject
+{
+Q_OBJECT
+public:
+ QQuickImageResponse();
+ virtual ~QQuickImageResponse();
+
+ virtual QQuickTextureFactory *textureFactory() const = 0;
+ virtual QString errorString() const;
+
+public Q_SLOTS:
+ virtual void cancel();
+
+Q_SIGNALS:
+ void finished();
};
class Q_QUICK_EXPORT QQuickImageProvider : public QQmlImageProviderBase
@@ -81,6 +101,18 @@ private:
QQuickImageProviderPrivate *d;
};
+class Q_QUICK_EXPORT QQuickAsyncImageProvider : public QQuickImageProvider
+{
+public:
+ QQuickAsyncImageProvider();
+ virtual ~QQuickAsyncImageProvider();
+
+ virtual QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) = 0;
+
+private:
+ QQuickAsyncImageProviderPrivate *d;
+};
+
QT_END_NAMESPACE
#endif // QQUICKIMAGEPROVIDER_H
diff --git a/src/quick/util/qquickpath_p.h b/src/quick/util/qquickpath_p.h
index eea313eeb1..b39b6e5c01 100644
--- a/src/quick/util/qquickpath_p.h
+++ b/src/quick/util/qquickpath_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKPATH_H
#define QQUICKPATH_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include <private/qqmlnullablevalue_p.h>
@@ -265,7 +276,7 @@ public:
: QQuickCurve(parent), _radiusX(0), _radiusY(0), _useLargeArc(false), _direction(Clockwise) {}
enum ArcDirection { Clockwise, Counterclockwise };
- Q_ENUMS(ArcDirection)
+ Q_ENUM(ArcDirection)
qreal radiusX() const;
void setRadiusX(qreal);
diff --git a/src/quick/util/qquickpathinterpolator_p.h b/src/quick/util/qquickpathinterpolator_p.h
index 895aa56078..38c5debbed 100644
--- a/src/quick/util/qquickpathinterpolator_p.h
+++ b/src/quick/util/qquickpathinterpolator_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKPATHINTERPOLATOR_P_H
#define QQUICKPATHINTERPOLATOR_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include <QObject>
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index a1c9205539..ed6da8ac91 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -44,7 +44,6 @@
#include <qpa/qplatformintegration.h>
#include <QtQuick/private/qsgtexture_p.h>
-#include <QtQuick/private/qsgcontext_p.h>
#include <QQuickWindow>
#include <QCoreApplication>
@@ -67,7 +66,7 @@
#include <private/qquickprofiler_p.h>
-#define IMAGEREQUEST_MAX_REQUEST_COUNT 8
+#define IMAGEREQUEST_MAX_NETWORK_REQUEST_COUNT 8
#define IMAGEREQUEST_MAX_REDIRECT_RECURSION 16
#define CACHE_EXPIRE_TIME 30
#define CACHE_REMOVAL_FRACTION 4
@@ -78,7 +77,7 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_DEBUG
-static bool qsg_leak_check = !qgetenv("QML_LEAK_CHECK").isEmpty();
+static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK");
#endif
// The cache limit describes the maximum "junk" in the cache.
@@ -115,16 +114,6 @@ QSGTexture *QQuickDefaultTextureFactory::createTexture(QQuickWindow *window) con
return t;
}
-static QQuickTextureFactory *textureFactoryForImage(const QImage &image)
-{
- if (image.isNull())
- return 0;
- QQuickTextureFactory *texture = QSGContext::createTextureFactoryFromImage(image);
- if (texture)
- return texture;
- return new QQuickDefaultTextureFactory(image);
-}
-
class QQuickPixmapReader;
class QQuickPixmapData;
class QQuickPixmapReply : public QObject
@@ -182,6 +171,7 @@ public:
virtual bool event(QEvent *e);
private slots:
void networkRequestDone();
+ void asyncResponseFinished();
private:
QQuickPixmapReader *reader;
};
@@ -206,8 +196,9 @@ protected:
private:
friend class QQuickPixmapReaderThreadObject;
void processJobs();
- void processJob(QQuickPixmapReply *, const QUrl &, const QSize &, AutoTransform);
+ void processJob(QQuickPixmapReply *, const QUrl &, const QString &, AutoTransform, QQuickImageProvider::ImageType, QQuickImageProvider *);
void networkRequestDone(QNetworkReply *);
+ void asyncResponseFinished(QQuickImageResponse *);
QList<QQuickPixmapReply*> jobs;
QList<QQuickPixmapReply*> cancelled;
@@ -221,7 +212,8 @@ private:
QNetworkAccessManager *networkAccessManager();
QNetworkAccessManager *accessManager;
- QHash<QNetworkReply*,QQuickPixmapReply*> replies;
+ QHash<QNetworkReply*,QQuickPixmapReply*> networkJobs;
+ QHash<QQuickImageResponse*,QQuickPixmapReply*> asyncResponses;
static int replyDownloadProgress;
static int replyFinished;
@@ -445,8 +437,8 @@ QQuickPixmapReader::~QQuickPixmapReader()
delete reply;
}
jobs.clear();
- QList<QQuickPixmapReply*> activeJobs = replies.values();
- foreach (QQuickPixmapReply *reply, activeJobs) {
+ QList<QQuickPixmapReply*> activeJobs = networkJobs.values() + asyncResponses.values();
+ foreach (QQuickPixmapReply *reply, activeJobs ) {
if (reply->loading) {
cancelled.append(reply);
reply->data = 0;
@@ -461,7 +453,7 @@ QQuickPixmapReader::~QQuickPixmapReader()
void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply)
{
- QQuickPixmapReply *job = replies.take(reply);
+ QQuickPixmapReply *job = networkJobs.take(reply);
if (job) {
job->redirectCount++;
@@ -478,7 +470,7 @@ void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply)
QMetaObject::connect(reply, replyDownloadProgress, job, downloadProgress);
QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone);
- replies.insert(reply, job);
+ networkJobs.insert(reply, job);
return;
}
}
@@ -500,7 +492,7 @@ void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply)
// send completion event to the QQuickPixmapReply
mutex.lock();
if (!cancelled.contains(job))
- job->postReply(error, errorString, readSize, textureFactoryForImage(image));
+ job->postReply(error, errorString, readSize, QQuickTextureFactory::textureFactoryForImage(image));
mutex.unlock();
}
reply->deleteLater();
@@ -509,6 +501,34 @@ void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply)
threadObject->processJobs();
}
+void QQuickPixmapReader::asyncResponseFinished(QQuickImageResponse *response)
+{
+ QQuickPixmapReply *job = asyncResponses.take(response);
+
+ if (job) {
+ QQuickTextureFactory *t = 0;
+ QQuickPixmapReply::ReadError error = QQuickPixmapReply::NoError;
+ QString errorString;
+ QSize readSize;
+ if (!response->errorString().isEmpty()) {
+ error = QQuickPixmapReply::Loading;
+ errorString = response->errorString();
+ } else {
+ t = response->textureFactory();
+ }
+ mutex.lock();
+ if (!cancelled.contains(job))
+ job->postReply(error, errorString, t ? t->textureSize() : QSize(), t);
+ else
+ delete t;
+ mutex.unlock();
+ }
+ response->deleteLater();
+
+ // kick off event loop again incase we have dropped below max request count
+ threadObject->processJobs();
+}
+
QQuickPixmapReaderThreadObject::QQuickPixmapReaderThreadObject(QQuickPixmapReader *i)
: reader(i)
{
@@ -535,6 +555,12 @@ void QQuickPixmapReaderThreadObject::networkRequestDone()
reader->networkRequestDone(reply);
}
+void QQuickPixmapReaderThreadObject::asyncResponseFinished()
+{
+ QQuickImageResponse *response = static_cast<QQuickImageResponse *>(sender());
+ reader->asyncResponseFinished(response);
+}
+
void QQuickPixmapReader::processJobs()
{
QMutexLocker locker(&mutex);
@@ -544,16 +570,23 @@ void QQuickPixmapReader::processJobs()
return; // Nothing else to do
// Clean cancelled jobs
- if (cancelled.count()) {
+ if (!cancelled.isEmpty()) {
for (int i = 0; i < cancelled.count(); ++i) {
QQuickPixmapReply *job = cancelled.at(i);
- QNetworkReply *reply = replies.key(job, 0);
+ QNetworkReply *reply = networkJobs.key(job, 0);
if (reply) {
- replies.remove(reply);
+ networkJobs.remove(reply);
if (reply->isRunning()) {
// cancel any jobs already started
reply->close();
}
+ } else {
+ QQuickImageResponse *asyncResponse = asyncResponses.key(job);
+ if (asyncResponse) {
+ asyncResponses.remove(asyncResponse);
+ asyncResponse->cancel();
+ asyncResponse->deleteLater();
+ }
}
PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(job->url));
// deleteLater, since not owned by this thread
@@ -566,27 +599,34 @@ void QQuickPixmapReader::processJobs()
// Find a job we can use
bool usableJob = false;
for (int i = jobs.count() - 1; !usableJob && i >= 0; i--) {
- QQuickPixmapReply *runningJob = jobs[i];
- const QUrl url = runningJob->url;
+ QQuickPixmapReply *job = jobs[i];
+ const QUrl url = job->url;
+ QString localFile;
+ QQuickImageProvider::ImageType imageType = QQuickImageProvider::Invalid;
+ QQuickImageProvider *provider = 0;
if (url.scheme() == QLatin1String("image")) {
+ provider = static_cast<QQuickImageProvider *>(engine->imageProvider(imageProviderId(url)));
+ if (provider)
+ imageType = provider->imageType();
+
usableJob = true;
} else {
- const QString localFile = QQmlFile::urlToLocalFileOrQrc(url);
- usableJob = !localFile.isEmpty() || replies.count() < IMAGEREQUEST_MAX_REQUEST_COUNT;
+ localFile = QQmlFile::urlToLocalFileOrQrc(url);
+ usableJob = !localFile.isEmpty() || networkJobs.count() < IMAGEREQUEST_MAX_NETWORK_REQUEST_COUNT;
}
+
if (usableJob) {
jobs.removeAt(i);
- runningJob->loading = true;
+ job->loading = true;
PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingStarted>(url));
- QSize requestSize = runningJob->requestSize;
- AutoTransform autoTransform = runningJob->autoTransform;
+ AutoTransform autoTransform = job->autoTransform;
locker.unlock();
- processJob(runningJob, url, requestSize, autoTransform);
+ processJob(job, url, localFile, autoTransform, imageType, provider);
locker.relock();
}
}
@@ -597,79 +637,97 @@ void QQuickPixmapReader::processJobs()
}
}
-void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &url,
- const QSize &requestSize, AutoTransform autoTransform)
+void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &url, const QString &localFile,
+ AutoTransform autoTransform, QQuickImageProvider::ImageType imageType, QQuickImageProvider *provider)
{
// fetch
if (url.scheme() == QLatin1String("image")) {
// Use QQuickImageProvider
QSize readSize;
- QQuickImageProvider::ImageType imageType = QQuickImageProvider::Invalid;
- QQuickImageProvider *provider = static_cast<QQuickImageProvider *>(engine->imageProvider(imageProviderId(url)));
- if (provider)
- imageType = provider->imageType();
+ switch (imageType) {
+ case QQuickImageProvider::Invalid:
+ {
+ QString errorStr = QQuickPixmap::tr("Invalid image provider: %1").arg(url.toString());
+ mutex.lock();
+ if (!cancelled.contains(runningJob))
+ runningJob->postReply(QQuickPixmapReply::Loading, errorStr, readSize, 0);
+ mutex.unlock();
+ break;
+ }
- if (imageType == QQuickImageProvider::Invalid) {
- QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::Loading;
- QString errorStr = QQuickPixmap::tr("Invalid image provider: %1").arg(url.toString());
- QImage image;
- mutex.lock();
- if (!cancelled.contains(runningJob))
- runningJob->postReply(errorCode, errorStr, readSize, textureFactoryForImage(image));
- mutex.unlock();
- } else if (imageType == QQuickImageProvider::Image) {
- QImage image = provider->requestImage(imageId(url), &readSize, requestSize);
- QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
- QString errorStr;
- if (image.isNull()) {
- errorCode = QQuickPixmapReply::Loading;
- errorStr = QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString());
+ case QQuickImageProvider::Image:
+ {
+ QImage image = provider->requestImage(imageId(url), &readSize, runningJob->requestSize);
+ QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
+ QString errorStr;
+ if (image.isNull()) {
+ errorCode = QQuickPixmapReply::Loading;
+ errorStr = QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString());
+ }
+ mutex.lock();
+ if (!cancelled.contains(runningJob))
+ runningJob->postReply(errorCode, errorStr, readSize, QQuickTextureFactory::textureFactoryForImage(image));
+ mutex.unlock();
+ break;
}
- mutex.lock();
- if (!cancelled.contains(runningJob))
- runningJob->postReply(errorCode, errorStr, readSize, textureFactoryForImage(image));
- mutex.unlock();
- } else if (imageType == QQuickImageProvider::Pixmap) {
- const QPixmap pixmap = provider->requestPixmap(imageId(url), &readSize, requestSize);
- QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
- QString errorStr;
- if (pixmap.isNull()) {
- errorCode = QQuickPixmapReply::Loading;
- errorStr = QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString());
+
+ case QQuickImageProvider::Pixmap:
+ {
+ const QPixmap pixmap = provider->requestPixmap(imageId(url), &readSize, runningJob->requestSize);
+ QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
+ QString errorStr;
+ if (pixmap.isNull()) {
+ errorCode = QQuickPixmapReply::Loading;
+ errorStr = QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString());
+ }
+ mutex.lock();
+ if (!cancelled.contains(runningJob))
+ runningJob->postReply(errorCode, errorStr, readSize, QQuickTextureFactory::textureFactoryForImage(pixmap.toImage()));
+ mutex.unlock();
+ break;
}
- mutex.lock();
- if (!cancelled.contains(runningJob))
- runningJob->postReply(errorCode, errorStr, readSize, textureFactoryForImage(pixmap.toImage()));
- mutex.unlock();
- } else {
- QQuickTextureFactory *t = provider->requestTexture(imageId(url), &readSize, requestSize);
- QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
- QString errorStr;
- if (!t) {
- errorCode = QQuickPixmapReply::Loading;
- errorStr = QQuickPixmap::tr("Failed to get texture from provider: %1").arg(url.toString());
+
+ case QQuickImageProvider::Texture:
+ {
+ QQuickTextureFactory *t = provider->requestTexture(imageId(url), &readSize, runningJob->requestSize);
+ QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
+ QString errorStr;
+ if (!t) {
+ errorCode = QQuickPixmapReply::Loading;
+ errorStr = QQuickPixmap::tr("Failed to get texture from provider: %1").arg(url.toString());
+ }
+ mutex.lock();
+ if (!cancelled.contains(runningJob))
+ runningJob->postReply(errorCode, errorStr, readSize, t);
+ else
+ delete t;
+ mutex.unlock();
+ break;
}
- mutex.lock();
- if (!cancelled.contains(runningJob))
- runningJob->postReply(errorCode, errorStr, readSize, t);
- else
- delete t;
- mutex.unlock();
+ case QQuickImageProvider::ImageResponse:
+ {
+ QQuickAsyncImageProvider *asyncProvider = static_cast<QQuickAsyncImageProvider*>(provider);
+ QQuickImageResponse *response = asyncProvider->requestImageResponse(imageId(url), runningJob->requestSize);
+
+ QObject::connect(response, SIGNAL(finished()), threadObject, SLOT(asyncResponseFinished()));
+
+ asyncResponses.insert(response, runningJob);
+ break;
+ }
}
} else {
- QString lf = QQmlFile::urlToLocalFileOrQrc(url);
- if (!lf.isEmpty()) {
+ if (!localFile.isEmpty()) {
// Image is local - load/decode immediately
QImage image;
QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
QString errorStr;
- QFile f(lf);
+ QFile f(localFile);
QSize readSize;
if (f.open(QIODevice::ReadOnly)) {
- if (!readImage(url, &f, &image, &errorStr, &readSize, requestSize, autoTransform))
+ if (!readImage(url, &f, &image, &errorStr, &readSize, runningJob->requestSize, autoTransform))
errorCode = QQuickPixmapReply::Loading;
} else {
errorStr = QQuickPixmap::tr("Cannot open: %1").arg(url.toString());
@@ -677,7 +735,7 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u
}
mutex.lock();
if (!cancelled.contains(runningJob))
- runningJob->postReply(errorCode, errorStr, readSize, textureFactoryForImage(image));
+ runningJob->postReply(errorCode, errorStr, readSize, QQuickTextureFactory::textureFactoryForImage(image));
mutex.unlock();
} else {
// Network resource
@@ -688,7 +746,7 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u
QMetaObject::connect(reply, replyDownloadProgress, runningJob, downloadProgress);
QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone);
- replies.insert(reply, runningJob);
+ networkJobs.insert(reply, runningJob);
}
}
}
@@ -781,8 +839,6 @@ inline uint qHash(const QQuickPixmapKey &key)
return qHash(*key.url) ^ (key.size->width()*7) ^ (key.size->height()*17) ^ (key.autoTransform * 0x5c5c5c5c);
}
-class QSGContext;
-
class QQuickPixmapStore : public QObject
{
Q_OBJECT
@@ -1091,7 +1147,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
QImage image = provider->requestImage(imageId(url), &readSize, requestSize);
if (!image.isNull()) {
*ok = true;
- return new QQuickPixmapData(declarativePixmap, url, textureFactoryForImage(image), readSize, requestSize, autoTransform, UsePluginDefault);
+ return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, autoTransform, UsePluginDefault);
}
}
case QQuickImageProvider::Pixmap:
@@ -1099,9 +1155,14 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
QPixmap pixmap = provider->requestPixmap(imageId(url), &readSize, requestSize);
if (!pixmap.isNull()) {
*ok = true;
- return new QQuickPixmapData(declarativePixmap, url, textureFactoryForImage(pixmap.toImage()), readSize, requestSize, autoTransform, UsePluginDefault);
+ return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(pixmap.toImage()), readSize, requestSize, autoTransform, UsePluginDefault);
}
}
+ case QQuickImageProvider::ImageResponse:
+ {
+ // Fall through, ImageResponse providers never get here
+ Q_ASSERT(imageType != QQuickImageProvider::ImageResponse && "Sync call to ImageResponse provider");
+ }
}
// provider has bad image type, or provider returned null image
@@ -1122,7 +1183,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
AutoTransform appliedTransform = autoTransform;
if (readImage(url, &f, &image, &errorString, &readSize, requestSize, appliedTransform)) {
*ok = true;
- return new QQuickPixmapData(declarativePixmap, url, textureFactoryForImage(image), readSize, requestSize, autoTransform, appliedTransform);
+ return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, autoTransform, appliedTransform);
}
errorString = QQuickPixmap::tr("Invalid image data: %1").arg(url.toString());
@@ -1259,7 +1320,7 @@ void QQuickPixmap::setImage(const QImage &p)
clear();
if (!p.isNull())
- d = new QQuickPixmapData(this, textureFactoryForImage(p));
+ d = new QQuickPixmapData(this, QQuickTextureFactory::textureFactoryForImage(p));
}
void QQuickPixmap::setPixmap(const QQuickPixmap &other)
diff --git a/src/quick/util/qquickpixmapcache_p.h b/src/quick/util/qquickpixmapcache_p.h
index 482a2e5653..6ab318ba7b 100644
--- a/src/quick/util/qquickpixmapcache_p.h
+++ b/src/quick/util/qquickpixmapcache_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKPIXMAPCACHE_H
#define QQUICKPIXMAPCACHE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qcoreapplication.h>
#include <QtCore/qstring.h>
#include <QtGui/qpixmap.h>
diff --git a/src/quick/util/qquickprofiler.cpp b/src/quick/util/qquickprofiler.cpp
index d9132a9cb2..77ffda474a 100644
--- a/src/quick/util/qquickprofiler.cpp
+++ b/src/quick/util/qquickprofiler.cpp
@@ -33,8 +33,7 @@
#include "qquickprofiler_p.h"
#include <QCoreApplication>
-#include <private/qqmldebugservice_p.h>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
QT_BEGIN_NAMESPACE
@@ -113,18 +112,22 @@ void QQuickProfilerData::toByteArrays(QList<QByteArray> &messages) const
qint64 QQuickProfiler::sendMessages(qint64 until, QList<QByteArray> &messages)
{
QMutexLocker lock(&m_dataMutex);
- while (next < m_data.size() && m_data[next].time <= until) {
- m_data[next++].toByteArrays(messages);
+ while (next < m_data.size()) {
+ if (m_data[next].time <= until)
+ m_data[next++].toByteArrays(messages);
+ else
+ return m_data[next].time;
}
- return next < m_data.size() ? m_data[next].time : -1;
+ m_data.clear();
+ next = 0;
+ return -1;
}
-void QQuickProfiler::initialize()
+void QQuickProfiler::initialize(QQmlProfilerService *service)
{
Q_ASSERT(s_instance == 0);
- QQmlProfilerService *service = QQmlProfilerService::instance();
s_instance = new QQuickProfiler(service);
- QQmlProfilerService::instance()->addGlobalProfiler(s_instance);
+ service->addGlobalProfiler(s_instance);
}
void animationTimerCallback(qint64 delta)
@@ -196,17 +199,12 @@ void QQuickProfiler::stopProfilingImpl()
{
QMutexLocker lock(&m_dataMutex);
featuresEnabled = 0;
- next = 0;
}
service->dataReady(this);
}
void QQuickProfiler::reportDataImpl()
{
- {
- QMutexLocker lock(&m_dataMutex);
- next = 0;
- }
service->dataReady(this);
}
diff --git a/src/quick/util/qquickprofiler_p.h b/src/quick/util/qquickprofiler_p.h
index aaed4bd60e..6b6e7fa062 100644
--- a/src/quick/util/qquickprofiler_p.h
+++ b/src/quick/util/qquickprofiler_p.h
@@ -318,7 +318,7 @@ public:
return featuresEnabled & (1 << QQuickProfiler::ProfileSceneGraph);
}
- static void initialize();
+ static void initialize(QQmlProfilerService *service);
virtual ~QQuickProfiler();
diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp
index 6c333c6b13..bda341412b 100644
--- a/src/quick/util/qquickpropertychanges.cpp
+++ b/src/quick/util/qquickpropertychanges.cpp
@@ -145,12 +145,12 @@ public:
QQmlBoundSignalExpressionPointer reverseExpression;
QQmlBoundSignalExpressionPointer rewindExpression;
- virtual void execute(Reason) {
+ virtual void execute() {
QQmlPropertyPrivate::setSignalExpression(property, expression);
}
virtual bool isReversable() { return true; }
- virtual void reverse(Reason) {
+ virtual void reverse() {
QQmlPropertyPrivate::setSignalExpression(property, reverseExpression);
}
@@ -451,7 +451,7 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions()
QQmlBinding *newBinding = 0;
if (e.id != QQmlBinding::Invalid) {
QV4::Scope scope(QQmlEnginePrivate::getV4Engine(qmlEngine(this)));
- QV4::ScopedValue function(scope, QV4::QmlBindingWrapper::createQmlCallableForFunction(context, object(), d->cdata->compilationUnit->runtimeFunctions[e.id]));
+ QV4::ScopedValue function(scope, QV4::FunctionObject::createQmlFunction(context, object(), d->cdata->compilationUnit->runtimeFunctions[e.id]));
newBinding = new QQmlBinding(function, object(), context);
}
// QQmlBinding *newBinding = e.id != QQmlBinding::Invalid ? QQmlBinding::createBinding(e.id, object(), qmlContext(this)) : 0;
@@ -464,10 +464,10 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions()
// XXX TODO: add a static QQmlJavaScriptExpression::evaluate(QString)
// so that we can avoid creating then destroying the binding in this case.
a.toValue = newBinding->evaluate();
- newBinding->destroy();
+ delete newBinding;
} else {
newBinding->setTarget(prop);
- a.toBinding = QQmlAbstractBinding::getPointer(newBinding);
+ a.toBinding = newBinding;
a.deletableToBinding = true;
}
@@ -558,11 +558,7 @@ void QQuickPropertyChanges::changeValue(const QString &name, const QVariant &val
if (entry.name == name) {
expressionIterator.remove();
if (state() && state()->isStateActive()) {
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(d->property(name));
- if (oldBinding) {
- QQmlPropertyPrivate::setBinding(d->property(name), 0);
- oldBinding->destroy();
- }
+ QQmlPropertyPrivate::removeBinding(d->property(name));
d->property(name).write(value);
}
@@ -624,15 +620,9 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString
if (entry.name == name) {
entry.expression = expression;
if (state() && state()->isStateActive()) {
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(d->property(name));
- if (oldBinding) {
- QQmlPropertyPrivate::setBinding(d->property(name), 0);
- oldBinding->destroy();
- }
-
QQmlBinding *newBinding = new QQmlBinding(expression, object(), qmlContext(this));
newBinding->setTarget(d->property(name));
- QQmlPropertyPrivate::setBinding(d->property(name), newBinding, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
+ QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
}
return;
}
@@ -651,7 +641,7 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString
QQmlBinding *newBinding = new QQmlBinding(expression, object(), qmlContext(this));
newBinding->setTarget(d->property(name));
- QQmlPropertyPrivate::setBinding(d->property(name), newBinding, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
+ QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
} else {
QQuickStateAction action;
action.restore = restoreEntryValues();
@@ -666,10 +656,10 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString
// XXX TODO: add a static QQmlJavaScriptExpression::evaluate(QString)
// so that we can avoid creating then destroying the binding in this case.
action.toValue = newBinding->evaluate();
- newBinding->destroy();
+ delete newBinding;
} else {
- newBinding->setTarget(d->property(name));
- action.toBinding = QQmlAbstractBinding::getPointer(newBinding);
+ newBinding->setTarget(action.property);
+ action.toBinding = newBinding;
action.deletableToBinding = true;
state()->addEntryToRevertList(action);
@@ -677,7 +667,7 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString
if (oldBinding)
oldBinding->setEnabled(false, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
- QQmlPropertyPrivate::setBinding(action.property, newBinding, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
+ QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
}
}
}
diff --git a/src/quick/util/qquickpropertychanges_p.h b/src/quick/util/qquickpropertychanges_p.h
index 15e5ec2936..d5938fd102 100644
--- a/src/quick/util/qquickpropertychanges_p.h
+++ b/src/quick/util/qquickpropertychanges_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKPROPERTYCHANGES_H
#define QQUICKPROPERTYCHANGES_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickstatechangescript_p.h"
#include <private/qqmlcustomparser_p.h>
diff --git a/src/quick/util/qquickshortcut.cpp b/src/quick/util/qquickshortcut.cpp
index 36c6933af4..e6f66f7bf1 100644
--- a/src/quick/util/qquickshortcut.cpp
+++ b/src/quick/util/qquickshortcut.cpp
@@ -134,6 +134,37 @@ void QQuickShortcut::setSequence(const QVariant &sequence)
}
/*!
+ \qmlproperty string QtQuick::Shortcut::nativeText
+ \since 5.6
+
+ This property provides the shortcut's key sequence as a platform specific
+ string. This means that it will be shown translated, and on OS X it will
+ resemble a key sequence from the menu bar. It is best to display this text
+ to the user (for example, on a tooltip).
+
+ \sa sequence, portableText
+*/
+QString QQuickShortcut::nativeText() const
+{
+ return m_shortcut.toString(QKeySequence::NativeText);
+}
+
+/*!
+ \qmlproperty string QtQuick::Shortcut::portableText
+ \since 5.6
+
+ This property provides the shortcut's key sequence as a string in a
+ "portable" format, suitable for reading and writing to a file. In many
+ cases, it will look similar to the native text on Windows and X11.
+
+ \sa sequence, nativeText
+*/
+QString QQuickShortcut::portableText() const
+{
+ return m_shortcut.toString(QKeySequence::PortableText);
+}
+
+/*!
\qmlproperty bool QtQuick::Shortcut::enabled
This property holds whether the shortcut is enabled.
diff --git a/src/quick/util/qquickshortcut_p.h b/src/quick/util/qquickshortcut_p.h
index e16ac9df20..d8a233af78 100644
--- a/src/quick/util/qquickshortcut_p.h
+++ b/src/quick/util/qquickshortcut_p.h
@@ -57,6 +57,8 @@ class QQuickShortcut : public QObject, public QQmlParserStatus
Q_OBJECT
Q_INTERFACES(QQmlParserStatus)
Q_PROPERTY(QVariant sequence READ sequence WRITE setSequence NOTIFY sequenceChanged FINAL)
+ Q_PROPERTY(QString nativeText READ nativeText NOTIFY sequenceChanged FINAL REVISION 1)
+ Q_PROPERTY(QString portableText READ portableText NOTIFY sequenceChanged FINAL REVISION 1)
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged FINAL)
Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY autoRepeatChanged FINAL)
Q_PROPERTY(Qt::ShortcutContext context READ context WRITE setContext NOTIFY contextChanged FINAL)
@@ -68,6 +70,9 @@ public:
QVariant sequence() const;
void setSequence(const QVariant &sequence);
+ QString nativeText() const;
+ QString portableText() const;
+
bool isEnabled() const;
void setEnabled(bool enabled);
diff --git a/src/quick/util/qquicksmoothedanimation_p.h b/src/quick/util/qquicksmoothedanimation_p.h
index 68479aa629..9f18170283 100644
--- a/src/quick/util/qquicksmoothedanimation_p.h
+++ b/src/quick/util/qquicksmoothedanimation_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKSMOOTHEDANIMATION_H
#define QQUICKSMOOTHEDANIMATION_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include "qquickanimation_p.h"
@@ -47,7 +58,6 @@ class Q_AUTOTEST_EXPORT QQuickSmoothedAnimation : public QQuickNumberAnimation
{
Q_OBJECT
Q_DECLARE_PRIVATE(QQuickSmoothedAnimation)
- Q_ENUMS(ReversingMode)
Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity NOTIFY velocityChanged)
Q_PROPERTY(ReversingMode reversingMode READ reversingMode WRITE setReversingMode NOTIFY reversingModeChanged)
@@ -55,6 +65,7 @@ class Q_AUTOTEST_EXPORT QQuickSmoothedAnimation : public QQuickNumberAnimation
public:
enum ReversingMode { Eased, Immediate, Sync };
+ Q_ENUM(ReversingMode)
QQuickSmoothedAnimation(QObject *parent = 0);
~QQuickSmoothedAnimation();
diff --git a/src/quick/util/qquickspringanimation_p.h b/src/quick/util/qquickspringanimation_p.h
index 082fd341f7..b924c4c72e 100644
--- a/src/quick/util/qquickspringanimation_p.h
+++ b/src/quick/util/qquickspringanimation_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKSPRINGANIMATION_H
#define QQUICKSPRINGANIMATION_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include "qquickanimation_p.h"
diff --git a/src/quick/util/qquickstate.cpp b/src/quick/util/qquickstate.cpp
index 98d7a76c7e..be676680a6 100644
--- a/src/quick/util/qquickstate.cpp
+++ b/src/quick/util/qquickstate.cpp
@@ -78,7 +78,7 @@ QQuickStateActionEvent::~QQuickStateActionEvent()
{
}
-void QQuickStateActionEvent::execute(Reason)
+void QQuickStateActionEvent::execute()
{
}
@@ -87,7 +87,7 @@ bool QQuickStateActionEvent::isReversable()
return false;
}
-void QQuickStateActionEvent::reverse(Reason)
+void QQuickStateActionEvent::reverse()
{
}
@@ -157,11 +157,6 @@ QQuickState::~QQuickState()
Q_D(QQuickState);
if (d->group)
d->group->removeState(this);
-
- foreach (const QQuickSimpleAction &action, d->revertList) {
- if (action.binding())
- action.binding()->destroy();
- }
}
/*!
@@ -361,8 +356,7 @@ void QQuickState::cancel()
void QQuickStateAction::deleteFromBinding()
{
if (fromBinding) {
- QQmlPropertyPrivate::setBinding(property, 0);
- fromBinding->destroy();
+ QQmlPropertyPrivate::removeBinding(property);
fromBinding = 0;
}
}
@@ -413,9 +407,6 @@ bool QQuickState::changeBindingInRevertList(QObject *target, const QString &name
while (revertListIterator.hasNext()) {
QQuickSimpleAction &simpleAction = revertListIterator.next();
if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) {
- if (simpleAction.binding())
- simpleAction.binding()->destroy();
-
simpleAction.setBinding(binding);
return true;
}
@@ -435,15 +426,11 @@ bool QQuickState::removeEntryFromRevertList(QObject *target, const QString &name
while (revertListIterator.hasNext()) {
QQuickSimpleAction &simpleAction = revertListIterator.next();
if (simpleAction.property().object() == target && simpleAction.property().name() == name) {
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(simpleAction.property());
- if (oldBinding) {
- QQmlPropertyPrivate::setBinding(simpleAction.property(), 0);
- oldBinding->destroy();
- }
+ QQmlPropertyPrivate::removeBinding(simpleAction.property());
simpleAction.property().write(simpleAction.value());
if (simpleAction.binding())
- QQmlPropertyPrivate::setBinding(simpleAction.property(), simpleAction.binding());
+ QQmlPropertyPrivate::setBinding(simpleAction.binding());
revertListIterator.remove();
return true;
@@ -473,15 +460,11 @@ void QQuickState::removeAllEntriesFromRevertList(QObject *target)
while (revertListIterator.hasNext()) {
QQuickSimpleAction &simpleAction = revertListIterator.next();
if (simpleAction.property().object() == target) {
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(simpleAction.property());
- if (oldBinding) {
- QQmlPropertyPrivate::setBinding(simpleAction.property(), 0);
- oldBinding->destroy();
- }
+ QQmlPropertyPrivate::removeBinding(simpleAction.property());
simpleAction.property().write(simpleAction.value());
if (simpleAction.binding())
- QQmlPropertyPrivate::setBinding(simpleAction.property(), simpleAction.binding());
+ QQmlPropertyPrivate::setBinding(simpleAction.binding());
revertListIterator.remove();
}
@@ -494,18 +477,15 @@ void QQuickState::addEntriesToRevertList(const QList<QQuickStateAction> &actionL
Q_D(QQuickState);
if (isStateActive()) {
QList<QQuickSimpleAction> simpleActionList;
+ simpleActionList.reserve(actionList.count());
QListIterator<QQuickStateAction> actionListIterator(actionList);
while(actionListIterator.hasNext()) {
const QQuickStateAction &action = actionListIterator.next();
QQuickSimpleAction simpleAction(action);
action.property.write(action.toValue);
- if (!action.toBinding.isNull()) {
- QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(simpleAction.property());
- if (oldBinding)
- QQmlPropertyPrivate::setBinding(simpleAction.property(), 0);
- QQmlPropertyPrivate::setBinding(simpleAction.property(), action.toBinding.data(), QQmlPropertyPrivate::DontRemoveBinding);
- }
+ if (action.toBinding)
+ QQmlPropertyPrivate::setBinding(action.toBinding.data());
simpleActionList.append(simpleAction);
}
@@ -619,7 +599,7 @@ void QQuickState::apply(QQuickTransition *trans, QQuickState *revert)
for (int jj = 0; jj < d->revertList.count(); ++jj) {
if (d->revertList.at(jj).property() == action.property) {
found = true;
- if (d->revertList.at(jj).binding() != action.fromBinding) {
+ if (d->revertList.at(jj).binding() != action.fromBinding.data()) {
action.deleteFromBinding();
}
break;
@@ -663,16 +643,13 @@ void QQuickState::apply(QQuickTransition *trans, QQuickState *revert)
}
if (!found) {
QVariant cur = d->revertList.at(ii).property().read();
- QQmlAbstractBinding *delBinding =
- QQmlPropertyPrivate::setBinding(d->revertList.at(ii).property(), 0);
- if (delBinding)
- delBinding->destroy();
+ QQmlPropertyPrivate::removeBinding(d->revertList.at(ii).property());
QQuickStateAction a;
a.property = d->revertList.at(ii).property();
a.fromValue = cur;
a.toValue = d->revertList.at(ii).value();
- a.toBinding = QQmlAbstractBinding::getPointer(d->revertList.at(ii).binding());
+ a.toBinding = d->revertList.at(ii).binding();
a.specifiedObject = d->revertList.at(ii).specifiedObject();
a.specifiedProperty = d->revertList.at(ii).specifiedProperty();
a.event = d->revertList.at(ii).event();
diff --git a/src/quick/util/qquickstate_p.h b/src/quick/util/qquickstate_p.h
index 0c774635d8..6d051ff578 100644
--- a/src/quick/util/qquickstate_p.h
+++ b/src/quick/util/qquickstate_p.h
@@ -34,18 +34,30 @@
#ifndef QQUICKSTATE_H
#define QQUICKSTATE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include <qqmlproperty.h>
#include <QtCore/qobject.h>
#include <QtCore/qsharedpointer.h>
#include <private/qtquickglobal_p.h>
+#include <private/qqmlabstractbinding_p.h>
QT_BEGIN_NAMESPACE
class QQuickStateActionEvent;
-class QQmlAbstractBinding;
class QQmlBinding;
class QQmlExpression;
+
class QQuickStateAction
{
public:
@@ -63,8 +75,8 @@ public:
QVariant fromValue;
QVariant toValue;
- QQmlAbstractBinding *fromBinding;
- QWeakPointer<QQmlAbstractBinding> toBinding;
+ QQmlAbstractBinding::Ptr fromBinding;
+ QQmlAbstractBinding::Ptr toBinding;
QQuickStateActionEvent *event;
//strictly for matching
@@ -80,13 +92,12 @@ public:
virtual ~QQuickStateActionEvent();
enum EventType { Script, SignalHandler, ParentChange, AnchorChanges };
- enum Reason { ActualChange, FastForward };
virtual EventType type() const = 0;
- virtual void execute(Reason reason = ActualChange);
+ virtual void execute();
virtual bool isReversable();
- virtual void reverse(Reason reason = ActualChange);
+ virtual void reverse();
virtual void saveOriginals() {}
virtual bool needsCopy() { return false; }
virtual void copyOriginals(QQuickStateActionEvent *) {}
diff --git a/src/quick/util/qquickstate_p_p.h b/src/quick/util/qquickstate_p_p.h
index fc589f0d2d..e6ecb424e5 100644
--- a/src/quick/util/qquickstate_p_p.h
+++ b/src/quick/util/qquickstate_p_p.h
@@ -71,7 +71,7 @@ public:
if (state == StartState) {
m_value = a.fromValue;
if (QQmlPropertyPrivate::binding(m_property)) {
- m_binding = QQmlAbstractBinding::getPointer(QQmlPropertyPrivate::binding(m_property));
+ m_binding = QQmlPropertyPrivate::binding(m_property);
}
m_reverseEvent = true;
} else {
@@ -88,7 +88,7 @@ public:
QQuickSimpleAction(const QQuickSimpleAction &other)
: m_property(other.m_property),
m_value(other.m_value),
- m_binding(QQmlAbstractBinding::getPointer(other.binding())),
+ m_binding(other.binding()),
m_specifiedObject(other.m_specifiedObject),
m_specifiedProperty(other.m_specifiedProperty),
m_event(other.m_event),
@@ -100,7 +100,7 @@ public:
{
m_property = other.m_property;
m_value = other.m_value;
- m_binding = QQmlAbstractBinding::getPointer(other.binding());
+ m_binding = other.binding();
m_specifiedObject = other.m_specifiedObject;
m_specifiedProperty = other.m_specifiedProperty;
m_event = other.m_event;
@@ -131,7 +131,7 @@ public:
void setBinding(QQmlAbstractBinding *binding)
{
- m_binding = QQmlAbstractBinding::getPointer(binding);
+ m_binding = binding;
}
QQmlAbstractBinding *binding() const
@@ -162,7 +162,7 @@ public:
private:
QQmlProperty m_property;
QVariant m_value;
- QQmlAbstractBinding::Pointer m_binding;
+ QQmlAbstractBinding::Ptr m_binding;
QObject *m_specifiedObject;
QString m_specifiedProperty;
QQuickStateActionEvent *m_event;
diff --git a/src/quick/util/qquickstatechangescript.cpp b/src/quick/util/qquickstatechangescript.cpp
index 6d25b9791d..c276183d62 100644
--- a/src/quick/util/qquickstatechangescript.cpp
+++ b/src/quick/util/qquickstatechangescript.cpp
@@ -118,7 +118,7 @@ void QQuickStateChangeScript::setName(const QString &n)
d->name = n;
}
-void QQuickStateChangeScript::execute(Reason)
+void QQuickStateChangeScript::execute()
{
Q_D(QQuickStateChangeScript);
if (!d->script.isEmpty()) {
diff --git a/src/quick/util/qquickstatechangescript_p.h b/src/quick/util/qquickstatechangescript_p.h
index 4ff6f0db3e..f9580a53df 100644
--- a/src/quick/util/qquickstatechangescript_p.h
+++ b/src/quick/util/qquickstatechangescript_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKSTATEOPERATIONS_H
#define QQUICKSTATEOPERATIONS_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickstate_p.h"
#include <qqmlscriptstring.h>
@@ -62,7 +73,7 @@ public:
QString name() const;
void setName(const QString &);
- virtual void execute(Reason reason = ActualChange);
+ virtual void execute();
};
diff --git a/src/quick/util/qquickstategroup_p.h b/src/quick/util/qquickstategroup_p.h
index 8ea2dbc4b3..03676a68fb 100644
--- a/src/quick/util/qquickstategroup_p.h
+++ b/src/quick/util/qquickstategroup_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKSTATEGROUP_H
#define QQUICKSTATEGROUP_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickstate_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/quick/util/qquickstyledtext.cpp b/src/quick/util/qquickstyledtext.cpp
index 6ed32c10e2..c411207121 100644
--- a/src/quick/util/qquickstyledtext.cpp
+++ b/src/quick/util/qquickstyledtext.cpp
@@ -182,7 +182,7 @@ void QQuickStyledText::parse(const QString &string, QTextLayout &layout,
void QQuickStyledTextPrivate::parse()
{
- QList<QTextLayout::FormatRange> ranges;
+ QVector<QTextLayout::FormatRange> ranges;
QStack<QTextCharFormat> formatStack;
QString drawText;
@@ -283,7 +283,7 @@ void QQuickStyledTextPrivate::parse()
}
layout.setText(drawText);
- layout.setAdditionalFormats(ranges);
+ layout.setFormats(ranges);
}
void QQuickStyledTextPrivate::appendText(const QString &textIn, int start, int length, QString &textOut)
diff --git a/src/quick/util/qquickstyledtext_p.h b/src/quick/util/qquickstyledtext_p.h
index 2f07a740e5..cd6710ff26 100644
--- a/src/quick/util/qquickstyledtext_p.h
+++ b/src/quick/util/qquickstyledtext_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKSTYLEDTEXT_H
#define QQUICKSTYLEDTEXT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QSize>
#include <QPointF>
#include <QList>
diff --git a/src/quick/util/qquicksvgparser_p.h b/src/quick/util/qquicksvgparser_p.h
index ed9a7558d0..60661a7840 100644
--- a/src/quick/util/qquicksvgparser_p.h
+++ b/src/quick/util/qquicksvgparser_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKSVGPARSER_P_H
#define QQUICKSVGPARSER_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qstring.h>
#include <QtGui/qpainterpath.h>
diff --git a/src/quick/util/qquicksystempalette_p.h b/src/quick/util/qquicksystempalette_p.h
index 143efa1c12..99654d76f7 100644
--- a/src/quick/util/qquicksystempalette_p.h
+++ b/src/quick/util/qquicksystempalette_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKSYSTEMPALETTE_H
#define QQUICKSYSTEMPALETTE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include <QtCore/qobject.h>
@@ -45,7 +56,6 @@ class QQuickSystemPalettePrivate;
class Q_AUTOTEST_EXPORT QQuickSystemPalette : public QObject
{
Q_OBJECT
- Q_ENUMS(ColorGroup)
Q_DECLARE_PRIVATE(QQuickSystemPalette)
Q_PROPERTY(QQuickSystemPalette::ColorGroup colorGroup READ colorGroup WRITE setColorGroup NOTIFY paletteChanged)
@@ -69,6 +79,7 @@ public:
~QQuickSystemPalette();
enum ColorGroup { Active = QPalette::Active, Inactive = QPalette::Inactive, Disabled = QPalette::Disabled };
+ Q_ENUM(ColorGroup)
QColor window() const;
QColor windowText() const;
diff --git a/src/quick/util/qquicktextmetrics.cpp b/src/quick/util/qquicktextmetrics.cpp
index 1dd787f4a5..13ccb515ce 100644
--- a/src/quick/util/qquicktextmetrics.cpp
+++ b/src/quick/util/qquicktextmetrics.cpp
@@ -244,7 +244,7 @@ QRectF QQuickTextMetrics::tightBoundingRect() const
}
/*!
- \qmlmethod string QtQuick::TextMetrics::elidedText
+ \qmlproperty string QtQuick::TextMetrics::elidedText
This property holds an elided version of the string (i.e., a string with
"..." in it) if the string \l text is wider than \l elideWidth. If the
diff --git a/src/quick/util/qquicktextmetrics_p.h b/src/quick/util/qquicktextmetrics_p.h
index c0265d9507..96e304b907 100644
--- a/src/quick/util/qquicktextmetrics_p.h
+++ b/src/quick/util/qquicktextmetrics_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKTEXTMETRICS_H
#define QQUICKTEXTMETRICS_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include <QtGui/QFontMetricsF>
diff --git a/src/quick/util/qquicktimeline.cpp b/src/quick/util/qquicktimeline.cpp
index 74754a0bfb..88fc03bba8 100644
--- a/src/quick/util/qquicktimeline.cpp
+++ b/src/quick/util/qquicktimeline.cpp
@@ -659,7 +659,7 @@ void QQuickTimeLine::complete()
*/
void QQuickTimeLine::clear()
{
- for (QQuickTimeLinePrivate::Ops::const_iterator iter = d->ops.begin(), cend = d->ops.end(); iter != cend; ++iter)
+ for (QQuickTimeLinePrivate::Ops::const_iterator iter = d->ops.cbegin(), cend = d->ops.cend(); iter != cend; ++iter)
iter.key()->_t = 0;
d->ops.clear();
d->length = 0;
diff --git a/src/quick/util/qquicktransition.cpp b/src/quick/util/qquicktransition.cpp
index 5c1c34b62f..2eaf8261af 100644
--- a/src/quick/util/qquicktransition.cpp
+++ b/src/quick/util/qquicktransition.cpp
@@ -432,7 +432,7 @@ bool QQuickTransition::running() const
This property holds a list of the animations to be run for this transition.
- \snippet qml/dynamicscene/dynamicscene.qml top-level transitions
+ \snippet ../qml/dynamicscene/dynamicscene.qml top-level transitions
The top-level animations are run in parallel. To run them sequentially,
define them within a SequentialAnimation:
diff --git a/src/quick/util/qquicktransition_p.h b/src/quick/util/qquicktransition_p.h
index 826df6794b..d4cd1a087b 100644
--- a/src/quick/util/qquicktransition_p.h
+++ b/src/quick/util/qquicktransition_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKTRANSITION_H
#define QQUICKTRANSITION_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickstate_p.h"
#include <private/qabstractanimationjob_p.h>
#include <qqml.h>
diff --git a/src/quick/util/qquicktransitionmanager.cpp b/src/quick/util/qquicktransitionmanager.cpp
index 832596d9a2..3992df993c 100644
--- a/src/quick/util/qquicktransitionmanager.cpp
+++ b/src/quick/util/qquicktransitionmanager.cpp
@@ -101,8 +101,8 @@ void QQuickTransitionManager::complete()
void QQuickTransitionManagerPrivate::applyBindings()
{
foreach(const QQuickStateAction &action, bindingsList) {
- if (!action.toBinding.isNull()) {
- QQmlPropertyPrivate::setBinding(action.property, action.toBinding.data());
+ if (action.toBinding) {
+ QQmlPropertyPrivate::setBinding(action.toBinding.data());
} else if (action.event) {
if (action.reverseEvent)
action.event->reverse();
@@ -131,7 +131,7 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
if (action.toBinding)
d->bindingsList << action;
if (action.fromBinding)
- QQmlPropertyPrivate::setBinding(action.property, 0); // Disable current binding
+ QQmlPropertyPrivate::removeBinding(action.property); // Disable current binding
if (action.event && action.event->changesBindings()) { //### assume isReversable()?
d->bindingsList << action;
action.event->clearBindings();
@@ -146,24 +146,21 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
//
// This doesn't catch everything, and it might be a little fragile in
// some cases - but whatcha going to do?
- //
- // Note that we only fast forward if both a transition and bindings are
- // present, as it is unnecessary (and potentially expensive) otherwise.
if (transition && !d->bindingsList.isEmpty()) {
// Apply all the property and binding changes
for (int ii = 0; ii < applyList.size(); ++ii) {
const QQuickStateAction &action = applyList.at(ii);
- if (!action.toBinding.isNull()) {
- QQmlPropertyPrivate::setBinding(action.property, action.toBinding.data(), QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
+ if (action.toBinding) {
+ QQmlPropertyPrivate::setBinding(action.toBinding.data(), QQmlPropertyPrivate::None, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
} else if (!action.event) {
QQmlPropertyPrivate::write(action.property, action.toValue, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
} else if (action.event->isReversable()) {
if (action.reverseEvent)
- action.event->reverse(QQuickStateActionEvent::FastForward);
+ action.event->reverse();
else
- action.event->execute(QQuickStateActionEvent::FastForward);
+ action.event->execute();
}
}
@@ -175,7 +172,7 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
continue;
}
const QQmlProperty &prop = action->property;
- if (!action->toBinding.isNull() || !action->toValue.isValid()) {
+ if (action->toBinding || !action->toValue.isValid()) {
action->toValue = prop.read();
}
}
@@ -192,7 +189,7 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
}
if (action.toBinding)
- QQmlPropertyPrivate::setBinding(action.property, 0); // Make sure this is disabled during the transition
+ QQmlPropertyPrivate::removeBinding(action.property); // Make sure this is disabled during the transition
QQmlPropertyPrivate::write(action.property, action.fromValue, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
}
@@ -269,10 +266,9 @@ void QQuickTransitionManager::cancel()
for(int i = 0; i < d->bindingsList.count(); ++i) {
QQuickStateAction action = d->bindingsList[i];
- if (!action.toBinding.isNull() && action.deletableToBinding) {
- QQmlPropertyPrivate::setBinding(action.property, 0);
- action.toBinding.data()->destroy();
- action.toBinding.clear();
+ if (action.toBinding && action.deletableToBinding) {
+ QQmlPropertyPrivate::removeBinding(action.property);
+ action.toBinding = 0;
action.deletableToBinding = false;
} else if (action.event) {
//### what do we do here?
diff --git a/src/quick/util/qquicktransitionmanager_p_p.h b/src/quick/util/qquicktransitionmanager_p_p.h
index a6d91d7efd..f39cde77b0 100644
--- a/src/quick/util/qquicktransitionmanager_p_p.h
+++ b/src/quick/util/qquicktransitionmanager_p_p.h
@@ -45,14 +45,14 @@
// We mean it.
//
-#include "qquickstatechangescript_p.h"
#include "qquickanimation_p.h"
QT_BEGIN_NAMESPACE
-class QQuickStatePrivate;
+class QQuickState;
+class QQuickStateAction;
class QQuickTransitionManagerPrivate;
-class Q_AUTOTEST_EXPORT QQuickTransitionManager
+class Q_QUICK_PRIVATE_EXPORT QQuickTransitionManager
{
public:
QQuickTransitionManager();
diff --git a/src/quick/util/qquickutilmodule.cpp b/src/quick/util/qquickutilmodule.cpp
index 4d156a2d9a..0af2343504 100644
--- a/src/quick/util/qquickutilmodule.cpp
+++ b/src/quick/util/qquickutilmodule.cpp
@@ -49,6 +49,7 @@
#include "qquicktransition_p.h"
#include "qquickanimator_p.h"
#include "qquickshortcut_p.h"
+#include "qquickvalidator_p.h"
#include <qqmlinfo.h>
#include <private/qqmltypenotavailable_p.h>
#include <private/qquickanimationcontroller_p.h>
@@ -87,6 +88,13 @@ void QQuickUtilModule::defineModule()
qmlRegisterType<QQuickTransition>("QtQuick",2,0,"Transition");
qmlRegisterType<QQuickVector3dAnimation>("QtQuick",2,0,"Vector3dAnimation");
+#ifndef QT_NO_VALIDATOR
+ qmlRegisterType<QValidator>();
+ qmlRegisterType<QQuickIntValidator>("QtQuick",2,0,"IntValidator");
+ qmlRegisterType<QQuickDoubleValidator>("QtQuick",2,0,"DoubleValidator");
+ qmlRegisterType<QRegExpValidator>("QtQuick",2,0,"RegExpValidator");
+#endif
+
qmlRegisterUncreatableType<QQuickAnimator>("QtQuick", 2, 2, "Animator", QQuickAbstractAnimation::tr("Animator is an abstract class"));
qmlRegisterType<QQuickXAnimator>("QtQuick", 2, 2, "XAnimator");
qmlRegisterType<QQuickYAnimator>("QtQuick", 2, 2, "YAnimator");
@@ -106,4 +114,6 @@ void QQuickUtilModule::defineModule()
qmlRegisterType<QQuickTextMetrics>("QtQuick", 2, 4, "TextMetrics");
qmlRegisterType<QQuickShortcut>("QtQuick", 2, 5, "Shortcut");
+
+ qmlRegisterType<QQuickShortcut,1>("QtQuick", 2, 6, "Shortcut");
}
diff --git a/src/quick/util/qquickutilmodule_p.h b/src/quick/util/qquickutilmodule_p.h
index 77d0e7dd3b..c2e80d22ce 100644
--- a/src/quick/util/qquickutilmodule_p.h
+++ b/src/quick/util/qquickutilmodule_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKUTILMODULE_H
#define QQUICKUTILMODULE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick/util/qquickvalidator.cpp b/src/quick/util/qquickvalidator.cpp
new file mode 100644
index 0000000000..3eebf5d77a
--- /dev/null
+++ b/src/quick/util/qquickvalidator.cpp
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickvalidator_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_VALIDATOR
+
+/*!
+ \qmltype IntValidator
+ \instantiates QIntValidator
+ \inqmlmodule QtQuick
+ \ingroup qtquick-text-utility
+ \brief Defines a validator for integer values
+
+ The IntValidator type provides a validator for integer values.
+
+ If no \l locale is set IntValidator uses the \l {QLocale::setDefault()}{default locale} to
+ interpret the number and will accept locale specific digits, group separators, and positive
+ and negative signs. In addition, IntValidator is always guaranteed to accept a number
+ formatted according to the "C" locale.
+*/
+
+QQuickIntValidator::QQuickIntValidator(QObject *parent)
+ : QIntValidator(parent)
+{
+}
+
+/*!
+ \qmlproperty string QtQuick::IntValidator::locale
+
+ This property holds the name of the locale used to interpret the number.
+
+ \sa {QtQml::Qt::locale()}{Qt.locale()}
+*/
+
+QString QQuickIntValidator::localeName() const
+{
+ return locale().name();
+}
+
+void QQuickIntValidator::setLocaleName(const QString &name)
+{
+ if (locale().name() != name) {
+ setLocale(QLocale(name));
+ emit localeNameChanged();
+ }
+}
+
+void QQuickIntValidator::resetLocaleName()
+{
+ QLocale defaultLocale;
+ if (locale() != defaultLocale) {
+ setLocale(defaultLocale);
+ emit localeNameChanged();
+ }
+}
+
+/*!
+ \qmlproperty int QtQuick::IntValidator::top
+
+ This property holds the validator's highest acceptable value.
+ By default, this property's value is derived from the highest signed integer available (typically 2147483647).
+*/
+/*!
+ \qmlproperty int QtQuick::IntValidator::bottom
+
+ This property holds the validator's lowest acceptable value.
+ By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
+*/
+
+/*!
+ \qmltype DoubleValidator
+ \instantiates QDoubleValidator
+ \inqmlmodule QtQuick
+ \ingroup qtquick-text-utility
+ \brief Defines a validator for non-integer numbers
+
+ The DoubleValidator type provides a validator for non-integer numbers.
+
+ Input is accepted if it contains a double that is within the valid range
+ and is in the correct format.
+
+ Input is accepected but invalid if it contains a double that is outside
+ the range or is in the wrong format; e.g. with too many digits after the
+ decimal point or is empty.
+
+ Input is rejected if it is not a double.
+
+ Note: If the valid range consists of just positive doubles (e.g. 0.0 to
+ 100.0) and input is a negative double then it is rejected. If \l notation
+ is set to DoubleValidator.StandardNotation, and the input contains more
+ digits before the decimal point than a double in the valid range may have,
+ it is also rejected. If \l notation is DoubleValidator.ScientificNotation,
+ and the input is not in the valid range, it is accecpted but invalid. The
+ value may yet become valid by changing the exponent.
+*/
+
+QQuickDoubleValidator::QQuickDoubleValidator(QObject *parent)
+ : QDoubleValidator(parent)
+{
+}
+
+/*!
+ \qmlproperty string QtQuick::DoubleValidator::locale
+
+ This property holds the name of the locale used to interpret the number.
+
+ \sa {QtQml::Qt::locale()}{Qt.locale()}
+*/
+
+QString QQuickDoubleValidator::localeName() const
+{
+ return locale().name();
+}
+
+void QQuickDoubleValidator::setLocaleName(const QString &name)
+{
+ if (locale().name() != name) {
+ setLocale(QLocale(name));
+ emit localeNameChanged();
+ }
+}
+
+void QQuickDoubleValidator::resetLocaleName()
+{
+ QLocale defaultLocale;
+ if (locale() != defaultLocale) {
+ setLocale(defaultLocale);
+ emit localeNameChanged();
+ }
+}
+
+/*!
+ \qmlproperty real QtQuick::DoubleValidator::top
+
+ This property holds the validator's maximum acceptable value.
+ By default, this property contains a value of infinity.
+*/
+/*!
+ \qmlproperty real QtQuick::DoubleValidator::bottom
+
+ This property holds the validator's minimum acceptable value.
+ By default, this property contains a value of -infinity.
+*/
+/*!
+ \qmlproperty int QtQuick::DoubleValidator::decimals
+
+ This property holds the validator's maximum number of digits after the decimal point.
+ By default, this property contains a value of 1000.
+*/
+/*!
+ \qmlproperty enumeration QtQuick::DoubleValidator::notation
+ This property holds the notation of how a string can describe a number.
+
+ The possible values for this property are:
+
+ \list
+ \li DoubleValidator.StandardNotation
+ \li DoubleValidator.ScientificNotation (default)
+ \endlist
+
+ If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
+*/
+
+/*!
+ \qmltype RegExpValidator
+ \instantiates QRegExpValidator
+ \inqmlmodule QtQuick
+ \ingroup qtquick-text-utility
+ \brief Provides a string validator
+
+ The RegExpValidator type provides a validator, which counts as valid any string which
+ matches a specified regular expression.
+*/
+/*!
+ \qmlproperty regExp QtQuick::RegExpValidator::regExp
+
+ This property holds the regular expression used for validation.
+
+ Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
+ matching "a".
+
+ By default, this property contains a regular expression with the pattern .* that matches any string.
+*/
+
+#endif // QT_NO_VALIDATOR
+
+QT_END_NAMESPACE
+
diff --git a/src/qml/debugger/qqmlinspectorservice_p.h b/src/quick/util/qquickvalidator_p.h
index f49c36aacb..da071ef2f5 100644
--- a/src/qml/debugger/qqmlinspectorservice_p.h
+++ b/src/quick/util/qquickvalidator_p.h
@@ -3,7 +3,7 @@
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
@@ -31,8 +31,8 @@
**
****************************************************************************/
-#ifndef QQMLINSPECTORSERVICE_H
-#define QQMLINSPECTORSERVICE_H
+#ifndef QQUICKVALIDATOR_P_H
+#define QQUICKVALIDATOR_P_H
//
// W A R N I N G
@@ -45,45 +45,50 @@
// We mean it.
//
-#include "qqmldebugservice_p.h"
-
-#include <QtQml/qtqmlglobal.h>
-#include <QtCore/QList>
+#include <QtGui/qvalidator.h>
+#include <QtQml/qqml.h>
QT_BEGIN_NAMESPACE
-
-class QQmlInspectorInterface;
-
-class Q_QML_PRIVATE_EXPORT QQmlInspectorService : public QQmlDebugService
+#ifndef QT_NO_VALIDATOR
+class Q_AUTOTEST_EXPORT QQuickIntValidator : public QIntValidator
{
Q_OBJECT
-
+ Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged)
public:
- QQmlInspectorService();
- static QQmlInspectorService *instance();
-
- void addView(QObject *);
- void removeView(QObject *);
+ QQuickIntValidator(QObject *parent = 0);
- void sendMessage(const QByteArray &message);
+ QString localeName() const;
+ void setLocaleName(const QString &name);
+ void resetLocaleName();
-protected:
- virtual void stateChanged(State state);
- virtual void messageReceived(const QByteArray &);
+Q_SIGNALS:
+ void localeNameChanged();
+};
-private Q_SLOTS:
- void processMessage(const QByteArray &message);
- void updateState();
+class Q_AUTOTEST_EXPORT QQuickDoubleValidator : public QDoubleValidator
+{
+ Q_OBJECT
+ Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged)
+public:
+ QQuickDoubleValidator(QObject *parent = 0);
-private:
- void loadInspectorPlugins();
+ QString localeName() const;
+ void setLocaleName(const QString &name);
+ void resetLocaleName();
- QList<QObject*> m_views;
- QQmlInspectorInterface *m_currentInspectorPlugin;
- QList<QQmlInspectorInterface*> m_inspectorPlugins;
+Q_SIGNALS:
+ void localeNameChanged();
};
+#endif
QT_END_NAMESPACE
-#endif // QQMLINSPECTORSERVICE_H
+#ifndef QT_NO_VALIDATOR
+QML_DECLARE_TYPE(QValidator)
+QML_DECLARE_TYPE(QQuickIntValidator)
+QML_DECLARE_TYPE(QQuickDoubleValidator)
+QML_DECLARE_TYPE(QRegExpValidator)
+#endif
+
+#endif // QQUICKVALIDATOR_P_H
diff --git a/src/quick/util/qquickvaluetypes.cpp b/src/quick/util/qquickvaluetypes.cpp
index fef6dfd1d0..1f0d54e4e7 100644
--- a/src/quick/util/qquickvaluetypes.cpp
+++ b/src/quick/util/qquickvaluetypes.cpp
@@ -533,6 +533,16 @@ void QQuickFontValueType::setFamily(const QString &family)
v.setFamily(family);
}
+QString QQuickFontValueType::styleName() const
+{
+ return v.styleName();
+}
+
+void QQuickFontValueType::setStyleName(const QString &style)
+{
+ v.setStyleName(style);
+}
+
bool QQuickFontValueType::bold() const
{
return v.bold();
diff --git a/src/quick/util/qquickvaluetypes_p.h b/src/quick/util/qquickvaluetypes_p.h
index f62306ed01..4c2b488660 100644
--- a/src/quick/util/qquickvaluetypes_p.h
+++ b/src/quick/util/qquickvaluetypes_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKVALUETYPES_P_H
#define QQUICKVALUETYPES_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qqml.h>
#include <qtquickglobal.h>
#include <private/qqmlvaluetype_p.h>
@@ -244,6 +255,13 @@ public:
void setM43(qreal value) { v(3, 2) = value; }
void setM44(qreal value) { v(3, 3) = value; }
+ Q_INVOKABLE void translate(const QVector3D &t) { v.translate(t); }
+ Q_INVOKABLE void rotate(float angle, const QVector3D &axis) { v.rotate(angle, axis); }
+ Q_INVOKABLE void scale(float s) { v.scale(s); }
+ Q_INVOKABLE void scale(float sx, float sy, float sz) { v.scale(sx, sy, sz); }
+ Q_INVOKABLE void scale(const QVector3D &s) { v.scale(s); }
+ Q_INVOKABLE void lookAt(const QVector3D &eye, const QVector3D &center, const QVector3D &up) { v.lookAt(eye, center, up); }
+
Q_INVOKABLE QMatrix4x4 times(const QMatrix4x4 &m) const;
Q_INVOKABLE QVector4D times(const QVector4D &vec) const;
Q_INVOKABLE QVector3D times(const QVector3D &vec) const;
@@ -266,10 +284,9 @@ class QQuickFontValueType
{
QFont v;
Q_GADGET
- Q_ENUMS(FontWeight)
- Q_ENUMS(Capitalization)
Q_PROPERTY(QString family READ family WRITE setFamily FINAL)
+ Q_PROPERTY(QString styleName READ styleName WRITE setStyleName FINAL)
Q_PROPERTY(bool bold READ bold WRITE setBold FINAL)
Q_PROPERTY(FontWeight weight READ weight WRITE setWeight FINAL)
Q_PROPERTY(bool italic READ italic WRITE setItalic FINAL)
@@ -292,17 +309,22 @@ public:
Bold = QFont::Bold,
ExtraBold = QFont::ExtraBold,
Black = QFont::Black };
+ Q_ENUM(FontWeight)
enum Capitalization { MixedCase = QFont::MixedCase,
AllUppercase = QFont::AllUppercase,
AllLowercase = QFont::AllLowercase,
SmallCaps = QFont::SmallCaps,
Capitalize = QFont::Capitalize };
+ Q_ENUM(Capitalization)
Q_INVOKABLE QString toString() const;
QString family() const;
void setFamily(const QString &);
+ QString styleName() const;
+ void setStyleName(const QString &);
+
bool bold() const;
void setBold(bool b);
diff --git a/src/quick/util/util.pri b/src/quick/util/util.pri
index 0e0df4e751..ffb31ae75e 100644
--- a/src/quick/util/util.pri
+++ b/src/quick/util/util.pri
@@ -29,7 +29,8 @@ SOURCES += \
$$PWD/qquickprofiler.cpp \
$$PWD/qquickfontmetrics.cpp \
$$PWD/qquicktextmetrics.cpp \
- $$PWD/qquickshortcut.cpp
+ $$PWD/qquickshortcut.cpp \
+ $$PWD/qquickvalidator.cpp
HEADERS += \
$$PWD/qquickapplication_p.h\
@@ -66,4 +67,5 @@ HEADERS += \
$$PWD/qquickprofiler_p.h \
$$PWD/qquickfontmetrics_p.h \
$$PWD/qquicktextmetrics_p.h \
- $$PWD/qquickshortcut_p.h
+ $$PWD/qquickshortcut_p.h \
+ $$PWD/qquickvalidator_p.h
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index 620d169eb4..2120be768c 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -39,8 +39,9 @@
#include "private/qquickitemchangelistener_p.h"
#include "private/qquickrendercontrol_p.h"
+#include <private/qqmldebugconnector_p.h>
#include <private/qquickprofiler_p.h>
-#include <private/qqmlinspectorservice_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
#include <private/qqmlmemoryprofiler_p.h>
#include <QtQml/qqmlengine.h>
@@ -95,8 +96,9 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
if (!engine.data()->incubationController())
engine.data()->setIncubationController(offscreenWindow->incubationController());
- if (QQmlDebugService::isDebuggingEnabled())
- QQmlInspectorService::instance()->addView(q);
+ QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>();
+ if (service)
+ service->addView(q);
#ifndef QT_NO_DRAGANDDROP
q->setAcceptDrops(true);
@@ -142,13 +144,15 @@ QQuickWidgetPrivate::QQuickWidgetPrivate()
, eventPending(false)
, updatePending(false)
, fakeHidden(false)
+ , requestedSamples(0)
{
}
QQuickWidgetPrivate::~QQuickWidgetPrivate()
{
- if (QQmlDebugService::isDebuggingEnabled())
- QQmlInspectorService::instance()->removeView(q_func());
+ QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>();
+ if (service)
+ service->removeView(q_func());
invalidateRenderControl();
@@ -202,6 +206,11 @@ void QQuickWidgetPrivate::itemGeometryChanged(QQuickItem *resizeItem, const QRec
void QQuickWidgetPrivate::render(bool needsSync)
{
+ // createFramebufferObject() bails out when the size is empty. In this case
+ // we cannot render either.
+ if (!fbo)
+ return;
+
Q_ASSERT(context);
if (!context->makeCurrent(offscreenSurface)) {
@@ -243,8 +252,15 @@ void QQuickWidgetPrivate::renderSceneGraph()
}
Q_ASSERT(offscreenSurface);
+
render(true);
- q->update(); // schedule composition
+
+#ifndef QT_NO_GRAPHICSVIEW
+ if (q->window()->graphicsProxyWidget())
+ QWidgetPrivate::nearestGraphicsProxyWidget(q)->update();
+ else
+#endif
+ q->update(); // schedule composition
}
QImage QQuickWidgetPrivate::grabFramebuffer()
@@ -338,8 +354,8 @@ QObject *QQuickWidgetPrivate::focusObject()
This limitation only applies when there are other widgets underneath the QQuickWidget
inside the same window. Making the window semi-transparent, with other applications
and the desktop visible in the background, is done in the traditional way: Set
- Qt::WA_TranslucentBackground and change the Qt Quick Scenegraph's clear color to
- Qt::transparent via setClearColor().
+ Qt::WA_TranslucentBackground on the top-level window, request an alpha channel, and
+ change the Qt Quick Scenegraph's clear color to Qt::transparent via setClearColor().
\sa {Exposing Attributes of C++ Types to QML}, {Qt Quick Widgets Example}, QQuickView
*/
@@ -540,6 +556,9 @@ QQuickWidget::Status QQuickWidget::status() const
if (!d->component)
return QQuickWidget::Null;
+ if (d->component->status() == QQmlComponent::Ready && !d->root)
+ return QQuickWidget::Error;
+
return QQuickWidget::Status(d->component->status());
}
@@ -561,6 +580,10 @@ QList<QQmlError> QQuickWidget::errors() const
QQmlError error;
error.setDescription(QLatin1String("QQuickWidget: invalid qml engine."));
errs << error;
+ } else if (d->component && d->component->status() == QQmlComponent::Ready && !d->root) {
+ QQmlError error;
+ error.setDescription(QLatin1String("QQuickWidget: invalid root object."));
+ errs << error;
}
return errs;
@@ -689,6 +712,7 @@ void QQuickWidgetPrivate::handleContextCreationFailure(const QSurfaceFormat &for
void QQuickWidgetPrivate::createContext()
{
+ Q_Q(QQuickWidget);
// On hide-show we invalidate() but our context is kept.
// We nonetheless need to initialize() again.
const bool reinit = context && !offscreenWindow->openglContext();
@@ -700,11 +724,13 @@ void QQuickWidgetPrivate::createContext()
context = new QOpenGLContext;
context->setFormat(offscreenWindow->requestedFormat());
- if (qt_gl_global_share_context()) {
- context->setShareContext(qt_gl_global_share_context());
- context->setScreen(context->shareContext()->screen());
+ QOpenGLContext *shareContext = qt_gl_global_share_context();
+ if (!shareContext)
+ shareContext = QWidgetPrivate::get(q->window())->shareContext();
+ if (shareContext) {
+ context->setShareContext(shareContext);
+ context->setScreen(shareContext->screen());
}
-
if (!context->create()) {
const bool isEs = context->isOpenGLES();
delete context;
@@ -766,7 +792,7 @@ void QQuickWidget::createFramebufferObject()
context->makeCurrent(d->offscreenSurface);
- int samples = d->offscreenWindow->requestedFormat().samples();
+ int samples = d->requestedSamples;
if (!QOpenGLExtensions(context).hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample))
samples = 0;
@@ -880,14 +906,15 @@ void QQuickWidgetPrivate::setRootObject(QObject *obj)
if (QQuickItem *sgItem = qobject_cast<QQuickItem *>(obj)) {
root = sgItem;
sgItem->setParentItem(offscreenWindow->contentItem());
+ } else if (qobject_cast<QWindow *>(obj)) {
+ qWarning() << "QQuickWidget does not support using windows as a root item." << endl
+ << endl
+ << "If you wish to create your root window from QML, consider using QQmlApplicationEngine instead." << endl;
} else {
qWarning() << "QQuickWidget only supports loading of root objects that derive from QQuickItem." << endl
<< endl
- << "If your example is using QML 2, (such as qmlscene) and the .qml file you" << endl
- << "loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur." << endl
- << endl
- << "To load files with 'import QtQuick 1.0' or 'import Qt 4.7', use the" << endl
- << "QDeclarativeView class in the Qt Quick 1 module." << endl;
+ << "Ensure your QML code is written for QtQuick 2, and uses a root that is or" << endl
+ << "inherits from QtQuick's Item (not a Timer, QtObject, etc)." << endl;
delete obj;
root = 0;
}
@@ -1078,6 +1105,12 @@ void QQuickWidget::showEvent(QShowEvent *)
d->render(true);
else
triggerUpdate();
+ QWindowPrivate *offscreenPrivate = QWindowPrivate::get(d->offscreenWindow);
+ if (!offscreenPrivate->visible) {
+ offscreenPrivate->visible = true;
+ emit d->offscreenWindow->visibleChanged(true);
+ offscreenPrivate->updateVisibility();
+ }
}
/*! \reimp */
@@ -1085,6 +1118,12 @@ void QQuickWidget::hideEvent(QHideEvent *)
{
Q_D(QQuickWidget);
d->invalidateRenderControl();
+ QWindowPrivate *offscreenPrivate = QWindowPrivate::get(d->offscreenWindow);
+ if (offscreenPrivate->visible) {
+ offscreenPrivate->visible = false;
+ emit d->offscreenWindow->visibleChanged(false);
+ offscreenPrivate->updateVisibility();
+ }
}
/*! \reimp */
@@ -1139,6 +1178,20 @@ void QQuickWidget::focusOutEvent(QFocusEvent * event)
d->offscreenWindow->focusOutEvent(event);
}
+static Qt::WindowState resolveWindowState(Qt::WindowStates states)
+{
+ // No more than one of these 3 can be set
+ if (states & Qt::WindowMinimized)
+ return Qt::WindowMinimized;
+ if (states & Qt::WindowMaximized)
+ return Qt::WindowMaximized;
+ if (states & Qt::WindowFullScreen)
+ return Qt::WindowFullScreen;
+
+ // No state means "windowed" - we ignore Qt::WindowActive
+ return Qt::WindowNoState;
+}
+
/*! \reimp */
bool QQuickWidget::event(QEvent *e)
{
@@ -1168,10 +1221,15 @@ bool QQuickWidget::event(QEvent *e)
}
break;
+ case QEvent::Show:
case QEvent::Move:
d->updatePosition();
break;
+ case QEvent::WindowStateChange:
+ d->offscreenWindow->setWindowState(resolveWindowState(windowState()));
+ break;
+
default:
break;
}
@@ -1249,6 +1307,14 @@ void QQuickWidget::setFormat(const QSurfaceFormat &format)
newFormat.setDepthBufferSize(qMax(newFormat.depthBufferSize(), currentFormat.depthBufferSize()));
newFormat.setStencilBufferSize(qMax(newFormat.stencilBufferSize(), currentFormat.stencilBufferSize()));
newFormat.setAlphaBufferSize(qMax(newFormat.alphaBufferSize(), currentFormat.alphaBufferSize()));
+
+ // Do not include the sample count. Requesting a multisampled context is not necessary
+ // since we render into an FBO, never to an actual surface. What's more, attempting to
+ // create a pbuffer with a multisampled config crashes certain implementations. Just
+ // avoid the entire hassle, the result is the same.
+ d->requestedSamples = newFormat.samples();
+ newFormat.setSamples(0);
+
d->offscreenWindow->setFormat(newFormat);
}
@@ -1278,9 +1344,10 @@ QImage QQuickWidget::grabFramebuffer() const
/*!
Sets the clear \a color. By default this is an opaque color.
- To get a semi- or fully transparent QQuickWidget, call this function with \a
- color set to Qt::transparent and set the Qt::WA_TranslucentBackground widget
- attribute.
+ To get a semi-transparent QQuickWidget, call this function with
+ \a color set to Qt::transparent, set the Qt::WA_TranslucentBackground
+ widget attribute on the top-level window, and request an alpha
+ channel via setFormat().
\sa QQuickWindow::setColor()
*/
diff --git a/src/quickwidgets/qquickwidget.h b/src/quickwidgets/qquickwidget.h
index a8bf03edfb..5bb6b49a49 100644
--- a/src/quickwidgets/qquickwidget.h
+++ b/src/quickwidgets/qquickwidget.h
@@ -56,7 +56,6 @@ class Q_QUICKWIDGETS_EXPORT QQuickWidget : public QWidget
Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(QUrl source READ source WRITE setSource DESIGNABLE true)
- Q_ENUMS(ResizeMode Status)
public:
explicit QQuickWidget(QWidget *parent = 0);
@@ -72,10 +71,12 @@ public:
QQuickItem *rootObject() const;
enum ResizeMode { SizeViewToRootObject, SizeRootObjectToView };
+ Q_ENUM(ResizeMode)
ResizeMode resizeMode() const;
void setResizeMode(ResizeMode);
enum Status { Null, Ready, Loading, Error };
+ Q_ENUM(Status)
Status status() const;
QList<QQmlError> errors() const;
diff --git a/src/quickwidgets/qquickwidget_p.h b/src/quickwidgets/qquickwidget_p.h
index e8d1f714f3..46f6ac5d8a 100644
--- a/src/quickwidgets/qquickwidget_p.h
+++ b/src/quickwidgets/qquickwidget_p.h
@@ -34,6 +34,17 @@
#ifndef QQUICKWIDGET_P_H
#define QQUICKWIDGET_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qquickwidget.h"
#include <private/qwidget_p.h>
@@ -115,6 +126,8 @@ public:
bool eventPending;
bool updatePending;
bool fakeHidden;
+
+ int requestedSamples;
};
QT_END_NAMESPACE