aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.cpp2
-rw-r--r--examples/quick/demos/demos.pro3
-rw-r--r--examples/quick/demos/photoviewer/deployment.pri19
-rw-r--r--examples/quick/demos/photoviewer/photoviewer.pro7
-rw-r--r--examples/quick/scenegraph/rendernode/d3d12renderer.cpp10
-rw-r--r--examples/quick/scenegraph/rendernode/d3d12renderer.h2
-rw-r--r--examples/quick/scenegraph/rendernode/openglrenderer.cpp10
-rw-r--r--examples/quick/scenegraph/rendernode/openglrenderer.h6
-rw-r--r--examples/quick/scenegraph/rendernode/softwarerenderer.cpp12
-rw-r--r--examples/quick/scenegraph/rendernode/softwarerenderer.h2
-rw-r--r--examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc4
-rw-r--r--src/imports/localstorage/plugin.cpp5
-rw-r--r--src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp18
-rw-r--r--src/plugins/qmltooling/packetprotocol/qpacketprotocol_p.h2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp10
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h10
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp5
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp4
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h5
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h1
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp4
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp9
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/globalinspector.h4
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/highlight.cpp26
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/highlight.h7
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp14
-rw-r--r--src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp7
-rw-r--r--src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.h4
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp29
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h1
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp14
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h4
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp39
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h13
-rw-r--r--src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp28
-rw-r--r--src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h2
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp76
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp7
-rw-r--r--src/plugins/qmltooling/shared/qqmldebugserver.h2
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp2
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12engine_p_p.h2
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp1
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp18
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h2
-rw-r--r--src/qml/compiler/qqmlpropertyvalidator.cpp22
-rw-r--r--src/qml/compiler/qqmlpropertyvalidator_p.h2
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp8
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h12
-rw-r--r--src/qml/compiler/qv4codegen.cpp116
-rw-r--r--src/qml/compiler/qv4compileddata.cpp94
-rw-r--r--src/qml/compiler/qv4compileddata_p.h86
-rw-r--r--src/qml/compiler/qv4compiler.cpp21
-rw-r--r--src/qml/compiler/qv4compiler_p.h3
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h17
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp37
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h11
-rw-r--r--src/qml/compiler/qv4isel_p.cpp3
-rw-r--r--src/qml/compiler/qv4isel_p.h6
-rw-r--r--src/qml/compiler/qv4jsir_p.h8
-rw-r--r--src/qml/debugger/debugger.pri27
-rw-r--r--src/qml/debugger/qqmlabstractprofileradapter_p.h4
-rw-r--r--src/qml/debugger/qqmldebug.cpp17
-rw-r--r--src/qml/debugger/qqmldebug.h3
-rw-r--r--src/qml/debugger/qqmldebugconnector_p.h25
-rw-r--r--src/qml/debugger/qqmldebugservice.cpp33
-rw-r--r--src/qml/debugger/qqmldebugservice_p.h20
-rw-r--r--src/qml/debugger/qqmldebugserviceinterfaces_p.h57
-rw-r--r--src/qml/debugger/qqmldebugstatesdelegate_p.h7
-rw-r--r--src/qml/debugger/qqmlmemoryprofiler.cpp (renamed from src/qml/qml/qqmlmemoryprofiler.cpp)0
-rw-r--r--src/qml/debugger/qqmlmemoryprofiler_p.h (renamed from src/qml/qml/qqmlmemoryprofiler_p.h)9
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h59
-rw-r--r--src/qml/debugger/qqmlprofilerdefinitions_p.h4
-rw-r--r--src/qml/doc/src/cppintegration/data.qdoc2
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc2
-rw-r--r--src/qml/jit/qv4assembler.cpp16
-rw-r--r--src/qml/jit/qv4assembler_p.h27
-rw-r--r--src/qml/jit/qv4binop.cpp8
-rw-r--r--src/qml/jit/qv4isel_masm.cpp47
-rw-r--r--src/qml/jit/qv4isel_masm_p.h12
-rw-r--r--src/qml/jsruntime/jsruntime.pri4
-rw-r--r--src/qml/jsruntime/qv4context.cpp4
-rw-r--r--src/qml/jsruntime/qv4context_p.h8
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp60
-rw-r--r--src/qml/jsruntime/qv4debugging_p.h15
-rw-r--r--src/qml/jsruntime/qv4engine.cpp34
-rw-r--r--src/qml/jsruntime/qv4engine_p.h21
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp8
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h62
-rw-r--r--src/qml/jsruntime/qv4script.cpp3
-rw-r--r--src/qml/jsruntime/qv4script_p.h4
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4value_p.h4
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp10
-rw-r--r--src/qml/memory/qv4mm.cpp24
-rw-r--r--src/qml/qml.pro2
-rw-r--r--src/qml/qml/qml.pri2
-rw-r--r--src/qml/qml/qqmlabstractbinding_p.h2
-rw-r--r--src/qml/qml/qqmlbinding.cpp120
-rw-r--r--src/qml/qml/qqmlbinding_p.h10
-rw-r--r--src/qml/qml/qqmlcomponent.cpp14
-rw-r--r--src/qml/qml/qqmlengine.cpp19
-rw-r--r--src/qml/qml/qqmlengine_p.h6
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp183
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h3
-rw-r--r--src/qml/qml/qqmlopenmetaobject.cpp2
-rw-r--r--src/qml/qml/qqmlproperty.cpp189
-rw-r--r--src/qml/qml/qqmlproperty_p.h18
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp209
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h44
-rw-r--r--src/qml/qml/qqmltypeloader.cpp115
-rw-r--r--src/qml/qml/qqmltypeloader_p.h9
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp2
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h2
-rw-r--r--src/qml/qml/qqmlvaluetypeproxybinding.cpp2
-rw-r--r--src/qml/qml/qqmlvaluetypeproxybinding_p.h2
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp6
-rw-r--r--src/qmldebug/qqmldebugconnection.cpp60
-rw-r--r--src/qmldebug/qqmldebugconnection_p.h2
-rw-r--r--src/qmldebug/qqmlprofilerclient_p.h2
-rw-r--r--src/qmltest/qmltest.pro2
-rw-r--r--src/quick/designer/qquickdesignercustomobjectdata.cpp4
-rw-r--r--src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc105
-rw-r--r--src/quick/doc/src/qmltypereference.qdoc13
-rw-r--r--src/quick/items/qquickclipnode.cpp2
-rw-r--r--src/quick/items/qquickevents_p_p.h8
-rw-r--r--src/quick/items/qquickflickable.cpp4
-rw-r--r--src/quick/items/qquickitem.cpp3
-rw-r--r--src/quick/items/qquickitemanimation.cpp42
-rw-r--r--src/quick/items/qquicktextedit.cpp4
-rw-r--r--src/quick/items/qquickview.cpp3
-rw-r--r--src/quick/items/qquickwindow.cpp39
-rw-r--r--src/quick/items/qquickwindow_p.h6
-rw-r--r--src/quick/qtquick2.cpp8
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwareadaptation.cpp11
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp18
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp3
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp991
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop_p.h118
-rw-r--r--src/quick/scenegraph/adaptations/software/software.pri6
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp8
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendernode.cpp67
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendernode.h10
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp2
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp4
-rw-r--r--src/quick/util/qquickanimation.cpp6
-rw-r--r--src/quick/util/qquickbehavior.cpp6
-rw-r--r--src/quick/util/qquickprofiler.cpp9
-rw-r--r--src/quick/util/qquickprofiler_p.h104
-rw-r--r--src/quick/util/qquickpropertychanges.cpp12
-rw-r--r--src/quick/util/qquicksmoothedanimation.cpp12
-rw-r--r--src/quick/util/qquickspringanimation.cpp4
-rw-r--r--src/quick/util/qquicktransitionmanager.cpp6
-rw-r--r--src/quick/util/qquickvaluetypes.cpp72
-rw-r--r--src/quick/util/qquickvaluetypes_p.h18
-rw-r--r--src/quick/util/util.pri3
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp7
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp18
-rw-r--r--tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp4
-rw-r--r--tests/auto/qml/debugger/shared/debugutil_p.h2
-rw-r--r--tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp121
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qtbug_54589.qml16
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp18
-rw-r--r--tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h24
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp1
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp6
-rw-r--r--tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp199
-rw-r--r--tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp35
-rw-r--r--tests/auto/qml/qqmlvaluetypes/data/color_read.qml6
-rw-r--r--tests/auto/qml/qqmlvaluetypes/data/color_write_HSL.qml8
-rw-r--r--tests/auto/qml/qqmlvaluetypes/data/color_write_HSV.qml8
-rw-r--r--tests/auto/qml/qqmlvaluetypes/testtypes.h6
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp33
-rw-r--r--tests/auto/quick/qquickflickable/data/ratios_smallContent.qml19
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp28
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp24
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp6
-rw-r--r--tests/auto/quick/qquickshadereffect/data/MyIcon.qml76
-rw-r--r--tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml61
-rw-r--r--tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp14
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp85
-rw-r--r--tests/benchmarks/qml/qml.pro1
-rw-r--r--tests/benchmarks/qml/qqmlchangeset/qqmlchangeset.pro10
-rw-r--r--tests/benchmarks/qml/qqmlchangeset/tst_qqmlchangeset.cpp60
-rw-r--r--tests/manual/scenegraph_lancelot/scenegrabber/main.cpp2
m---------tests/manual/v4/test2620
-rw-r--r--tools/qml/qml.pro2
-rw-r--r--tools/qmlplugindump/qmlplugindump.pro2
-rw-r--r--tools/qmlprofiler/commandlistener.h2
-rw-r--r--tools/qmlprofiler/main.cpp6
-rw-r--r--tools/qmlprofiler/qmlprofilerapplication.cpp28
-rw-r--r--tools/qmlprofiler/qmlprofilerapplication.h11
-rw-r--r--tools/qmlprofiler/qmlprofilerdata.h11
-rw-r--r--tools/qmlscene/qmlscene.pro3
197 files changed, 4079 insertions, 1192 deletions
diff --git a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp
index 965e5152c1..d963b6d1b4 100644
--- a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp
@@ -41,7 +41,7 @@
#include "pieslice.h"
PieChart::PieChart(QQuickItem *parent)
- : QQuickItem(parent)
+ : QQuickItem(parent), m_pieSlice(0)
{
}
diff --git a/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.cpp b/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.cpp
index ceb0041ec8..50c018e33e 100644
--- a/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.cpp
@@ -42,7 +42,7 @@
#include <QPainter>
PieSlice::PieSlice(QQuickItem *parent)
- : QQuickPaintedItem(parent)
+ : QQuickPaintedItem(parent), m_fromAngle(0), m_angleSpan(0)
{
}
diff --git a/examples/quick/demos/demos.pro b/examples/quick/demos/demos.pro
index 9aac7bf6f7..e6937683ab 100644
--- a/examples/quick/demos/demos.pro
+++ b/examples/quick/demos/demos.pro
@@ -5,9 +5,8 @@ SUBDIRS = samegame \
tweetsearch \
maroon \
photosurface \
+ photoviewer \
stocqt
qtHaveModule(xmlpatterns): SUBDIRS += rssnews
-EXAMPLE_FILES = \
- photoviewer
diff --git a/examples/quick/demos/photoviewer/deployment.pri b/examples/quick/demos/photoviewer/deployment.pri
deleted file mode 100644
index 0d58a25c61..0000000000
--- a/examples/quick/demos/photoviewer/deployment.pri
+++ /dev/null
@@ -1,19 +0,0 @@
-android {
- x86 {
- target.path = /libs/x86
- } else: armeabi-v7a {
- target.path = /libs/armeabi-v7a
- } else {
- target.path = /libs/armeabi
- }
- export(target.path)
- INSTALLS += target
-} else:unix {
- isEmpty(target.path) {
- target.path = /opt/$${TARGET}/bin
- export(target.path)
- }
- INSTALLS += target
-}
-
-export(INSTALLS)
diff --git a/examples/quick/demos/photoviewer/photoviewer.pro b/examples/quick/demos/photoviewer/photoviewer.pro
index 704e2ce003..4bfdb86f31 100644
--- a/examples/quick/demos/photoviewer/photoviewer.pro
+++ b/examples/quick/demos/photoviewer/photoviewer.pro
@@ -15,8 +15,5 @@ TRANSLATIONS += i18n/qml_fr.ts \
RESOURCES += qml.qrc
-# Additional import path used to resolve QML modules in Qt Creator's code model
-QML_IMPORT_PATH =
-
-# Default rules for deployment.
-include(deployment.pri)
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/demos/photoviewer
+INSTALLS += target
diff --git a/examples/quick/scenegraph/rendernode/d3d12renderer.cpp b/examples/quick/scenegraph/rendernode/d3d12renderer.cpp
index f475ec838b..d35f82a76a 100644
--- a/examples/quick/scenegraph/rendernode/d3d12renderer.cpp
+++ b/examples/quick/scenegraph/rendernode/d3d12renderer.cpp
@@ -270,4 +270,14 @@ void D3D12RenderNode::render(const RenderState *state)
// No need to reimplement changedStates() because no relevant commands are
// added to the command list in render().
+QSGRenderNode::RenderingFlags D3D12RenderNode::flags() const
+{
+ return BoundedRectRendering | DepthAwareRendering;
+}
+
+QRectF D3D12RenderNode::rect() const
+{
+ return QRect(0, 0, m_item->width(), m_item->height());
+}
+
#endif // HAS_D3D12
diff --git a/examples/quick/scenegraph/rendernode/d3d12renderer.h b/examples/quick/scenegraph/rendernode/d3d12renderer.h
index a81db0f398..f13a1d451c 100644
--- a/examples/quick/scenegraph/rendernode/d3d12renderer.h
+++ b/examples/quick/scenegraph/rendernode/d3d12renderer.h
@@ -60,6 +60,8 @@ public:
void render(const RenderState *state) override;
void releaseResources() override;
+ RenderingFlags flags() const override;
+ QRectF rect() const override;
private:
void init();
diff --git a/examples/quick/scenegraph/rendernode/openglrenderer.cpp b/examples/quick/scenegraph/rendernode/openglrenderer.cpp
index 33c59198b8..3de864b7b9 100644
--- a/examples/quick/scenegraph/rendernode/openglrenderer.cpp
+++ b/examples/quick/scenegraph/rendernode/openglrenderer.cpp
@@ -151,4 +151,14 @@ QSGRenderNode::StateFlags OpenGLRenderNode::changedStates() const
return BlendState;
}
+QSGRenderNode::RenderingFlags OpenGLRenderNode::flags() const
+{
+ return BoundedRectRendering | DepthAwareRendering;
+}
+
+QRectF OpenGLRenderNode::rect() const
+{
+ return QRect(0, 0, m_item->width(), m_item->height());
+}
+
#endif // QT_NO_OPENGL
diff --git a/examples/quick/scenegraph/rendernode/openglrenderer.h b/examples/quick/scenegraph/rendernode/openglrenderer.h
index 28d528e617..92cc2bc72b 100644
--- a/examples/quick/scenegraph/rendernode/openglrenderer.h
+++ b/examples/quick/scenegraph/rendernode/openglrenderer.h
@@ -45,6 +45,8 @@
#ifndef QT_NO_OPENGL
+QT_BEGIN_NAMESPACE
+
class QQuickItem;
class QOpenGLShaderProgram;
class QOpenGLBuffer;
@@ -58,6 +60,8 @@ public:
void render(const RenderState *state) override;
void releaseResources() override;
StateFlags changedStates() const override;
+ RenderingFlags flags() const override;
+ QRectF rect() const override;
private:
void init();
@@ -69,6 +73,8 @@ private:
QOpenGLBuffer *m_vbo = nullptr;
};
+QT_END_NAMESPACE
+
#endif // QT_NO_OPENGL
#endif
diff --git a/examples/quick/scenegraph/rendernode/softwarerenderer.cpp b/examples/quick/scenegraph/rendernode/softwarerenderer.cpp
index 2f11c56f29..06e406874a 100644
--- a/examples/quick/scenegraph/rendernode/softwarerenderer.cpp
+++ b/examples/quick/scenegraph/rendernode/softwarerenderer.cpp
@@ -68,7 +68,7 @@ void SoftwareRenderNode::render(const RenderState *renderState)
p->setOpacity(inheritedOpacity());
const QRegion *clipRegion = renderState->clipRegion();
if (clipRegion && !clipRegion->isEmpty())
- p->setClipRegion(*clipRegion);
+ p->setClipRegion(*clipRegion, Qt::IntersectClip);
const QPointF p0(m_item->width() - 1, m_item->height() - 1);
const QPointF p1(0, 0);
@@ -89,3 +89,13 @@ QSGRenderNode::StateFlags SoftwareRenderNode::changedStates() const
{
return 0;
}
+
+QSGRenderNode::RenderingFlags SoftwareRenderNode::flags() const
+{
+ return BoundedRectRendering;
+}
+
+QRectF SoftwareRenderNode::rect() const
+{
+ return QRect(0, 0, m_item->width(), m_item->height());
+}
diff --git a/examples/quick/scenegraph/rendernode/softwarerenderer.h b/examples/quick/scenegraph/rendernode/softwarerenderer.h
index 60036f96a1..5b2a475ed8 100644
--- a/examples/quick/scenegraph/rendernode/softwarerenderer.h
+++ b/examples/quick/scenegraph/rendernode/softwarerenderer.h
@@ -54,6 +54,8 @@ public:
void render(const RenderState *state) override;
void releaseResources() override;
StateFlags changedStates() const override;
+ RenderingFlags flags() const override;
+ QRectF rect() const override;
private:
QQuickItem *m_item;
diff --git a/examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc b/examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc
index 278f154781..d6eb711929 100644
--- a/examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc
+++ b/examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc
@@ -102,8 +102,8 @@
state and we use it to update the shader program with the current
color. The previous state is passed in as a second parameter so
that the user can update only that which has changed. In our
- usecase, where all the colors are different, the updateState will
- be called once for every node.
+ use case, where all the colors are different, the updateState()
+ function will be called once for every node.
\snippet scenegraph/simplematerial/simplematerial.cpp 7
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp
index 7d96f11768..f59ccc551e 100644
--- a/src/imports/localstorage/plugin.cpp
+++ b/src/imports/localstorage/plugin.cpp
@@ -149,7 +149,12 @@ public:
using namespace QV4;
+QT_WARNING_PUSH
+#if (Q_CC_GNU >= 600)
+QT_WARNING_DISABLE_GCC("-Wtautological-compare")
+#endif
DEFINE_OBJECT_VTABLE(QV4::QQmlSqlDatabaseWrapper);
+QT_WARNING_POP
diff --git a/src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp b/src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp
index d20ddf9dc0..e541810330 100644
--- a/src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp
+++ b/src/plugins/qmltooling/packetprotocol/qpacketprotocol.cpp
@@ -124,12 +124,9 @@ QPacketProtocol::QPacketProtocol(QIODevice *dev, QObject *parent)
Q_ASSERT(4 == sizeof(qint32));
Q_ASSERT(dev);
- QObject::connect(dev, SIGNAL(readyRead()),
- this, SLOT(readyToRead()));
- QObject::connect(dev, SIGNAL(aboutToClose()),
- this, SLOT(aboutToClose()));
- QObject::connect(dev, SIGNAL(bytesWritten(qint64)),
- this, SLOT(bytesWritten(qint64)));
+ QObject::connect(dev, &QIODevice::readyRead, this, &QPacketProtocol::readyToRead);
+ QObject::connect(dev, &QIODevice::aboutToClose, this, &QPacketProtocol::aboutToClose);
+ QObject::connect(dev, &QIODevice::bytesWritten, this, &QPacketProtocol::bytesWritten);
}
/*!
@@ -247,12 +244,9 @@ void QPacketProtocol::readyToRead()
// Check sizing constraints
if (d->inProgressSize > MAX_PACKET_SIZE) {
- QObject::disconnect(d->dev, SIGNAL(readyRead()),
- this, SLOT(readyToRead()));
- QObject::disconnect(d->dev, SIGNAL(aboutToClose()),
- this, SLOT(aboutToClose()));
- QObject::disconnect(d->dev, SIGNAL(bytesWritten(qint64)),
- this, SLOT(bytesWritten(qint64)));
+ disconnect(d->dev, &QIODevice::readyRead, this, &QPacketProtocol::readyToRead);
+ disconnect(d->dev, &QIODevice::aboutToClose, this, &QPacketProtocol::aboutToClose);
+ disconnect(d->dev, &QIODevice::bytesWritten, this, &QPacketProtocol::bytesWritten);
d->dev = 0;
emit invalidPacket();
return;
diff --git a/src/plugins/qmltooling/packetprotocol/qpacketprotocol_p.h b/src/plugins/qmltooling/packetprotocol/qpacketprotocol_p.h
index 8f95a081e9..7fd722f17f 100644
--- a/src/plugins/qmltooling/packetprotocol/qpacketprotocol_p.h
+++ b/src/plugins/qmltooling/packetprotocol/qpacketprotocol_p.h
@@ -74,7 +74,7 @@ Q_SIGNALS:
void readyRead();
void invalidPacket();
-private Q_SLOTS:
+private:
void aboutToClose();
void bytesWritten(qint64 bytes);
void readyToRead();
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
index e49b15218e..12ed987ca0 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
@@ -63,8 +63,12 @@ QT_BEGIN_NAMESPACE
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)));
+ connect(m_watch, &QQmlWatcher::propertyChanged,
+ this, &QQmlEngineDebugServiceImpl::propertyChanged);
+
+ // Move the message into the correct thread for processing
+ connect(this, &QQmlEngineDebugServiceImpl::scheduleMessage,
+ this, &QQmlEngineDebugServiceImpl::processMessage, Qt::QueuedConnection);
}
QQmlEngineDebugServiceImpl::~QQmlEngineDebugServiceImpl()
@@ -420,7 +424,7 @@ QQmlEngineDebugServiceImpl::objectData(QObject *object)
void QQmlEngineDebugServiceImpl::messageReceived(const QByteArray &message)
{
- QMetaObject::invokeMethod(this, "processMessage", Qt::QueuedConnection, Q_ARG(QByteArray, message));
+ emit scheduleMessage(message);
}
/*!
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h
index cb75a63850..2e40eb4de8 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.h
@@ -101,16 +101,18 @@ public:
void setStatesDelegate(QQmlDebugStatesDelegate *) Q_DECL_OVERRIDE;
+signals:
+ void scheduleMessage(const QByteArray &);
+
protected:
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 processMessage(const QByteArray &msg);
+ void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value);
+
void prepareDeferredObjects(QObject *);
void buildObjectList(QDataStream &, QQmlContext *,
const QList<QPointer<QObject> > &instances);
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp
index d54bf98068..5b96163b48 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp
@@ -761,7 +761,7 @@ void QQmlNativeDebugServiceImpl::stateAboutToBeChanged(QQmlDebugService::State s
if (state == Enabled) {
foreach (NativeDebugger *debugger, m_debuggers) {
QV4::ExecutionEngine *engine = debugger->engine();
- if (!engine->debugger)
+ if (!engine->debugger())
engine->setDebugger(debugger);
}
}
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp
index 392080dd51..1214212727 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp
@@ -69,7 +69,7 @@ public:
QQmlWatcher *parent = 0);
public slots:
- void notifyValueChanged();
+ void notifyValueChanged(); // Needs to be a slot because of QQmlPropertyPrivate::connect()
private:
friend class QQmlWatcher;
@@ -88,7 +88,8 @@ QQmlWatchProxy::QQmlWatchProxy(int id,
QQmlWatcher *parent)
: QObject(parent), m_id(id), m_watch(parent), m_object(0), m_debugId(debugId), m_expr(exp)
{
- QObject::connect(m_expr, SIGNAL(valueChanged()), this, SLOT(notifyValueChanged()));
+ QObject::connect(m_expr, &QQmlExpression::valueChanged,
+ this, &QQmlWatchProxy::notifyValueChanged);
}
QQmlWatchProxy::QQmlWatchProxy(int id,
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp
index 53f2eab5ff..44810dd4cb 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp
@@ -79,6 +79,8 @@ QV4Debugger::QV4Debugger(QV4::ExecutionEngine *engine)
static int pauseReasonId = qRegisterMetaType<QV4Debugger::PauseReason>();
Q_UNUSED(debuggerId);
Q_UNUSED(pauseReasonId);
+ connect(this, &QV4Debugger::scheduleJob,
+ this, &QV4Debugger::runJobUnpaused, Qt::QueuedConnection);
}
QV4::ExecutionEngine *QV4Debugger::engine() const
@@ -320,7 +322,7 @@ void QV4Debugger::runInEngine_havingLock(QV4DebugJob *job)
if (state() == Paused)
m_runningCondition.wakeAll();
else
- QMetaObject::invokeMethod(this, "runJobUnpaused", Qt::QueuedConnection);
+ emit scheduleJob();
m_jobIsRunning.wait(&m_lock);
m_runningJob = 0;
}
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h
index 3a5b6080cb..cd412e573d 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h
@@ -140,15 +140,14 @@ public:
signals:
void debuggerPaused(QV4Debugger *self, QV4Debugger::PauseReason reason);
-
-private slots:
- void runJobUnpaused();
+ void scheduleJob();
private:
// requires lock to be held
void pauseAndWait(PauseReason reason);
bool reallyHitTheBreakPoint(const QString &filename, int linenr);
void runInEngine_havingLock(QV4DebugJob *job);
+ void runJobUnpaused();
QV4::ExecutionEngine *m_engine;
QV4::PersistentValue m_currentContext;
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h
index 1c7eb50ac7..39ac4d4dcb 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h
@@ -72,7 +72,6 @@ public:
void setBreakOnThrow(bool onoff);
void clearAllPauseRequests();
-public slots:
void debuggerPaused(QV4Debugger *debugger, QV4Debugger::PauseReason reason);
void handleDebuggerDeleted(QObject *debugger);
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
index c87ca47c49..00c5c1ad77 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp
@@ -706,7 +706,7 @@ void QV4DebugServiceImpl::engineAboutToBeRemoved(QJSEngine *engine)
if (engine){
const QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
if (ee) {
- QV4Debugger *debugger = qobject_cast<QV4Debugger *>(ee->debugger);
+ QV4Debugger *debugger = qobject_cast<QV4Debugger *>(ee->debugger());
if (debugger)
debuggerAgent.removeDebugger(debugger);
}
@@ -720,7 +720,7 @@ void QV4DebugServiceImpl::stateAboutToBeChanged(State state)
if (state == Enabled) {
foreach (QV4Debugger *debugger, debuggerAgent.debuggers()) {
QV4::ExecutionEngine *ee = debugger->engine();
- if (!ee->debugger)
+ if (!ee->debugger())
ee->setDebugger(debugger);
}
}
diff --git a/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp
index 2150b68f32..107d54c626 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp
@@ -148,10 +148,6 @@ public:
m_component.setData(qml, filename);
}
-signals:
- void result(int requestId, bool success);
-
-public slots:
void tryCreateObject(QQmlComponent::Status status)
{
switch (status) {
@@ -171,7 +167,7 @@ public slots:
else
emit result(m_requestId, false);
}
- delete this;
+ deleteLater(); // The component might send more signals
return;
}
default:
@@ -179,6 +175,9 @@ public slots:
}
}
+signals:
+ void result(int requestId, bool success);
+
private:
QQmlComponent m_component;
int m_requestId;
diff --git a/src/plugins/qmltooling/qmldbg_inspector/globalinspector.h b/src/plugins/qmltooling/qmldbg_inspector/globalinspector.h
index 7bbe6d6aa2..338eee14c3 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/globalinspector.h
+++ b/src/plugins/qmltooling/qmldbg_inspector/globalinspector.h
@@ -72,10 +72,8 @@ public:
signals:
void messageToClient(const QString &name, const QByteArray &data);
-private slots:
- void sendResult(int requestId, bool success);
-
private:
+ void sendResult(int requestId, bool success);
void sendCurrentObjects(const QList<QObject *> &objects);
void removeFromSelectedItems(QObject *object);
QString titleForItem(QQuickItem *item) const;
diff --git a/src/plugins/qmltooling/qmldbg_inspector/highlight.cpp b/src/plugins/qmltooling/qmldbg_inspector/highlight.cpp
index 26eb0f8ed8..88a6ea6b6d 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/highlight.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/highlight.cpp
@@ -72,24 +72,22 @@ void Highlight::setItem(QQuickItem *item)
m_item->disconnect(this);
if (item) {
- connect(item, SIGNAL(xChanged()), SLOT(adjust()));
- connect(item, SIGNAL(yChanged()), SLOT(adjust()));
- connect(item, SIGNAL(widthChanged()), SLOT(adjust()));
- connect(item, SIGNAL(heightChanged()), SLOT(adjust()));
- connect(item, SIGNAL(rotationChanged()), SLOT(adjust()));
- connect(item, SIGNAL(transformOriginChanged(TransformOrigin)),
- SLOT(adjust()));
+ connect(item, &QQuickItem::xChanged, this, &Highlight::adjust);
+ connect(item, &QQuickItem::yChanged, this, &Highlight::adjust);
+ connect(item, &QQuickItem::widthChanged, this, &Highlight::adjust);
+ connect(item, &QQuickItem::heightChanged, this, &Highlight::adjust);
+ connect(item, &QQuickItem::rotationChanged, this, &Highlight::adjust);
+ connect(item, &QQuickItem::transformOriginChanged, this, &Highlight::adjust);
}
QQuickWindow *view = item->window();
QQuickItem * contentItem = view->contentItem();
if (contentItem) {
- connect(contentItem, SIGNAL(xChanged()), SLOT(adjust()));
- connect(contentItem, SIGNAL(yChanged()), SLOT(adjust()));
- connect(contentItem, SIGNAL(widthChanged()), SLOT(adjust()));
- connect(contentItem, SIGNAL(heightChanged()), SLOT(adjust()));
- connect(contentItem, SIGNAL(rotationChanged()), SLOT(adjust()));
- connect(contentItem, SIGNAL(transformOriginChanged(TransformOrigin)),
- SLOT(adjust()));
+ connect(contentItem, &QQuickItem::xChanged, this, &Highlight::adjust);
+ connect(contentItem, &QQuickItem::yChanged, this, &Highlight::adjust);
+ connect(contentItem, &QQuickItem::widthChanged, this, &Highlight::adjust);
+ connect(contentItem, &QQuickItem::heightChanged, this, &Highlight::adjust);
+ connect(contentItem, &QQuickItem::rotationChanged, this, &Highlight::adjust);
+ connect(contentItem, &QQuickItem::transformOriginChanged, this, &Highlight::adjust);
}
m_item = item;
setContentsSize(view->size());
diff --git a/src/plugins/qmltooling/qmldbg_inspector/highlight.h b/src/plugins/qmltooling/qmldbg_inspector/highlight.h
index 4a85cb4d50..2bf4fc1ad5 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/highlight.h
+++ b/src/plugins/qmltooling/qmldbg_inspector/highlight.h
@@ -65,8 +65,6 @@ protected:
private:
void initRenderDetails();
-
-private slots:
void adjust();
private:
@@ -86,13 +84,12 @@ public:
void paint(QPainter *painter);
void showName(const QPointF &displayPoint);
-private slots:
- void disableNameDisplay();
-
private:
QPointF m_displayPoint;
QString m_name;
bool m_nameDisplayActive;
+
+ void disableNameDisplay();
};
/**
diff --git a/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp
index 48a3f656b0..ab1aeebf64 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/qqmlinspectorservice.cpp
@@ -55,23 +55,27 @@ public:
void setParentWindow(QQuickWindow *window, QWindow *parent) Q_DECL_OVERRIDE;
void removeWindow(QQuickWindow *window) Q_DECL_OVERRIDE;
+signals:
+ void scheduleMessage(const QByteArray &message);
+
protected:
virtual void messageReceived(const QByteArray &) Q_DECL_OVERRIDE;
-private slots:
- void messageFromClient(const QByteArray &message);
-
private:
friend class QQmlInspectorServiceFactory;
QmlJSDebugger::GlobalInspector *checkInspector();
QmlJSDebugger::GlobalInspector *m_globalInspector;
QHash<QQuickWindow *, QWindow *> m_waitingWindows;
+
+ void messageFromClient(const QByteArray &message);
};
QQmlInspectorServiceImpl::QQmlInspectorServiceImpl(QObject *parent):
QQmlInspectorService(1, parent), m_globalInspector(0)
{
+ connect(this, &QQmlInspectorServiceImpl::scheduleMessage,
+ this, &QQmlInspectorServiceImpl::messageFromClient, Qt::QueuedConnection);
}
QmlJSDebugger::GlobalInspector *QQmlInspectorServiceImpl::checkInspector()
@@ -122,8 +126,8 @@ void QQmlInspectorServiceImpl::setParentWindow(QQuickWindow *window, QWindow *pa
void QQmlInspectorServiceImpl::messageReceived(const QByteArray &message)
{
- QMetaObject::invokeMethod(this, "messageFromClient", Qt::QueuedConnection,
- Q_ARG(QByteArray, message));
+ // Move the message to the right thread via queued signal
+ emit scheduleMessage(message);
}
void QQmlInspectorServiceImpl::messageFromClient(const QByteArray &message)
diff --git a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
index 01c24f2395..64b26bdd0d 100644
--- a/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
+++ b/src/plugins/qmltooling/qmldbg_local/qlocalclientconnection.cpp
@@ -65,10 +65,8 @@ public:
void waitForConnection();
void flush();
-private slots:
- void connectionEstablished();
-
private:
+ void connectionEstablished();
bool connectToServer();
bool m_block;
@@ -135,7 +133,8 @@ bool QLocalClientConnection::connectToServer()
{
m_socket = new QLocalSocket;
m_socket->setParent(this);
- QObject::connect(m_socket, SIGNAL(connected()), this, SLOT(connectionEstablished()));
+ QObject::connect(m_socket, &QLocalSocket::connected,
+ this, &QLocalClientConnection::connectionEstablished);
m_socket->connectToServer(m_filename);
qDebug("QML Debugger: Connecting to socket %s...", m_filename.toLatin1().constData());
return true;
diff --git a/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.h b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.h
index 03b5b5eb1e..1184925e53 100644
--- a/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.h
+++ b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.h
@@ -63,11 +63,9 @@ public:
bool open(const QVariantHash &configuration) Q_DECL_OVERRIDE;
static void setDataStreamVersion(int version);
-private slots:
+private:
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;
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
index f161f988de..a4320098c0 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
@@ -48,20 +48,21 @@ QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEngin
next(0)
{
setService(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(bool)), engine->profiler, SLOT(reportData(bool)));
- connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
- engine->profiler, SLOT(setTimer(QElapsedTimer)));
- connect(engine->profiler,
- SIGNAL(dataReady(QVector<QQmlProfilerData>,QQmlProfiler::LocationHash)),
- this,
- SLOT(receiveData(QVector<QQmlProfilerData>,QQmlProfiler::LocationHash)));
+ engine->profiler = new QQmlProfiler;
+ connect(this, &QQmlProfilerAdapter::profilingEnabled,
+ engine->profiler, &QQmlProfiler::startProfiling);
+ connect(this, &QQmlAbstractProfilerAdapter::profilingEnabledWhileWaiting,
+ engine->profiler, &QQmlProfiler::startProfiling, Qt::DirectConnection);
+ connect(this, &QQmlAbstractProfilerAdapter::profilingDisabled,
+ engine->profiler, &QQmlProfiler::stopProfiling);
+ connect(this, &QQmlAbstractProfilerAdapter::profilingDisabledWhileWaiting,
+ engine->profiler, &QQmlProfiler::stopProfiling, Qt::DirectConnection);
+ connect(this, &QQmlAbstractProfilerAdapter::dataRequested,
+ engine->profiler, &QQmlProfiler::reportData);
+ connect(this, &QQmlAbstractProfilerAdapter::referenceTimeKnown,
+ engine->profiler, &QQmlProfiler::setTimer);
+ connect(engine->profiler, &QQmlProfiler::dataReady,
+ this, &QQmlProfilerAdapter::receiveData);
}
// convert to QByteArrays that can be sent to the debug client
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
index 96cdcd6d38..1fee5c389f 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
@@ -63,7 +63,6 @@ public:
qint64 sendMessages(qint64 until, QList<QByteArray> &messages,
bool trackLocations) Q_DECL_OVERRIDE;
-public slots:
void receiveData(const QVector<QQmlProfilerData> &new_data,
const QQmlProfiler::LocationHash &locations);
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
index 425543d27a..dba2fd3cc3 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
@@ -409,14 +409,16 @@ void QQmlProfilerServiceImpl::messageReceived(const QByteArray &message)
if (!stream.atEnd()) {
stream >> flushInterval;
m_flushTimer.setInterval(flushInterval);
+ auto timerStart = static_cast<void(QTimer::*)()>(&QTimer::start);
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()));
+ connect(&m_flushTimer, &QTimer::timeout, this, &QQmlProfilerServiceImpl::flush);
+ connect(this, &QQmlProfilerServiceImpl::startFlushTimer, &m_flushTimer, timerStart);
+ connect(this, &QQmlProfilerServiceImpl::stopFlushTimer, &m_flushTimer, &QTimer::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()));
+ disconnect(&m_flushTimer, &QTimer::timeout, this, &QQmlProfilerServiceImpl::flush);
+ disconnect(this, &QQmlProfilerServiceImpl::startFlushTimer, &m_flushTimer, timerStart);
+ disconnect(this, &QQmlProfilerServiceImpl::stopFlushTimer,
+ &m_flushTimer, &QTimer::stop);
}
}
if (!stream.atEnd())
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h
index 42efdefd12..bbfc32b681 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h
@@ -99,9 +99,6 @@ signals:
void startFlushTimer();
void stopFlushTimer();
-private slots:
- void flush();
-
protected:
virtual void stateAboutToBeChanged(State state) Q_DECL_OVERRIDE;
virtual void messageReceived(const QByteArray &) Q_DECL_OVERRIDE;
@@ -112,6 +109,7 @@ private:
void sendMessages();
void addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QJSEngine *engine);
void removeProfilerFromStartTimes(const QQmlAbstractProfilerAdapter *profiler);
+ void flush();
QElapsedTimer m_timer;
QTimer m_flushTimer;
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
index c3bbb86e3a..eee1dd7eae 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
@@ -46,27 +46,26 @@ QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::Execut
m_functionCallPos(0), m_memoryPos(0)
{
setService(service);
- engine->enableProfiler();
- connect(this, SIGNAL(profilingEnabled(quint64)),
- this, SLOT(forwardEnabled(quint64)));
- connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
- this, SLOT(forwardEnabledWhileWaiting(quint64)), Qt::DirectConnection);
- connect(this, SIGNAL(v4ProfilingEnabled(quint64)),
- engine->profiler, SLOT(startProfiling(quint64)));
- connect(this, SIGNAL(v4ProfilingEnabledWhileWaiting(quint64)),
- engine->profiler, SLOT(startProfiling(quint64)), Qt::DirectConnection);
- connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
- connect(this, SIGNAL(profilingDisabledWhileWaiting()), engine->profiler, SLOT(stopProfiling()),
+ engine->setProfiler(new QV4::Profiling::Profiler(engine));
+ connect(this, &QQmlAbstractProfilerAdapter::profilingEnabled,
+ this, &QV4ProfilerAdapter::forwardEnabled);
+ connect(this, &QQmlAbstractProfilerAdapter::profilingEnabledWhileWaiting,
+ this, &QV4ProfilerAdapter::forwardEnabledWhileWaiting, Qt::DirectConnection);
+ connect(this, &QV4ProfilerAdapter::v4ProfilingEnabled,
+ engine->profiler(), &QV4::Profiling::Profiler::startProfiling);
+ connect(this, &QV4ProfilerAdapter::v4ProfilingEnabledWhileWaiting,
+ engine->profiler(), &QV4::Profiling::Profiler::startProfiling, Qt::DirectConnection);
+ connect(this, &QQmlAbstractProfilerAdapter::profilingDisabled,
+ engine->profiler(), &QV4::Profiling::Profiler::stopProfiling);
+ connect(this, &QQmlAbstractProfilerAdapter::profilingDisabledWhileWaiting,
+ engine->profiler(), &QV4::Profiling::Profiler::stopProfiling,
Qt::DirectConnection);
- connect(this, SIGNAL(dataRequested(bool)), engine->profiler, SLOT(reportData(bool)));
- connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
- engine->profiler, SLOT(setTimer(QElapsedTimer)));
- connect(engine->profiler, SIGNAL(dataReady(QV4::Profiling::FunctionLocationHash,
- QVector<QV4::Profiling::FunctionCallProperties>,
- QVector<QV4::Profiling::MemoryAllocationProperties>)),
- this, SLOT(receiveData(QV4::Profiling::FunctionLocationHash,
- QVector<QV4::Profiling::FunctionCallProperties>,
- QVector<QV4::Profiling::MemoryAllocationProperties>)));
+ connect(this, &QQmlAbstractProfilerAdapter::dataRequested,
+ engine->profiler(), &QV4::Profiling::Profiler::reportData);
+ connect(this, &QQmlAbstractProfilerAdapter::referenceTimeKnown,
+ engine->profiler(), &QV4::Profiling::Profiler::setTimer);
+ connect(engine->profiler(), &QV4::Profiling::Profiler::dataReady,
+ this, &QV4ProfilerAdapter::receiveData);
}
qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &messages,
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
index 13a595f6eb..5d5b83f7ca 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
@@ -70,18 +70,13 @@ public:
virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages,
bool trackLocations) override;
-signals:
- void v4ProfilingEnabled(quint64 v4Features);
- void v4ProfilingEnabledWhileWaiting(quint64 v4Features);
-
-public slots:
void receiveData(const QV4::Profiling::FunctionLocationHash &,
const QVector<QV4::Profiling::FunctionCallProperties> &,
const QVector<QV4::Profiling::MemoryAllocationProperties> &);
-private slots:
- void forwardEnabled(quint64 features);
- void forwardEnabledWhileWaiting(quint64 features);
+signals:
+ void v4ProfilingEnabled(quint64 v4Features);
+ void v4ProfilingEnabledWhileWaiting(quint64 v4Features);
private:
QV4::Profiling::FunctionLocationHash m_functionLocations;
@@ -93,6 +88,8 @@ private:
qint64 appendMemoryEvents(qint64 until, QList<QByteArray> &messages, QQmlDebugPacket &d);
qint64 finalizeMessages(qint64 until, QList<QByteArray> &messages, qint64 callNext,
QQmlDebugPacket &d);
+ void forwardEnabled(quint64 features);
+ void forwardEnabledWhileWaiting(quint64 features);
static quint64 translateFeatures(quint64 qmlFeatures);
};
diff --git a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp
index bebf8806c6..0c9fc36463 100644
--- a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp
@@ -51,20 +51,20 @@ QQuickProfilerAdapter::QQuickProfilerAdapter(QObject *parent) :
QQuickProfiler::initialize(this);
// We can always do DirectConnection here as all methods are protected by mutexes
- connect(this, SIGNAL(profilingEnabled(quint64)),
- QQuickProfiler::s_instance, SLOT(startProfilingImpl(quint64)), Qt::DirectConnection);
- connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
- QQuickProfiler::s_instance, SLOT(startProfilingImpl(quint64)), Qt::DirectConnection);
- connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
- QQuickProfiler::s_instance, SLOT(setTimer(QElapsedTimer)), Qt::DirectConnection);
- connect(this, SIGNAL(profilingDisabled()),
- QQuickProfiler::s_instance, SLOT(stopProfilingImpl()), Qt::DirectConnection);
- connect(this, SIGNAL(profilingDisabledWhileWaiting()),
- QQuickProfiler::s_instance, SLOT(stopProfilingImpl()), Qt::DirectConnection);
- connect(this, SIGNAL(dataRequested(bool)),
- QQuickProfiler::s_instance, SLOT(reportDataImpl(bool)), Qt::DirectConnection);
- connect(QQuickProfiler::s_instance, SIGNAL(dataReady(QVector<QQuickProfilerData>)),
- this, SLOT(receiveData(QVector<QQuickProfilerData>)), Qt::DirectConnection);
+ connect(this, &QQmlAbstractProfilerAdapter::profilingEnabled,
+ QQuickProfiler::s_instance, &QQuickProfiler::startProfilingImpl, Qt::DirectConnection);
+ connect(this, &QQmlAbstractProfilerAdapter::profilingEnabledWhileWaiting,
+ QQuickProfiler::s_instance, &QQuickProfiler::startProfilingImpl, Qt::DirectConnection);
+ connect(this, &QQmlAbstractProfilerAdapter::referenceTimeKnown,
+ QQuickProfiler::s_instance, &QQuickProfiler::setTimer, Qt::DirectConnection);
+ connect(this, &QQmlAbstractProfilerAdapter::profilingDisabled,
+ QQuickProfiler::s_instance, &QQuickProfiler::stopProfilingImpl, Qt::DirectConnection);
+ connect(this, &QQmlAbstractProfilerAdapter::profilingDisabledWhileWaiting,
+ QQuickProfiler::s_instance, &QQuickProfiler::stopProfilingImpl, Qt::DirectConnection);
+ connect(this, &QQmlAbstractProfilerAdapter::dataRequested,
+ QQuickProfiler::s_instance, &QQuickProfiler::reportDataImpl, Qt::DirectConnection);
+ connect(QQuickProfiler::s_instance, &QQuickProfiler::dataReady,
+ this, &QQuickProfilerAdapter::receiveData, Qt::DirectConnection);
}
QQuickProfilerAdapter::~QQuickProfilerAdapter()
diff --git a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h
index f1ba411ac5..1ad020afd6 100644
--- a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h
+++ b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h
@@ -62,8 +62,6 @@ public:
QQuickProfilerAdapter(QObject *parent = 0);
~QQuickProfilerAdapter();
qint64 sendMessages(qint64 until, QList<QByteArray> &messages, bool trackLocations) override;
-
-public slots:
void receiveData(const QVector<QQuickProfilerData> &new_data);
private:
diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
index cbde86e389..96b3455790 100644
--- a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
+++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
@@ -149,15 +149,6 @@ public:
static void cleanup();
-private slots:
- void wakeEngine(QJSEngine *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;
@@ -179,6 +170,13 @@ private:
bool canSendMessage(const QString &name);
void doSendMessage(const QString &name, const QByteArray &message);
+ void wakeEngine(QJSEngine *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();
QQmlDebugServerConnection *m_connection;
QHash<QString, QQmlDebugService *> m_plugins;
@@ -203,18 +201,22 @@ void QQmlDebugServerImpl::cleanup()
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));
+ {
+ QObject signalSource;
+ for (QHash<QString, QQmlDebugService *>::ConstIterator i = server->m_plugins.constBegin();
+ i != server->m_plugins.constEnd(); ++i) {
+ server->m_changeServiceStateCalls.ref();
+ QString key = i.key();
+ // Process this in the server's thread.
+ connect(&signalSource, &QObject::destroyed, server, [key, server](){
+ server->changeServiceState(key, QQmlDebugService::NotConnected);
+ }, Qt::QueuedConnection);
+ }
}
// 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)
+ // might again defer execution of stuff in the GUI thread)
QEventLoop loop;
while (!server->m_changeServiceStateCalls.testAndSetOrdered(0, 0))
loop.processEvents();
@@ -293,7 +295,7 @@ QQmlDebugServerImpl::QQmlDebugServerImpl() :
// 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()),
+ QObject::connect(&m_thread, &QThread::finished, this, &QQmlDebugServerImpl::removeThread,
Qt::DirectConnection);
m_thread.setObjectName(QStringLiteral("QQmlDebugServerThread"));
parseArguments();
@@ -631,15 +633,15 @@ bool QQmlDebugServerImpl::addService(const QString &name, QQmlDebugService *serv
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, &QQmlDebugService::messageToClient,
+ this, &QQmlDebugServerImpl::sendMessage);
+ connect(service, &QQmlDebugService::messagesToClient,
+ this, &QQmlDebugServerImpl::sendMessages);
- connect(service, SIGNAL(attachedToEngine(QJSEngine*)),
- this, SLOT(wakeEngine(QJSEngine*)), Qt::QueuedConnection);
- connect(service, SIGNAL(detachedFromEngine(QJSEngine*)),
- this, SLOT(wakeEngine(QJSEngine*)), Qt::QueuedConnection);
+ connect(service, &QQmlDebugService::attachedToEngine,
+ this, &QQmlDebugServerImpl::wakeEngine, Qt::QueuedConnection);
+ connect(service, &QQmlDebugService::detachedFromEngine,
+ this, &QQmlDebugServerImpl::wakeEngine, Qt::QueuedConnection);
service->setState(QQmlDebugService::Unavailable);
m_plugins.insert(name, service);
@@ -659,15 +661,15 @@ bool QQmlDebugServerImpl::removeService(const QString &name)
m_plugins.remove(name);
service->setState(QQmlDebugService::NotConnected);
- disconnect(service, SIGNAL(detachedFromEngine(QJSEngine*)),
- this, SLOT(wakeEngine(QJSEngine*)));
- disconnect(service, SIGNAL(attachedToEngine(QJSEngine*)),
- this, SLOT(wakeEngine(QJSEngine*)));
+ disconnect(service, &QQmlDebugService::detachedFromEngine,
+ this, &QQmlDebugServerImpl::wakeEngine);
+ disconnect(service, &QQmlDebugService::attachedToEngine,
+ this, &QQmlDebugServerImpl::wakeEngine);
- disconnect(service, SIGNAL(messagesToClient(QString,QList<QByteArray>)),
- this, SLOT(sendMessages(QString,QList<QByteArray>)));
- disconnect(service, SIGNAL(messageToClient(QString,QByteArray)),
- this, SLOT(sendMessage(QString,QByteArray)));
+ disconnect(service, &QQmlDebugService::messagesToClient,
+ this, &QQmlDebugServerImpl::sendMessages);
+ disconnect(service, &QQmlDebugService::messageToClient,
+ this, &QQmlDebugServerImpl::sendMessage);
return true;
}
@@ -738,8 +740,10 @@ void QQmlDebugServerImpl::EngineCondition::wake()
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()));
+ QObject::connect(m_protocol, &QPacketProtocol::readyRead,
+ this, &QQmlDebugServerImpl::receiveMessage);
+ QObject::connect(m_protocol, &QPacketProtocol::invalidPacket,
+ this, &QQmlDebugServerImpl::invalidPacket);
if (blockingMode())
m_protocol->waitForReadyRead(-1);
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
index 3d64312b16..b305c3f535 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
@@ -65,10 +65,8 @@ public:
void waitForConnection();
void flush();
-private slots:
- void newConnection();
-
private:
+ void newConnection();
bool listen();
int m_portFrom;
@@ -152,7 +150,8 @@ void QTcpServerConnection::flush()
bool QTcpServerConnection::listen()
{
m_tcpServer = new QTcpServer(this);
- QObject::connect(m_tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection()));
+ QObject::connect(m_tcpServer, &QTcpServer::newConnection,
+ this, &QTcpServerConnection::newConnection);
QHostAddress hostaddress;
if (!m_hostaddress.isEmpty()) {
if (!hostaddress.setAddress(m_hostaddress)) {
diff --git a/src/plugins/qmltooling/shared/qqmldebugserver.h b/src/plugins/qmltooling/shared/qqmldebugserver.h
index 424c7c4120..109f1e246c 100644
--- a/src/plugins/qmltooling/shared/qqmldebugserver.h
+++ b/src/plugins/qmltooling/shared/qqmldebugserver.h
@@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE
-class QQmlDebugServer : protected QQmlDebugConnector
+class QQmlDebugServer : public QQmlDebugConnector
{
Q_OBJECT
public:
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp
index 34ab4d11b0..e32ecdc138 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp
@@ -682,9 +682,11 @@ void QSGD3D12EnginePrivate::releaseResources()
commandQueue = nullptr;
copyCommandQueue = nullptr;
+#ifndef Q_OS_WINRT
dcompTarget = nullptr;
dcompVisual = nullptr;
dcompDevice = nullptr;
+#endif
swapChain = nullptr;
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12engine_p_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12engine_p_p.h
index 2b1e3dc7b7..b3b244cd86 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12engine_p_p.h
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12engine_p_p.h
@@ -435,9 +435,11 @@ private:
DeviceLossTester devLossTest;
+#ifndef Q_OS_WINRT
ComPtr<IDCompositionDevice> dcompDevice;
ComPtr<IDCompositionTarget> dcompTarget;
ComPtr<IDCompositionVisual> dcompVisual;
+#endif
};
inline uint qHash(const QSGD3D12EnginePrivate::PersistentFrameData::PendingRelease &pr, uint seed = 0)
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp
index 11b88cfd34..a803f67380 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp
@@ -44,7 +44,6 @@
#include "qsgd3d12shadereffectnode_p.h"
#include <private/qsgrenderer_p.h>
#include <private/qquickwindow_p.h>
-#include <private/qquickprofiler_p.h>
#include <private/qquickanimatorcontroller_p.h>
#include <private/qquickprofiler_p.h>
#include <private/qqmldebugserviceinterfaces_p.h>
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index f736e04b88..2c164abd6f 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -819,7 +819,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
const QStringRef &name = node->name;
bool typeFound = false;
- QV4::CompiledData::Property::Type type;
+ QV4::CompiledData::Property::Type type = QV4::CompiledData::Property::Var;
for (int ii = 0; !typeFound && ii < propTypeNameToTypesCount; ++ii) {
const TypeNameToType *t = propTypeNameToTypes + ii;
@@ -1359,7 +1359,7 @@ bool IRBuilder::isRedundantNullInitializerForPropertyDeclaration(Property *prope
return QQmlJS::AST::cast<QQmlJS::AST::NullExpression *>(expr);
}
-QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
+QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output, QQmlEngine *engine, const QV4::CompiledData::ResolvedTypeReferenceMap &dependentTypes)
{
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = output.javaScriptCompilationUnit;
QV4::CompiledData::Unit *jsUnit = compilationUnit->createUnitData(&output);
@@ -1402,6 +1402,20 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
qmlUnit->offsetToStringTable = totalSize - output.jsGenerator.stringTable.sizeOfTableAndData();
qmlUnit->stringTableSize = output.jsGenerator.stringTable.stringCount();
+#ifndef V4_BOOTSTRAP
+ if (!dependentTypes.isEmpty()) {
+ QCryptographicHash hash(QCryptographicHash::Md5);
+ if (dependentTypes.addToHash(&hash, engine)) {
+ QByteArray checksum = hash.result();
+ Q_ASSERT(checksum.size() == sizeof(qmlUnit->dependencyMD5Checksum));
+ memcpy(qmlUnit->dependencyMD5Checksum, checksum.constData(), sizeof(qmlUnit->dependencyMD5Checksum));
+ }
+ }
+#else
+ Q_UNUSED(dependentTypes);
+ Q_UNUSED(engine);
+#endif
+
// write imports
char *importPtr = data + qmlUnit->offsetToImports;
foreach (const QV4::CompiledData::Import *imp, output.imports) {
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 821a6bba6d..eedc262e7a 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -549,7 +549,7 @@ public:
struct Q_QML_PRIVATE_EXPORT QmlUnitGenerator
{
- QV4::CompiledData::Unit *generate(Document &output);
+ QV4::CompiledData::Unit *generate(Document &output, QQmlEngine *engine, const QV4::CompiledData::ResolvedTypeReferenceMap &dependentTypes);
private:
typedef bool (Binding::*BindingFilter)() const;
diff --git a/src/qml/compiler/qqmlpropertyvalidator.cpp b/src/qml/compiler/qqmlpropertyvalidator.cpp
index 9ea52e240d..c644330e97 100644
--- a/src/qml/compiler/qqmlpropertyvalidator.cpp
+++ b/src/qml/compiler/qqmlpropertyvalidator.cpp
@@ -492,6 +492,16 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
}
}
break;
+ case QVariant::Vector2D: {
+ struct {
+ float xp;
+ float yp;
+ } vec;
+ if (!QQmlStringConverters::createFromString(QMetaType::QVector2D, binding->valueAsString(qmlUnit), &vec, sizeof(vec))) {
+ return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: 2D vector expected"));
+ }
+ }
+ break;
case QVariant::Vector3D: {
struct {
float xp;
@@ -515,6 +525,18 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
}
}
break;
+ case QVariant::Quaternion: {
+ struct {
+ float wp;
+ float xp;
+ float yp;
+ float zp;
+ } vec;
+ if (!QQmlStringConverters::createFromString(QMetaType::QQuaternion, binding->valueAsString(qmlUnit), &vec, sizeof(vec))) {
+ return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: quaternion expected"));
+ }
+ }
+ break;
case QVariant::RegExp:
return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: regular expression expected; use /pattern/ syntax"));
default: {
diff --git a/src/qml/compiler/qqmlpropertyvalidator_p.h b/src/qml/compiler/qqmlpropertyvalidator_p.h
index 1cbb370068..d0bd314461 100644
--- a/src/qml/compiler/qqmlpropertyvalidator_p.h
+++ b/src/qml/compiler/qqmlpropertyvalidator_p.h
@@ -76,7 +76,7 @@ private:
QQmlEnginePrivate *enginePrivate;
const QQmlImports &imports;
const QV4::CompiledData::Unit *qmlUnit;
- const QHash<int, QV4::CompiledData::CompilationUnit::ResolvedTypeReference*> &resolvedTypes;
+ const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypes;
const QQmlPropertyCacheVector &propertyCaches;
QVector<QV4::CompiledData::BindingPropertyData> * const bindingPropertyDataPerObject;
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index bb4d603f68..68de9aee44 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -56,7 +56,9 @@
QT_BEGIN_NAMESPACE
-QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *parsedQML, const QQmlRefPointer<QQmlTypeNameCache> &importCache, const QV4::CompiledData::CompilationUnit::ResolvedTypeReferenceMap &resolvedTypeCache)
+QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData,
+ QmlIR::Document *parsedQML, const QQmlRefPointer<QQmlTypeNameCache> &importCache,
+ const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache)
: resolvedTypes(resolvedTypeCache)
, engine(engine)
, typeData(typeData)
@@ -154,7 +156,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile()
// Generate QML compiled type data structures
QmlIR::QmlUnitGenerator qmlGenerator;
- QV4::CompiledData::Unit *qmlUnit = qmlGenerator.generate(*document);
+ QV4::CompiledData::Unit *qmlUnit = qmlGenerator.generate(*document, QQmlEnginePrivate::get(engine), resolvedTypes);
Q_ASSERT(document->javaScriptCompilationUnit);
// The js unit owns the data and will free the qml unit.
@@ -837,7 +839,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
syntheticComponent->flags |= QV4::CompiledData::Object::IsComponent;
if (!resolvedTypes->contains(syntheticComponent->inheritedTypeNameIndex)) {
- auto typeRef = new QV4::CompiledData::CompilationUnit::ResolvedTypeReference;
+ auto typeRef = new QV4::CompiledData::ResolvedTypeReference;
typeRef->type = componentType;
typeRef->majorVersion = componentType->majorVersion();
typeRef->minorVersion = componentType->minorVersion();
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index 9f1a09b35c..6ad6ad8557 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -89,7 +89,7 @@ struct QQmlTypeCompiler
{
Q_DECLARE_TR_FUNCTIONS(QQmlTypeCompiler)
public:
- QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *document, const QQmlRefPointer<QQmlTypeNameCache> &importCache, const QV4::CompiledData::CompilationUnit::ResolvedTypeReferenceMap &resolvedTypeCache);
+ QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *document, const QQmlRefPointer<QQmlTypeNameCache> &importCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache);
// --- interface used by QQmlPropertyCacheCreator
typedef QmlIR::Object CompiledObject;
@@ -98,7 +98,7 @@ public:
QString stringAt(int idx) const;
QmlIR::PoolList<QmlIR::Function>::Iterator objectFunctionsBegin(const QmlIR::Object *object) const { return object->functionsBegin(); }
QmlIR::PoolList<QmlIR::Function>::Iterator objectFunctionsEnd(const QmlIR::Object *object) const { return object->functionsEnd(); }
- QV4::CompiledData::CompilationUnit::ResolvedTypeReferenceMap resolvedTypes;
+ QV4::CompiledData::ResolvedTypeReferenceMap resolvedTypes;
// ---
QV4::CompiledData::CompilationUnit *compile();
@@ -182,7 +182,7 @@ private:
const QVector<QmlIR::Object*> &qmlObjects;
const QQmlImports *imports;
const QHash<int, QQmlCustomParser*> &customParsers;
- const QHash<int, QV4::CompiledData::CompilationUnit::ResolvedTypeReference*> &resolvedTypes;
+ const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypes;
const QSet<QString> &illegalNames;
const QQmlPropertyCacheVector * const propertyCaches;
};
@@ -213,7 +213,7 @@ private:
const QVector<QmlIR::Object*> &qmlObjects;
const QQmlPropertyCacheVector * const propertyCaches;
const QQmlImports *imports;
- QHash<int, QV4::CompiledData::CompilationUnit::ResolvedTypeReference *> *resolvedTypes;
+ QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypes;
};
class QQmlCustomParserScriptIndexer: public QQmlCompilePass
@@ -288,7 +288,7 @@ protected:
QHash<int, int> _idToObjectIndex;
QVector<int> _objectsWithAliases;
- QHash<int, QV4::CompiledData::CompilationUnit::ResolvedTypeReference*> *resolvedTypes;
+ QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypes;
QQmlPropertyCacheVector propertyCaches;
};
@@ -321,7 +321,7 @@ private:
bool compileComponent(int componentRoot);
bool compileJavaScriptCodeInObjectsRecursively(int objectIndex, int scopeObjectIndex);
- const QHash<int, QV4::CompiledData::CompilationUnit::ResolvedTypeReference*> &resolvedTypes;
+ const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypes;
const QHash<int, QQmlCustomParser*> &customParsers;
const QVector<QmlIR::Object*> &qmlObjects;
const QQmlPropertyCacheVector * const propertyCaches;
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 7a444e8c57..4130ad08d7 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -1058,6 +1058,8 @@ bool Codegen::visit(ArrayLiteral *ast)
current->expr = _block->CONST(IR::MissingType, 0);
}
Result expr = expression(it->expression);
+ if (hasError)
+ return false;
IR::ExprList *arg = _function->New<IR::ExprList>();
if (!current) {
@@ -1100,6 +1102,8 @@ bool Codegen::visit(ArrayMemberExpression *ast)
Result base = expression(ast->base);
Result index = expression(ast->expression);
+ if (hasError)
+ return false;
_expr.code = subscript(*base, *index);
return false;
}
@@ -1139,10 +1143,16 @@ bool Codegen::visit(BinaryExpression *ast)
const unsigned r = _block->newTemp();
- move(_block->TEMP(r), *expression(ast->left));
+ Result lhs = expression(ast->left);
+ if (hasError)
+ return false;
+ move(_block->TEMP(r), *lhs);
setLocation(cjump(_block->TEMP(r), iftrue, endif), ast->operatorToken);
_block = iftrue;
- move(_block->TEMP(r), *expression(ast->right));
+ Result rhs = expression(ast->right);
+ if (hasError)
+ return false;
+ move(_block->TEMP(r), *rhs);
_block->JUMP(endif);
_expr.code = _block->TEMP(r);
@@ -1160,10 +1170,16 @@ bool Codegen::visit(BinaryExpression *ast)
IR::BasicBlock *endif = _function->newBasicBlock(exceptionHandler());
const unsigned r = _block->newTemp();
- move(_block->TEMP(r), *expression(ast->left));
+ Result lhs = expression(ast->left);
+ if (hasError)
+ return false;
+ move(_block->TEMP(r), *lhs);
setLocation(cjump(_block->TEMP(r), endif, iffalse), ast->operatorToken);
_block = iffalse;
- move(_block->TEMP(r), *expression(ast->right));
+ Result rhs = expression(ast->right);
+ if (hasError)
+ return false;
+ move(_block->TEMP(r), *rhs);
_block->JUMP(endif);
_block = endif;
@@ -1173,6 +1189,8 @@ bool Codegen::visit(BinaryExpression *ast)
}
IR::Expr* left = *expression(ast->left);
+ if (hasError)
+ return false;
switch (ast->op) {
case QSOperator::Or:
@@ -1182,17 +1200,19 @@ bool Codegen::visit(BinaryExpression *ast)
case QSOperator::Assign: {
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(left, ast->left->lastSourceLocation()))
return false;
- IR::Expr* right = *expression(ast->right);
+ Result right = expression(ast->right);
+ if (hasError)
+ return false;
if (!left->isLValue()) {
throwReferenceError(ast->operatorToken, QStringLiteral("left-hand side of assignment operator is not an lvalue"));
return false;
}
if (_expr.accept(nx)) {
- move(left, right);
+ move(left, *right);
} else {
const unsigned t = _block->newTemp();
- move(_block->TEMP(t), right);
+ move(_block->TEMP(t), *right);
move(left, _block->TEMP(t));
_expr.code = _block->TEMP(t);
}
@@ -1212,17 +1232,19 @@ bool Codegen::visit(BinaryExpression *ast)
case QSOperator::InplaceXor: {
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(left, ast->left->lastSourceLocation()))
return false;
- IR::Expr* right = *expression(ast->right);
+ Result right = expression(ast->right);
+ if (hasError)
+ return false;
if (!left->isLValue()) {
throwSyntaxError(ast->operatorToken, QStringLiteral("left-hand side of inplace operator is not an lvalue"));
return false;
}
if (_expr.accept(nx)) {
- move(left, right, baseOp(ast->op));
+ move(left, *right, baseOp(ast->op));
} else {
const unsigned t = _block->newTemp();
- move(_block->TEMP(t), right);
+ move(_block->TEMP(t), *right);
move(left, _block->TEMP(t), baseOp(ast->op));
_expr.code = left;
}
@@ -1245,12 +1267,14 @@ bool Codegen::visit(BinaryExpression *ast)
left = _block->TEMP(t);
}
- IR::Expr* right = *expression(ast->right);
+ Result right = expression(ast->right);
+ if (hasError)
+ return false;
if (_expr.accept(cx)) {
- setLocation(cjump(binop(IR::binaryOperator(ast->op), left, right, ast->operatorToken), _expr.iftrue, _expr.iffalse), ast->operatorToken);
+ setLocation(cjump(binop(IR::binaryOperator(ast->op), left, *right, ast->operatorToken), _expr.iftrue, _expr.iffalse), ast->operatorToken);
} else {
- IR::Expr *e = binop(IR::binaryOperator(ast->op), left, right, ast->operatorToken);
+ IR::Expr *e = binop(IR::binaryOperator(ast->op), left, *right, ast->operatorToken);
if (e->asConst() || e->asString())
_expr.code = e;
else {
@@ -1279,9 +1303,11 @@ bool Codegen::visit(BinaryExpression *ast)
left = _block->TEMP(t);
}
- IR::Expr* right = *expression(ast->right);
+ Result right = expression(ast->right);
+ if (hasError)
+ return false;
- IR::Expr *e = binop(IR::binaryOperator(ast->op), left, right, ast->operatorToken);
+ IR::Expr *e = binop(IR::binaryOperator(ast->op), left, *right, ast->operatorToken);
if (e->asConst() || e->asString())
_expr.code = e;
else {
@@ -1306,11 +1332,15 @@ bool Codegen::visit(CallExpression *ast)
IR::ExprList *args = 0, **args_it = &args;
for (ArgumentList *it = ast->arguments; it; it = it->next) {
Result arg = expression(it->expression);
+ if (hasError)
+ return false;
IR::Expr *actual = argument(*arg);
*args_it = _function->New<IR::ExprList>();
(*args_it)->init(actual);
args_it = &(*args_it)->next;
}
+ if (hasError)
+ return false;
_expr.code = call(*base, args);
return false;
}
@@ -1329,11 +1359,17 @@ bool Codegen::visit(ConditionalExpression *ast)
condition(ast->expression, iftrue, iffalse);
_block = iftrue;
- move(_block->TEMP(t), *expression(ast->ok));
+ Result ok = expression(ast->ok);
+ if (hasError)
+ return false;
+ move(_block->TEMP(t), *ok);
_block->JUMP(endif);
_block = iffalse;
- move(_block->TEMP(t), *expression(ast->ko));
+ Result ko = expression(ast->ko);
+ if (hasError)
+ return false;
+ move(_block->TEMP(t), *ko);
_block->JUMP(endif);
_block = endif;
@@ -1349,6 +1385,8 @@ bool Codegen::visit(DeleteExpression *ast)
return false;
IR::Expr* expr = *expression(ast->expression);
+ if (hasError)
+ return false;
// Temporaries cannot be deleted
IR::ArgLocal *al = expr->asArgLocal();
if (al && al->index < static_cast<unsigned>(_env->members.size())) {
@@ -1410,7 +1448,8 @@ bool Codegen::visit(FieldMemberExpression *ast)
return false;
Result base = expression(ast->base);
- _expr.code = member(*base, _function->newString(ast->name.toString()));
+ if (!hasError)
+ _expr.code = member(*base, _function->newString(ast->name.toString()));
return false;
}
@@ -1501,6 +1540,8 @@ bool Codegen::visit(NewExpression *ast)
return false;
Result base = expression(ast->expression);
+ if (hasError)
+ return false;
IR::Expr *expr = *base;
if (expr && !expr->asTemp() && !expr->asArgLocal() && !expr->asName() && !expr->asMember()) {
const unsigned t = _block->newTemp();
@@ -1517,6 +1558,8 @@ bool Codegen::visit(NewMemberExpression *ast)
return false;
Result base = expression(ast->base);
+ if (hasError)
+ return false;
IR::Expr *expr = *base;
if (expr && !expr->asTemp() && !expr->asArgLocal() && !expr->asName() && !expr->asMember()) {
const unsigned t = _block->newTemp();
@@ -1527,6 +1570,8 @@ bool Codegen::visit(NewMemberExpression *ast)
IR::ExprList *args = 0, **args_it = &args;
for (ArgumentList *it = ast->arguments; it; it = it->next) {
Result arg = expression(it->expression);
+ if (hasError)
+ return false;
IR::Expr *actual = argument(*arg);
*args_it = _function->New<IR::ExprList>();
(*args_it)->init(actual);
@@ -1544,6 +1589,8 @@ bool Codegen::visit(NotExpression *ast)
return false;
Result expr = expression(ast->expression);
+ if (hasError)
+ return false;
const unsigned r = _block->newTemp();
setLocation(move(_block->TEMP(r), unop(IR::OpNot, *expr, ast->notToken)), ast->notToken);
_expr.code = _block->TEMP(r);
@@ -1601,6 +1648,8 @@ bool Codegen::visit(ObjectLiteral *ast)
QString name = it->assignment->name->asString();
if (PropertyNameAndValue *nv = AST::cast<AST::PropertyNameAndValue *>(it->assignment)) {
Result value = expression(nv->value);
+ if (hasError)
+ return false;
ObjectPropertyValue &v = valueMap[name];
if (v.hasGetter() || v.hasSetter() || (_function->isStrict && v.value)) {
throwSyntaxError(nv->lastSourceLocation(),
@@ -1731,6 +1780,8 @@ bool Codegen::visit(PostDecrementExpression *ast)
return false;
Result expr = expression(ast->base);
+ if (hasError)
+ return false;
if (!expr->isLValue()) {
throwReferenceError(ast->base->lastSourceLocation(), QStringLiteral("Invalid left-hand side expression in postfix operation"));
return false;
@@ -1757,6 +1808,8 @@ bool Codegen::visit(PostIncrementExpression *ast)
return false;
Result expr = expression(ast->base);
+ if (hasError)
+ return false;
if (!expr->isLValue()) {
throwReferenceError(ast->base->lastSourceLocation(), QStringLiteral("Invalid left-hand side expression in postfix operation"));
return false;
@@ -1783,6 +1836,8 @@ bool Codegen::visit(PreDecrementExpression *ast)
return false;
Result expr = expression(ast->expression);
+ if (hasError)
+ return false;
if (!expr->isLValue()) {
throwReferenceError(ast->expression->lastSourceLocation(), QStringLiteral("Prefix ++ operator applied to value that is not a reference."));
return false;
@@ -1808,6 +1863,8 @@ bool Codegen::visit(PreIncrementExpression *ast)
return false;
Result expr = expression(ast->expression);
+ if (hasError)
+ return false;
if (!expr->isLValue()) {
throwReferenceError(ast->expression->lastSourceLocation(), QStringLiteral("Prefix ++ operator applied to value that is not a reference."));
return false;
@@ -1860,6 +1917,8 @@ bool Codegen::visit(TildeExpression *ast)
return false;
Result expr = expression(ast->expression);
+ if (hasError)
+ return false;
const unsigned t = _block->newTemp();
setLocation(move(_block->TEMP(t), unop(IR::OpCompl, *expr, ast->tildeToken)), ast->tildeToken);
_expr.code = _block->TEMP(t);
@@ -1885,6 +1944,8 @@ bool Codegen::visit(TypeOfExpression *ast)
return false;
Result expr = expression(ast->expression);
+ if (hasError)
+ return false;
IR::ExprList *args = _function->New<IR::ExprList>();
args->init(reference(*expr));
_expr.code = call(_block->NAME(IR::Name::builtin_typeof, ast->typeofToken.startLine, ast->typeofToken.startColumn), args);
@@ -1897,6 +1958,8 @@ bool Codegen::visit(UnaryMinusExpression *ast)
return false;
Result expr = expression(ast->expression);
+ if (hasError)
+ return false;
const unsigned t = _block->newTemp();
setLocation(move(_block->TEMP(t), unop(IR::OpUMinus, *expr, ast->minusToken)), ast->minusToken);
_expr.code = _block->TEMP(t);
@@ -1909,6 +1972,8 @@ bool Codegen::visit(UnaryPlusExpression *ast)
return false;
Result expr = expression(ast->expression);
+ if (hasError)
+ return false;
const unsigned t = _block->newTemp();
setLocation(move(_block->TEMP(t), unop(IR::OpUPlus, *expr, ast->plusToken)), ast->plusToken);
_expr.code = _block->TEMP(t);
@@ -2224,7 +2289,10 @@ bool Codegen::visit(ForEachStatement *ast)
IR::BasicBlock *foreachend = _function->newBasicBlock(exceptionHandler());
int objectToIterateOn = _block->newTemp();
- move(_block->TEMP(objectToIterateOn), *expression(ast->expression));
+ Result expr = expression(ast->expression);
+ if (hasError)
+ return false;
+ move(_block->TEMP(objectToIterateOn), *expr);
IR::ExprList *args = _function->New<IR::ExprList>();
args->init(_block->TEMP(objectToIterateOn));
@@ -2236,7 +2304,10 @@ bool Codegen::visit(ForEachStatement *ast)
_block = foreachbody;
int temp = _block->newTemp();
- move(*expression(ast->initialiser), _block->TEMP(temp));
+ Result init = expression(ast->initialiser);
+ if (hasError)
+ return false;
+ move(*init, _block->TEMP(temp));
statement(ast->statement);
_block->JUMP(foreachin);
@@ -2726,7 +2797,10 @@ bool Codegen::visit(WithStatement *ast)
_function->hasWith = true;
const int withObject = _block->newTemp();
- _block->MOVE(_block->TEMP(withObject), *expression(ast->expression));
+ Result src = expression(ast->expression);
+ if (hasError)
+ return false;
+ _block->MOVE(_block->TEMP(withObject), *src);
// need an exception handler for with to cleanup the with scope
IR::BasicBlock *withExceptionHandler = _function->newBasicBlock(exceptionHandler());
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 3f7c8df973..5948992f67 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -50,6 +50,7 @@
#include <private/qqmltypeloader_p.h>
#include <private/qqmlengine_p.h>
#include <QQmlPropertyMap>
+#include <QDateTime>
#include <QSaveFile>
#include <QFile>
#include <QFileInfo>
@@ -57,6 +58,7 @@
#endif
#include <private/qqmlirbuilder_p.h>
#include <QCoreApplication>
+#include <QCryptographicHash>
#include <algorithm>
@@ -160,6 +162,16 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
}
}
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ Value *bigEndianConstants = new Value[data->constantTableSize];
+ const LEUInt64 *littleEndianConstants = data->constants();
+ for (uint i = 0; i < data->constantTableSize; ++i)
+ bigEndianConstants[i] = Value::fromReturnedValue(littleEndianConstants[i]);
+ constants = bigEndianConstants;
+#else
+ constants = reinterpret_cast<const Value*>(data->constants());
+#endif
+
linkBackendToEngine(engine);
if (data->indexOfRootFunction != -1)
@@ -202,6 +214,9 @@ void CompilationUnit::unlink()
runtimeClasses = 0;
qDeleteAll(runtimeFunctions);
runtimeFunctions.clear();
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ delete [] constants;
+#endif
}
void CompilationUnit::markObjects(QV4::ExecutionEngine *e)
@@ -290,6 +305,11 @@ bool CompilationUnit::saveToDisk(QString *errorString)
{
errorString->clear();
+ if (data->sourceTimeStamp == 0) {
+ *errorString = QStringLiteral("Missing time stamp for source file");
+ return false;
+ }
+
const QUrl unitUrl = url();
if (!unitUrl.isLocalFile()) {
*errorString = QStringLiteral("File has to be a local file.");
@@ -330,20 +350,56 @@ bool CompilationUnit::saveToDisk(QString *errorString)
return true;
}
-bool CompilationUnit::loadFromDisk(const QUrl &url, QString *errorString)
+bool CompilationUnit::loadFromDisk(const QUrl &url, EvalISelFactory *iselFactory, QString *errorString)
{
if (!url.isLocalFile()) {
*errorString = QStringLiteral("File has to be a local file.");
return false;
}
- QScopedPointer<QFile> cacheFile(new QFile(url.toLocalFile() + QLatin1Char('c')));
+ const QString sourcePath = url.toLocalFile();
+ QScopedPointer<QFile> cacheFile(new QFile(sourcePath + QLatin1Char('c')));
if (!cacheFile->open(QIODevice::ReadOnly)) {
*errorString = cacheFile->errorString();
return false;
}
+ {
+ CompiledData::Unit header;
+ qint64 bytesRead = cacheFile->read(reinterpret_cast<char *>(&header), sizeof(header));
+
+ if (bytesRead != sizeof(header)) {
+ *errorString = QStringLiteral("File too small for the header fields");
+ return false;
+ }
+
+ if (strncmp(header.magic, CompiledData::magic_str, sizeof(header.magic))) {
+ *errorString = QStringLiteral("Magic bytes in the header do not match");
+ return false;
+ }
+
+ if (header.version != quint32(QV4_DATA_STRUCTURE_VERSION)) {
+ *errorString = QString::fromUtf8("V4 data structure version mismatch. Found %1 expected %2").arg(header.version, 0, 16).arg(QV4_DATA_STRUCTURE_VERSION, 0, 16);
+ return false;
+ }
+
+ if (header.qtVersion != quint32(QT_VERSION)) {
+ *errorString = QString::fromUtf8("Qt version mismatch. Found %1 expected %2").arg(header.qtVersion, 0, 16).arg(QT_VERSION, 0, 16);
+ return false;
+ }
+
+ {
+ QFileInfo sourceCode(sourcePath);
+ if (sourceCode.exists() && sourceCode.lastModified().toMSecsSinceEpoch() != header.sourceTimeStamp) {
+ *errorString = QStringLiteral("QML source file has a different time stamp than cached file.");
+ return false;
+ }
+ }
+
+ }
+ // Data structure and qt version matched, so now we can access the rest of the file safely.
+
uchar *cacheData = cacheFile->map(/*offset*/0, cacheFile->size());
if (!cacheData) {
*errorString = cacheFile->errorString();
@@ -353,13 +409,22 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, QString *errorString)
QScopedValueRollback<const Unit *> dataPtrChange(data, reinterpret_cast<const Unit *>(cacheData));
{
- QFileInfo sourceCode(url.toLocalFile());
- if (sourceCode.exists() && sourceCode.lastModified().toMSecsSinceEpoch() != data->sourceTimeStamp) {
- *errorString = QStringLiteral("QML source file has a different time stamp than cached file.");
+ const QString foundArchitecture = stringAt(data->architectureIndex);
+ const QString expectedArchitecture = QSysInfo::buildAbi();
+ if (foundArchitecture != expectedArchitecture) {
+ *errorString = QString::fromUtf8("Architecture mismatch. Found %1 expected %2").arg(foundArchitecture).arg(expectedArchitecture);
return false;
}
}
+ {
+ const QString foundCodeGenerator = stringAt(data->codeGeneratorIndex);
+ const QString expectedCodeGenerator = iselFactory->codeGeneratorName;
+ if (foundCodeGenerator != expectedCodeGenerator) {
+ *errorString = QString::fromUtf8("Code generator mismatch. Found code generated by %1 but expected %2").arg(foundCodeGenerator).arg(expectedCodeGenerator);
+ return false;
+ }
+ }
if (!memoryMapCode(errorString))
return false;
@@ -489,7 +554,7 @@ QString Binding::valueAsScriptString(const Unit *unit) const
/*!
Returns the property cache, if one alread exists. The cache is not referenced.
*/
-QQmlPropertyCache *CompilationUnit::ResolvedTypeReference::propertyCache() const
+QQmlPropertyCache *ResolvedTypeReference::propertyCache() const
{
if (type)
return typePropertyCache;
@@ -500,7 +565,7 @@ QQmlPropertyCache *CompilationUnit::ResolvedTypeReference::propertyCache() const
/*!
Returns the property cache, creating one if it doesn't already exist. The cache is not referenced.
*/
-QQmlPropertyCache *CompilationUnit::ResolvedTypeReference::createPropertyCache(QQmlEngine *engine)
+QQmlPropertyCache *ResolvedTypeReference::createPropertyCache(QQmlEngine *engine)
{
if (typePropertyCache) {
return typePropertyCache;
@@ -522,7 +587,7 @@ bool qtTypeInherits(const QMetaObject *mo) {
return false;
}
-void CompilationUnit::ResolvedTypeReference::doDynamicTypeCheck()
+void ResolvedTypeReference::doDynamicTypeCheck()
{
const QMetaObject *mo = 0;
if (typePropertyCache)
@@ -533,6 +598,19 @@ void CompilationUnit::ResolvedTypeReference::doDynamicTypeCheck()
mo = compilationUnit->rootPropertyCache()->firstCppMetaObject();
isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
}
+
+bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *engine) const
+{
+ for (auto it = constBegin(), end = constEnd(); it != end; ++it) {
+ QQmlPropertyCache *pc = it.value()->createPropertyCache(engine);
+ bool ok = false;
+ hash->addData(pc->checksum(&ok));
+ if (!ok)
+ return false;
+ }
+ return true;
+}
+
#endif
}
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 20b68026e9..1f253e02fd 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -70,6 +70,9 @@
QT_BEGIN_NAMESPACE
+// Bump this whenever the compiler data structures change in an incompatible way.
+#define QV4_DATA_STRUCTURE_VERSION 0x01
+
class QIODevice;
class QQmlPropertyCache;
class QQmlPropertyData;
@@ -88,6 +91,7 @@ struct Function;
}
struct Function;
+class EvalISelFactory;
namespace CompiledData {
@@ -597,11 +601,17 @@ static const char magic_str[] = "qv4cdata";
struct Unit
{
+ // DO NOT CHANGE THESE FIELDS EVER
char magic[8];
- LEInt16 architecture;
- LEInt16 version;
+ LEUInt32 version;
+ LEUInt32 qtVersion;
LEInt64 sourceTimeStamp;
LEUInt32 unitSize; // Size of the Unit and any depending data.
+ // END DO NOT CHANGE THESE FIELDS EVER
+
+ LEUInt32 architectureIndex; // string index to QSysInfo::buildAbi()
+ LEUInt32 codeGeneratorIndex;
+ char dependencyMD5Checksum[16];
enum : unsigned int {
IsJavascript = 0x1,
@@ -681,8 +691,8 @@ struct Unit
const RegExp *regexpAt(int index) const {
return reinterpret_cast<const RegExp*>(reinterpret_cast<const char *>(this) + offsetToRegexpTable + index * sizeof(RegExp));
}
- const QV4::Value *constants() const {
- return reinterpret_cast<const QV4::Value*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
+ const LEUInt64 *constants() const {
+ return reinterpret_cast<const LEUInt64*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
}
const JSClassMember *jsClassAt(int idx, int *nMembers) const {
@@ -753,6 +763,42 @@ struct TypeReferenceMap : QHash<int, TypeReference>
}
};
+#ifndef V4_BOOTSTRAP
+struct ResolvedTypeReference
+{
+ ResolvedTypeReference()
+ : type(0)
+ , majorVersion(0)
+ , minorVersion(0)
+ , isFullyDynamicType(false)
+ {}
+
+ QQmlType *type;
+ QQmlRefPointer<QQmlPropertyCache> typePropertyCache;
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
+
+ int majorVersion;
+ int minorVersion;
+ // Types such as QQmlPropertyMap can add properties dynamically at run-time and
+ // therefore cannot have a property cache installed when instantiated.
+ bool isFullyDynamicType;
+
+ QQmlPropertyCache *propertyCache() const;
+ QQmlPropertyCache *createPropertyCache(QQmlEngine *);
+
+ void doDynamicTypeCheck();
+};
+// map from name index
+// While this could be a hash, a map is chosen here to provide a stable
+// order, which is used to calculating a check-sum on dependent meta-objects.
+struct ResolvedTypeReferenceMap: public QMap<int, ResolvedTypeReference*>
+{
+ bool addToHash(QCryptographicHash *hash, QQmlEngine *engine) const;
+};
+#else
+struct ResolvedTypeReferenceMap {};
+#endif
+
// index is per-object binding index
typedef QVector<QQmlPropertyData*> BindingPropertyData;
@@ -807,6 +853,9 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
QHash<int, IdentifierHash<int>> namedObjectsPerComponentCache;
IdentifierHash<int> namedObjectsPerComponent(int componentObjectIndex);
+ // pointers either to data->constants() or little-endian memory copy.
+ const Value* constants;
+
void finalize(QQmlEnginePrivate *engine);
int totalBindingsCount; // Number of bindings used in this type
@@ -814,33 +863,6 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
int totalObjectCount; // Number of objects explicitly instantiated
QVector<QQmlScriptData *> dependentScripts;
-
- struct ResolvedTypeReference
- {
- ResolvedTypeReference()
- : type(0)
- , majorVersion(0)
- , minorVersion(0)
- , isFullyDynamicType(false)
- {}
-
- QQmlType *type;
- QQmlRefPointer<QQmlPropertyCache> typePropertyCache;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
-
- int majorVersion;
- int minorVersion;
- // Types such as QQmlPropertyMap can add properties dynamically at run-time and
- // therefore cannot have a property cache installed when instantiated.
- bool isFullyDynamicType;
-
- QQmlPropertyCache *propertyCache() const;
- QQmlPropertyCache *createPropertyCache(QQmlEngine *);
-
- void doDynamicTypeCheck();
- };
- // map from name index
- typedef QHash<int, ResolvedTypeReference*> ResolvedTypeReferenceMap;
ResolvedTypeReferenceMap resolvedTypes;
int metaTypeId;
@@ -880,7 +902,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
void destroy() Q_DECL_OVERRIDE;
bool saveToDisk(QString *errorString);
- bool loadFromDisk(const QUrl &url, QString *errorString);
+ bool loadFromDisk(const QUrl &url, EvalISelFactory *iselFactory, QString *errorString);
protected:
virtual void linkBackendToEngine(QV4::ExecutionEngine *engine) = 0;
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index 5d13734247..50ade2c6e5 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -43,6 +43,7 @@
#include <private/qv4string_p.h>
#include <private/qv4value_p.h>
#include <private/qv4alloca_p.h>
+#include <wtf/MathExtras.h>
QV4::Compiler::StringTableGenerator::StringTableGenerator()
{
@@ -247,8 +248,14 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorO
CompiledData::RegExp *regexpTable = reinterpret_cast<CompiledData::RegExp *>(dataPtr + unit->offsetToRegexpTable);
memcpy(regexpTable, regexps.constData(), regexps.size() * sizeof(*regexpTable));
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
ReturnedValue *constantTable = reinterpret_cast<ReturnedValue *>(dataPtr + unit->offsetToConstantTable);
memcpy(constantTable, constants.constData(), constants.size() * sizeof(ReturnedValue));
+#else
+ CompiledData::LEUInt64 *constantTable = reinterpret_cast<CompiledData::LEUInt64 *>(dataPtr + unit->offsetToConstantTable);
+ for (int i = 0; i < constants.count(); ++i)
+ constantTable[i] = constants.at(i);
+#endif
{
memcpy(dataPtr + jsClassDataOffset, jsClassData.constData(), jsClassData.size());
@@ -352,17 +359,20 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::IR::Function *i
}
}
-QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Compiler::JSUnitGenerator::GeneratorOption option, QJsonPrivate::q_littleendian<quint32> *functionOffsets, uint *jsClassDataOffset) const
+QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Compiler::JSUnitGenerator::GeneratorOption option, QJsonPrivate::q_littleendian<quint32> *functionOffsets, uint *jsClassDataOffset)
{
CompiledData::Unit unit;
memcpy(unit.magic, CompiledData::magic_str, sizeof(unit.magic));
- unit.architecture = 0; // ###
unit.flags = QV4::CompiledData::Unit::IsJavascript;
- unit.version = 1;
- unit.functionTableSize = irModule->functions.size();
+ unit.version = QV4_DATA_STRUCTURE_VERSION;
+ unit.qtVersion = QT_VERSION;
+ unit.architectureIndex = registerString(QSysInfo::buildAbi());
+ unit.codeGeneratorIndex = registerString(codeGeneratorName);
+ memset(unit.dependencyMD5Checksum, 0, sizeof(unit.dependencyMD5Checksum));
quint32 nextOffset = sizeof(CompiledData::Unit);
+ unit.functionTableSize = irModule->functions.size();
unit.offsetToFunctionTable = nextOffset;
nextOffset += unit.functionTableSize * sizeof(uint);
@@ -375,6 +385,9 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp
nextOffset += unit.regexpTableSize * sizeof(CompiledData::RegExp);
unit.constantTableSize = constants.size();
+
+ // Ensure we load constants from well-aligned addresses into for example SSE registers.
+ nextOffset = static_cast<quint32>(WTF::roundUpToMultipleOf(16, nextOffset));
unit.offsetToConstantTable = nextOffset;
nextOffset += unit.constantTableSize * sizeof(ReturnedValue);
diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h
index 4b67fe8600..49b8664513 100644
--- a/src/qml/compiler/qv4compiler_p.h
+++ b/src/qml/compiler/qv4compiler_p.h
@@ -118,8 +118,9 @@ struct Q_QML_PRIVATE_EXPORT JSUnitGenerator {
void writeFunction(char *f, IR::Function *irFunction) const;
StringTableGenerator stringTable;
+ QString codeGeneratorName;
private:
- CompiledData::Unit generateHeader(GeneratorOption option, QJsonPrivate::q_littleendian<quint32> *functionOffsets, uint *jsClassDataOffset) const;
+ CompiledData::Unit generateHeader(GeneratorOption option, QJsonPrivate::q_littleendian<quint32> *functionOffsets, uint *jsClassDataOffset);
IR::Module *irModule;
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index e95a7f7046..20b871c4e8 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -58,10 +58,17 @@
QT_BEGIN_NAMESPACE
+#ifdef QT_NO_QML_DEBUGGER
+#define MOTH_DEBUG_INSTR(F)
+#else
+#define MOTH_DEBUG_INSTR(F) \
+ F(Line, line) \
+ F(Debug, debug)
+#endif
+
#define FOR_EACH_MOTH_INSTR(F) \
F(Ret, ret) \
- F(Line, line) \
- F(Debug, debug) \
+ MOTH_DEBUG_INSTR(F) \
F(LoadRuntimeString, loadRuntimeString) \
F(LoadRegExp, loadRegExp) \
F(LoadClosure, loadClosure) \
@@ -174,6 +181,8 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
namespace Moth {
+ // When making changes to the instructions, make sure to bump QV4_DATA_STRUCTURE_VERSION in qv4compileddata_p.h
+
struct Param {
// Params are looked up as follows:
// Constant: 0
@@ -252,6 +261,8 @@ union Instr
MOTH_INSTR_HEADER
Param result;
};
+
+#ifndef QT_NO_QML_DEBUGGING
struct instr_line {
MOTH_INSTR_HEADER
qint32 lineNumber;
@@ -260,6 +271,8 @@ union Instr
MOTH_INSTR_HEADER
qint32 lineNumber;
};
+#endif // QT_NO_QML_DEBUGGING
+
struct instr_loadRuntimeString {
MOTH_INSTR_HEADER
int stringId;
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index 283948727b..41790c04a9 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -313,8 +313,8 @@ protected:
};
} // anonymous namespace
-InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
- : EvalInstructionSelection(execAllocator, module, jsGenerator)
+InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator, EvalISelFactory *iselFactory)
+ : EvalInstructionSelection(execAllocator, module, jsGenerator, iselFactory)
, qmlEngine(qmlEngine)
, _block(0)
, _codeStart(0)
@@ -412,6 +412,7 @@ void InstructionSelection::run(int functionIndex)
if (s->location.startLine != currentLine) {
blockNeedsDebugInstruction = false;
currentLine = s->location.startLine;
+#ifndef QT_NO_QML_DEBUGGER
if (irModule->debugMode) {
Instruction::Debug debug;
debug.lineNumber = currentLine;
@@ -421,6 +422,7 @@ void InstructionSelection::run(int functionIndex)
line.lineNumber = currentLine;
addInstruction(line);
}
+#endif
}
}
@@ -1092,6 +1094,17 @@ void InstructionSelection::prepareCallArgs(IR::ExprList *e, quint32 &argc, quint
}
}
+void InstructionSelection::addDebugInstruction()
+{
+#ifndef QT_NO_QML_DEBUGGER
+ if (blockNeedsDebugInstruction) {
+ Instruction::Debug debug;
+ debug.lineNumber = -int(currentLine);
+ addInstruction(debug);
+ }
+#endif
+}
+
void InstructionSelection::visitJump(IR::Jump *s)
{
if (s->target == _nextBlock)
@@ -1099,11 +1112,7 @@ void InstructionSelection::visitJump(IR::Jump *s)
if (_removableJumps.contains(s))
return;
- if (blockNeedsDebugInstruction) {
- Instruction::Debug debug;
- debug.lineNumber = -int(currentLine);
- addInstruction(debug);
- }
+ addDebugInstruction();
Instruction::Jump jump;
jump.offset = 0;
@@ -1114,11 +1123,7 @@ void InstructionSelection::visitJump(IR::Jump *s)
void InstructionSelection::visitCJump(IR::CJump *s)
{
- if (blockNeedsDebugInstruction) {
- Instruction::Debug debug;
- debug.lineNumber = -int(currentLine);
- addInstruction(debug);
- }
+ addDebugInstruction();
Param condition;
if (IR::Temp *t = s->cond->asTemp()) {
@@ -1153,12 +1158,8 @@ void InstructionSelection::visitCJump(IR::CJump *s)
void InstructionSelection::visitRet(IR::Ret *s)
{
- if (blockNeedsDebugInstruction) {
- // this is required so stepOut will always be guaranteed to stop in every stack frame
- Instruction::Debug debug;
- debug.lineNumber = -int(currentLine);
- addInstruction(debug);
- }
+ // this is required so stepOut will always be guaranteed to stop in every stack frame
+ addDebugInstruction();
Instruction::Ret ret;
ret.result = getParam(s->expr);
diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h
index eaca299c94..2d2bb91228 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -80,7 +80,7 @@ class Q_QML_EXPORT InstructionSelection:
public EvalInstructionSelection
{
public:
- InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator);
+ InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator, EvalISelFactory *iselFactory);
~InstructionSelection();
virtual void run(int functionIndex);
@@ -177,6 +177,8 @@ private:
template <int Instr>
inline ptrdiff_t addInstruction(const InstrData<Instr> &data);
+ inline void addDebugInstruction();
+
ptrdiff_t addInstructionHelper(Instr::Type type, Instr &instr);
void patchJumpAddresses();
QByteArray squeezeCode() const;
@@ -205,10 +207,11 @@ private:
class Q_QML_EXPORT ISelFactory: public EvalISelFactory
{
public:
+ ISelFactory() : EvalISelFactory(QStringLiteral("moth")) {}
virtual ~ISelFactory() {}
- virtual EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
- { return new InstructionSelection(qmlEngine, execAllocator, module, jsGenerator); }
- virtual bool jitCompileRegexps() const
+ EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator) Q_DECL_OVERRIDE Q_DECL_FINAL
+ { return new InstructionSelection(qmlEngine, execAllocator, module, jsGenerator, this); }
+ bool jitCompileRegexps() const Q_DECL_OVERRIDE Q_DECL_FINAL
{ return false; }
QQmlRefPointer<QV4::CompiledData::CompilationUnit> createUnitForLoading() Q_DECL_OVERRIDE;
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index 0ae08160ab..d97eec5e1d 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -52,7 +52,7 @@
using namespace QV4;
using namespace QV4::IR;
-EvalInstructionSelection::EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
+EvalInstructionSelection::EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator, EvalISelFactory *iselFactory)
: useFastLookups(true)
, useTypeInference(true)
, executableAllocator(execAllocator)
@@ -67,6 +67,7 @@ EvalInstructionSelection::EvalInstructionSelection(QV4::ExecutableAllocator *exe
Q_ASSERT(execAllocator);
#endif
Q_ASSERT(module);
+ jsGenerator->codeGeneratorName = iselFactory->codeGeneratorName;
}
EvalInstructionSelection::~EvalInstructionSelection()
diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h
index d93c0893ae..a3fa80b6f0 100644
--- a/src/qml/compiler/qv4isel_p.h
+++ b/src/qml/compiler/qv4isel_p.h
@@ -65,13 +65,14 @@ class QQmlEnginePrivate;
namespace QV4 {
+class EvalISelFactory;
class ExecutableAllocator;
struct Function;
class Q_QML_PRIVATE_EXPORT EvalInstructionSelection
{
public:
- EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator);
+ EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator, EvalISelFactory *iselFactory);
virtual ~EvalInstructionSelection() = 0;
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compile(bool generateUnitData = true);
@@ -104,10 +105,13 @@ protected:
class Q_QML_PRIVATE_EXPORT EvalISelFactory
{
public:
+ EvalISelFactory(const QString &codeGeneratorName) : codeGeneratorName(codeGeneratorName) {}
virtual ~EvalISelFactory() = 0;
virtual EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator) = 0;
virtual bool jitCompileRegexps() const = 0;
virtual QQmlRefPointer<QV4::CompiledData::CompilationUnit> createUnitForLoading() = 0;
+
+ const QString codeGeneratorName;
};
namespace IR {
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index de84accbb1..51b8797862 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -934,7 +934,11 @@ struct Q_QML_PRIVATE_EXPORT Module {
QString fileName;
qint64 sourceTimeStamp;
bool isQmlModule; // implies rootFunction is always 0
+#ifdef QT_NO_QML_DEBUGGER
+ static const bool debugMode = false;
+#else
bool debugMode;
+#endif
Function *newFunction(const QString &name, Function *outer);
@@ -942,8 +946,12 @@ struct Q_QML_PRIVATE_EXPORT Module {
: rootFunction(0)
, sourceTimeStamp(0)
, isQmlModule(false)
+#ifndef QT_NO_QML_DEBUGGER
, debugMode(debugMode)
{}
+#else
+ { Q_UNUSED(debugMode); }
+#endif
~Module();
void setFileName(const QString &name);
diff --git a/src/qml/debugger/debugger.pri b/src/qml/debugger/debugger.pri
index 30a44eedd1..da1ab867d4 100644
--- a/src/qml/debugger/debugger.pri
+++ b/src/qml/debugger/debugger.pri
@@ -1,21 +1,28 @@
-contains(QT_CONFIG, no-qml-debug):DEFINES += QT_NO_QML_DEBUGGER
+contains(QT_CONFIG, no-qml-debug) {
+ DEFINES += QT_NO_QML_DEBUGGER
+ MODULE_DEFINES += QT_NO_QML_DEBUGGER
+} else {
+ HEADERS += \
+ $$PWD/qqmldebugpluginmanager_p.h \
+ $$PWD/qqmldebugservicefactory_p.h
-SOURCES += \
- $$PWD/qqmldebug.cpp \
- $$PWD/qqmldebugconnector.cpp \
- $$PWD/qqmldebugservice.cpp \
- $$PWD/qqmldebugserviceinterfaces.cpp \
- $$PWD/qqmlabstractprofileradapter.cpp \
- $$PWD/qqmlprofiler.cpp
+ SOURCES += \
+ $$PWD/qqmldebug.cpp \
+ $$PWD/qqmldebugconnector.cpp \
+ $$PWD/qqmldebugservice.cpp \
+ $$PWD/qqmlabstractprofileradapter.cpp \
+ $$PWD/qqmlmemoryprofiler.cpp \
+ $$PWD/qqmlprofiler.cpp \
+ $$PWD/qqmldebugserviceinterfaces.cpp
+}
HEADERS += \
$$PWD/qqmldebugconnector_p.h \
- $$PWD/qqmldebugpluginmanager_p.h \
$$PWD/qqmldebugservice_p.h \
- $$PWD/qqmldebugservicefactory_p.h \
$$PWD/qqmldebugserviceinterfaces_p.h \
$$PWD/qqmldebugstatesdelegate_p.h \
$$PWD/qqmldebug.h \
+ $$PWD/qqmlmemoryprofiler_p.h \
$$PWD/qqmlprofilerdefinitions_p.h \
$$PWD/qqmlabstractprofileradapter_p.h \
$$PWD/qqmlprofiler_p.h
diff --git a/src/qml/debugger/qqmlabstractprofileradapter_p.h b/src/qml/debugger/qqmlabstractprofileradapter_p.h
index 8820c4311a..6a05a80f37 100644
--- a/src/qml/debugger/qqmlabstractprofileradapter_p.h
+++ b/src/qml/debugger/qqmlabstractprofileradapter_p.h
@@ -59,6 +59,8 @@
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_QML_DEBUGGER
+
class QQmlProfilerService;
class Q_QML_PRIVATE_EXPORT QQmlAbstractProfilerAdapter : public QObject, public QQmlProfilerDefinitions {
Q_OBJECT
@@ -114,6 +116,8 @@ public:
#define QQmlAbstractProfilerAdapterFactory_iid "org.qt-project.Qt.QQmlAbstractProfilerAdapterFactory"
+#endif // QT_NO_QML_DEBUGGER
+
QT_END_NAMESPACE
#endif // QQMLABSTRACTPROFILERADAPTER_P_H
diff --git a/src/qml/debugger/qqmldebug.cpp b/src/qml/debugger/qqmldebug.cpp
index 9276bd0544..386fb60b3a 100644
--- a/src/qml/debugger/qqmldebug.cpp
+++ b/src/qml/debugger/qqmldebug.cpp
@@ -47,15 +47,11 @@ 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
}
/*!
@@ -105,11 +101,7 @@ QStringList QQmlDebuggingEnabler::profilerServices()
*/
void QQmlDebuggingEnabler::setServices(const QStringList &services)
{
-#ifndef QQML_NO_DEBUG_PROTOCOL
QQmlDebugConnector::setServices(services);
-#else
- Q_UNUSED(services);
-#endif
}
/*!
@@ -172,16 +164,9 @@ bool QQmlDebuggingEnabler::connectToLocalDebugger(const QString &socketFileName,
bool QQmlDebuggingEnabler::startDebugConnector(const QString &pluginName,
const QVariantHash &configuration)
{
-#ifndef QQML_NO_DEBUG_PROTOCOL
QQmlDebugConnector::setPluginKey(pluginName);
QQmlDebugConnector *connector = QQmlDebugConnector::instance();
- if (connector)
- return connector->open(configuration);
-#else
- Q_UNUSED(pluginName);
- Q_UNUSED(configuration);
-#endif
- return false;
+ return connector ? connector->open(configuration) : false;
}
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmldebug.h b/src/qml/debugger/qqmldebug.h
index 660b9e4d46..fb41039867 100644
--- a/src/qml/debugger/qqmldebug.h
+++ b/src/qml/debugger/qqmldebug.h
@@ -46,6 +46,7 @@
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_QML_DEBUGGER
struct Q_QML_EXPORT QQmlDebuggingEnabler
{
@@ -77,6 +78,8 @@ static QQmlDebuggingEnabler qQmlEnableDebuggingHelper(false);
static QQmlDebuggingEnabler qQmlEnableDebuggingHelper(true);
#endif
+#endif
+
QT_END_NAMESPACE
#endif // QQMLDEBUG_H
diff --git a/src/qml/debugger/qqmldebugconnector_p.h b/src/qml/debugger/qqmldebugconnector_p.h
index 05755250bd..0d3e2e2e47 100644
--- a/src/qml/debugger/qqmldebugconnector_p.h
+++ b/src/qml/debugger/qqmldebugconnector_p.h
@@ -59,6 +59,29 @@
QT_BEGIN_NAMESPACE
+#ifdef QT_NO_QML_DEBUGGER
+
+class Q_QML_PRIVATE_EXPORT QQmlDebugConnector
+{
+public:
+ static QQmlDebugConnector *instance() { return nullptr; }
+
+ template<class Service>
+ static Service *service() { return nullptr; }
+
+ bool hasEngine(QJSEngine *) const { return false; }
+ void addEngine(QJSEngine *) {}
+ void removeEngine(QJSEngine *) {}
+
+ bool open(const QVariantHash &configuration = QVariantHash())
+ {
+ Q_UNUSED(configuration);
+ return false;
+ }
+};
+
+#else
+
class QQmlDebugService;
class Q_QML_PRIVATE_EXPORT QQmlDebugConnector : public QObject
{
@@ -106,6 +129,8 @@ public:
#define QQmlDebugConnectorFactory_iid "org.qt-project.Qt.QQmlDebugConnectorFactory"
+#endif
+
QT_END_NAMESPACE
#endif // QQMLDEBUGCONNECTOR_H
diff --git a/src/qml/debugger/qqmldebugservice.cpp b/src/qml/debugger/qqmldebugservice.cpp
index b780735f48..b576c3bb85 100644
--- a/src/qml/debugger/qqmldebugservice.cpp
+++ b/src/qml/debugger/qqmldebugservice.cpp
@@ -132,7 +132,6 @@ public:
int nextId;
-private slots:
void remove(QObject *obj);
};
}
@@ -163,7 +162,7 @@ int QQmlDebugService::idForObject(QObject *object)
int id = hash->nextId++;
hash->ids.insert(id, object);
iter = hash->objects.insert(object, id);
- connect(object, SIGNAL(destroyed(QObject*)), hash, SLOT(remove(QObject*)));
+ connect(object, &QObject::destroyed, hash, &ObjectReferenceHash::remove);
}
return iter.value();
}
@@ -176,36 +175,6 @@ const QHash<int, QObject *> &QQmlDebugService::objectsForIds()
return objectReferenceHash()->ids;
}
-void QQmlDebugService::stateAboutToBeChanged(State)
-{
-}
-
-void QQmlDebugService::stateChanged(State)
-{
-}
-
-void QQmlDebugService::messageReceived(const QByteArray &)
-{
-}
-
-void QQmlDebugService::engineAboutToBeAdded(QJSEngine *engine)
-{
- emit attachedToEngine(engine);
-}
-
-void QQmlDebugService::engineAboutToBeRemoved(QJSEngine *engine)
-{
- emit detachedFromEngine(engine);
-}
-
-void QQmlDebugService::engineAdded(QJSEngine *)
-{
-}
-
-void QQmlDebugService::engineRemoved(QJSEngine *)
-{
-}
-
QT_END_NAMESPACE
#include "qqmldebugservice.moc"
diff --git a/src/qml/debugger/qqmldebugservice_p.h b/src/qml/debugger/qqmldebugservice_p.h
index 9ddc692ecc..42a57a39f2 100644
--- a/src/qml/debugger/qqmldebugservice_p.h
+++ b/src/qml/debugger/qqmldebugservice_p.h
@@ -58,6 +58,8 @@
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_QML_DEBUGGER
+
class QJSEngine;
class QQmlDebugServicePrivate;
@@ -65,7 +67,6 @@ class Q_QML_PRIVATE_EXPORT QQmlDebugService : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QQmlDebugService)
- Q_DISABLE_COPY(QQmlDebugService)
public:
~QQmlDebugService();
@@ -77,14 +78,15 @@ public:
State state() const;
void setState(State newState);
- virtual void stateAboutToBeChanged(State);
- virtual void stateChanged(State);
- virtual void messageReceived(const QByteArray &);
+ virtual void stateAboutToBeChanged(State) {}
+ virtual void stateChanged(State) {}
+ virtual void messageReceived(const QByteArray &) {}
+
+ virtual void engineAboutToBeAdded(QJSEngine *engine) { emit attachedToEngine(engine); }
+ virtual void engineAboutToBeRemoved(QJSEngine *engine) { emit detachedFromEngine(engine); }
- virtual void engineAboutToBeAdded(QJSEngine *);
- virtual void engineAboutToBeRemoved(QJSEngine *);
- virtual void engineAdded(QJSEngine *);
- virtual void engineRemoved(QJSEngine *);
+ virtual void engineAdded(QJSEngine *) {}
+ virtual void engineRemoved(QJSEngine *) {}
static const QHash<int, QObject *> &objectsForIds();
static int idForObject(QObject *);
@@ -101,6 +103,8 @@ signals:
void messagesToClient(const QString &name, const QList<QByteArray> &messages);
};
+#endif
+
QT_END_NAMESPACE
#endif // QQMLDEBUGSERVICE_H
diff --git a/src/qml/debugger/qqmldebugserviceinterfaces_p.h b/src/qml/debugger/qqmldebugserviceinterfaces_p.h
index 8f66779872..ca6293c3ec 100644
--- a/src/qml/debugger/qqmldebugserviceinterfaces_p.h
+++ b/src/qml/debugger/qqmldebugserviceinterfaces_p.h
@@ -62,7 +62,46 @@
QT_BEGIN_NAMESPACE
-class Q_QML_PRIVATE_EXPORT QV4DebugService : protected QQmlDebugService
+class QWindow;
+class QQuickWindow;
+
+#ifdef QT_NO_QML_DEBUGGER
+
+struct QV4DebugService
+{
+ void signalEmitted(const QString &) {}
+};
+
+struct QQmlProfilerService
+{
+ void startProfiling(QJSEngine *engine, quint64 features = std::numeric_limits<quint64>::max())
+ {
+ Q_UNUSED(engine);
+ Q_UNUSED(features);
+ }
+
+ void stopProfiling(QJSEngine *) {}
+};
+
+struct QQmlEngineDebugService
+{
+ void objectCreated(QJSEngine *, QObject *) {}
+ virtual void setStatesDelegate(QQmlDebugStatesDelegate *) {}
+};
+
+struct QQmlInspectorService {
+ void addWindow(QQuickWindow *) {}
+ void setParentWindow(QQuickWindow *, QWindow *) {}
+ void removeWindow(QQuickWindow *) {}
+};
+
+struct QDebugMessageService {};
+struct QQmlEngineControlService {};
+struct QQmlNativeDebugService {};
+
+#else
+
+class Q_QML_PRIVATE_EXPORT QV4DebugService : public QQmlDebugService
{
Q_OBJECT
public:
@@ -77,7 +116,7 @@ protected:
QQmlDebugService(s_key, version, parent) {}
};
-class Q_QML_PRIVATE_EXPORT QQmlProfilerService : protected QQmlDebugService
+class Q_QML_PRIVATE_EXPORT QQmlProfilerService : public QQmlDebugService
{
Q_OBJECT
public:
@@ -99,7 +138,7 @@ protected:
QQmlDebugService(s_key, version, parent) {}
};
-class Q_QML_PRIVATE_EXPORT QQmlEngineDebugService : protected QQmlDebugService
+class Q_QML_PRIVATE_EXPORT QQmlEngineDebugService : public QQmlDebugService
{
Q_OBJECT
public:
@@ -117,9 +156,7 @@ protected:
QQmlBoundSignal *nextSignal(QQmlBoundSignal *prev) { return prev->m_nextSignal; }
};
-class QWindow;
-class QQuickWindow;
-class Q_QML_PRIVATE_EXPORT QQmlInspectorService : protected QQmlDebugService
+class Q_QML_PRIVATE_EXPORT QQmlInspectorService : public QQmlDebugService
{
Q_OBJECT
public:
@@ -136,7 +173,7 @@ protected:
QQmlDebugService(s_key, version, parent) {}
};
-class Q_QML_PRIVATE_EXPORT QDebugMessageService : protected QQmlDebugService
+class Q_QML_PRIVATE_EXPORT QDebugMessageService : public QQmlDebugService
{
Q_OBJECT
public:
@@ -151,7 +188,7 @@ protected:
QQmlDebugService(s_key, version, parent) {}
};
-class Q_QML_PRIVATE_EXPORT QQmlEngineControlService : protected QQmlDebugService
+class Q_QML_PRIVATE_EXPORT QQmlEngineControlService : public QQmlDebugService
{
Q_OBJECT
public:
@@ -165,7 +202,7 @@ protected:
};
-class Q_QML_PRIVATE_EXPORT QQmlNativeDebugService : protected QQmlDebugService
+class Q_QML_PRIVATE_EXPORT QQmlNativeDebugService : public QQmlDebugService
{
Q_OBJECT
@@ -178,6 +215,8 @@ protected:
static const QString s_key;
};
+#endif
+
QT_END_NAMESPACE
#endif // QQMLDEBUGSERVICEINTERFACES_P_H
diff --git a/src/qml/debugger/qqmldebugstatesdelegate_p.h b/src/qml/debugger/qqmldebugstatesdelegate_p.h
index 42c4e94b50..95f727fb2d 100644
--- a/src/qml/debugger/qqmldebugstatesdelegate_p.h
+++ b/src/qml/debugger/qqmldebugstatesdelegate_p.h
@@ -57,6 +57,11 @@
QT_BEGIN_NAMESPACE
+#ifdef QT_NO_QML_DEBUGGER
+
+class QQmlDebugStatesDelegate {};
+
+#else
class QQmlContext;
class QQmlProperty;
@@ -90,6 +95,8 @@ private:
Q_DISABLE_COPY(QQmlDebugStatesDelegate)
};
+#endif
+
QT_END_NAMESPACE
#endif // QQMLDEBUGSTATESDELEGATE_P_H
diff --git a/src/qml/qml/qqmlmemoryprofiler.cpp b/src/qml/debugger/qqmlmemoryprofiler.cpp
index 60f6d96eaf..60f6d96eaf 100644
--- a/src/qml/qml/qqmlmemoryprofiler.cpp
+++ b/src/qml/debugger/qqmlmemoryprofiler.cpp
diff --git a/src/qml/qml/qqmlmemoryprofiler_p.h b/src/qml/debugger/qqmlmemoryprofiler_p.h
index 4b0ba823ba..59f08704ca 100644
--- a/src/qml/qml/qqmlmemoryprofiler_p.h
+++ b/src/qml/debugger/qqmlmemoryprofiler_p.h
@@ -55,6 +55,13 @@
QT_BEGIN_NAMESPACE
+#ifdef QT_NO_QML_DEBUGGER
+
+#define QML_MEMORY_SCOPE_URL(url)
+#define QML_MEMORY_SCOPE_STRING(s)
+
+#else
+
class QUrl;
class Q_QML_PRIVATE_EXPORT QQmlMemoryScope
@@ -83,5 +90,7 @@ public:
#define QML_MEMORY_SCOPE_URL(url) QQmlMemoryScope _qml_memory_scope(url)
#define QML_MEMORY_SCOPE_STRING(s) QQmlMemoryScope _qml_memory_scope(s)
+#endif
+
QT_END_NAMESPACE
#endif // QQMLMEMORYPROFILER_H
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
index 707901063c..6643695d11 100644
--- a/src/qml/debugger/qqmlprofiler_p.h
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -63,6 +63,54 @@
QT_BEGIN_NAMESPACE
+#ifdef QT_NO_QML_DEBUGGER
+
+#define Q_QML_PROFILE_IF_ENABLED(feature, profiler, Code)
+#define Q_QML_PROFILE(feature, profiler, Method)
+#define Q_QML_OC_PROFILE(member, Code)
+
+struct QQmlProfiler {};
+
+struct QQmlBindingProfiler
+{
+ QQmlBindingProfiler(quintptr, QQmlBinding *, QV4::FunctionObject *) {}
+};
+
+struct QQmlHandlingSignalProfiler
+{
+ QQmlHandlingSignalProfiler(quintptr, QQmlBoundSignalExpression *) {}
+};
+
+struct QQmlCompilingProfiler
+{
+ QQmlCompilingProfiler(quintptr, QQmlDataBlob *) {}
+};
+
+struct QQmlVmeProfiler {
+ QQmlVmeProfiler() {}
+
+ void init(quintptr, int) {}
+
+ const QV4::CompiledData::Object *pop() { return nullptr; }
+ void push(const QV4::CompiledData::Object *) {}
+
+ static const quintptr profiler = 0;
+};
+
+struct QQmlObjectCreationProfiler
+{
+ QQmlObjectCreationProfiler(quintptr, const QV4::CompiledData::Object *) {}
+ void update(QV4::CompiledData::CompilationUnit *, const QV4::CompiledData::Object *,
+ const QString &, const QUrl &) {}
+};
+
+struct QQmlObjectCompletionProfiler
+{
+ QQmlObjectCompletionProfiler(QQmlVmeProfiler *) {}
+};
+
+#else
+
#define Q_QML_PROFILE_IF_ENABLED(feature, profiler, Code)\
if (profiler && (profiler->featuresEnabled & (1 << feature))) {\
Code;\
@@ -72,6 +120,9 @@ QT_BEGIN_NAMESPACE
#define Q_QML_PROFILE(feature, profiler, Method)\
Q_QML_PROFILE_IF_ENABLED(feature, profiler, profiler->Method)
+#define Q_QML_OC_PROFILE(member, Code)\
+ Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, member.profiler, Code)
+
// 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
@@ -94,7 +145,7 @@ struct Q_AUTOTEST_EXPORT QQmlProfilerData : public QQmlProfilerDefinitions
Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
-class QQmlProfiler : public QObject, public QQmlProfilerDefinitions {
+class Q_QML_PRIVATE_EXPORT QQmlProfiler : public QObject, public QQmlProfilerDefinitions {
Q_OBJECT
public:
@@ -250,7 +301,6 @@ public:
return reinterpret_cast<quintptr>(pointer);
}
-public slots:
void startProfiling(quint64 features);
void stopProfiling();
void reportData(bool trackLocations);
@@ -349,9 +399,6 @@ private:
QFiniteStack<const QV4::CompiledData::Object *> ranges;
};
-#define Q_QML_OC_PROFILE(member, Code)\
- Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, member.profiler, Code)
-
class QQmlObjectCreationProfiler {
public:
@@ -399,4 +446,6 @@ QT_END_NAMESPACE
Q_DECLARE_METATYPE(QVector<QQmlProfilerData>)
Q_DECLARE_METATYPE(QQmlProfiler::LocationHash)
+#endif // QT_NO_QML_DEBUGGER
+
#endif // QQMLPROFILER_P_H
diff --git a/src/qml/debugger/qqmlprofilerdefinitions_p.h b/src/qml/debugger/qqmlprofilerdefinitions_p.h
index 2b2eda22e1..c6ae4593a9 100644
--- a/src/qml/debugger/qqmlprofilerdefinitions_p.h
+++ b/src/qml/debugger/qqmlprofilerdefinitions_p.h
@@ -56,6 +56,8 @@
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_QML_DEBUGGER
+
struct QQmlProfilerDefinitions {
enum Message {
Event,
@@ -161,6 +163,8 @@ struct QQmlProfilerDefinitions {
};
};
+#endif // QT_NO_QML_DEBUGGER
+
QT_END_NAMESPACE
#endif
diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc
index 0d875bd10f..7bb4d701e2 100644
--- a/src/qml/doc/src/cppintegration/data.qdoc
+++ b/src/qml/doc/src/cppintegration/data.qdoc
@@ -381,6 +381,8 @@ Message {
}
\endqml
+To use an enum as a \l {QFlags}{flags} type in QML, see \l Q_FLAG().
+
\note The names of enum values must begin with a capital letter in order to
be accessible from QML.
diff --git a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
index 04d0d0ed2e..de0515e5d0 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
@@ -729,7 +729,7 @@ Rectangle {
MouseArea {
anchors.fill: parent
onPressed: root.activated(mouse.x, mouse.y)
- onRelased: root.deactivated()
+ onReleased: root.deactivated()
}
}
\endqml
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index 08e4f0a8c0..625f5b5e5a 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -148,8 +148,7 @@ bool CompilationUnit::memoryMapCode(QString *errorString)
const Assembler::VoidType Assembler::Void;
Assembler::Assembler(InstructionSelection *isel, IR::Function* function, QV4::ExecutableAllocator *executableAllocator)
- : _constTable(this)
- , _function(function)
+ : _function(function)
, _nextBlock(0)
, _executableAllocator(executableAllocator)
, _isel(isel)
@@ -279,6 +278,19 @@ Assembler::Pointer Assembler::loadStringAddress(RegisterID reg, const QString &s
return Pointer(reg, id * sizeof(QV4::String*));
}
+Assembler::Address Assembler::loadConstant(IR::Const *c, RegisterID baseReg)
+{
+ return loadConstant(convertToValue(c), baseReg);
+}
+
+Assembler::Address Assembler::loadConstant(const Primitive &v, RegisterID baseReg)
+{
+ loadPtr(Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), baseReg);
+ loadPtr(Address(baseReg, qOffsetOf(QV4::Heap::ExecutionContext, constantTable)), baseReg);
+ const int index = _isel->jsUnitGenerator()->registerConstant(v.asReturnedValue());
+ return Address(baseReg, index * sizeof(QV4::Value));
+}
+
void Assembler::loadStringRef(RegisterID reg, const QString &string)
{
const int id = _isel->registerString(string);
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index 748afbfba4..d76a21c74c 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -89,7 +89,6 @@ struct CompilationUnit : public QV4::CompiledData::CompilationUnit
// Coderef + execution engine
QVector<JSC::MacroAssemblerCodeRef> codeRefs;
- QList<QVector<QV4::Primitive> > constantValues;
};
struct LookupCall {
@@ -105,7 +104,7 @@ struct LookupCall {
struct RuntimeCall {
JSC::MacroAssembler::Address addr;
- inline RuntimeCall(uint offset = INT_MIN);
+ inline RuntimeCall(uint offset = uint(INT_MIN));
bool isValid() const { return addr.offset >= 0; }
};
@@ -297,22 +296,6 @@ public:
int savedRegCount;
};
- class ConstantTable
- {
- public:
- ConstantTable(Assembler *as): _as(as) {}
-
- int add(const QV4::Primitive &v);
- Address loadValueAddress(IR::Const *c, RegisterID baseReg);
- Address loadValueAddress(const QV4::Primitive &v, RegisterID baseReg);
- void finalize(JSC::LinkBuffer &linkBuffer, InstructionSelection *isel);
-
- private:
- Assembler *_as;
- QVector<QV4::Primitive> _values;
- QVector<DataLabelPtr> _toPatch;
- };
-
struct VoidType { VoidType() {} };
static const VoidType Void;
@@ -382,6 +365,8 @@ public:
Pointer loadTempAddress(IR::Temp *t);
Pointer loadArgLocalAddress(RegisterID baseReg, IR::ArgLocal *al);
Pointer loadStringAddress(RegisterID reg, const QString &string);
+ Address loadConstant(IR::Const *c, RegisterID baseReg);
+ Address loadConstant(const Primitive &v, RegisterID baseReg);
void loadStringRef(RegisterID reg, const QString &string);
Pointer stackSlotPointer(IR::Temp *t) const
{
@@ -1029,7 +1014,7 @@ public:
move(TrustedImm64(i), ReturnValueRegister);
move64ToDouble(ReturnValueRegister, target);
#else
- JSC::MacroAssembler::loadDouble(constantTable().loadValueAddress(c, ScratchRegister), target);
+ JSC::MacroAssembler::loadDouble(loadConstant(c, ScratchRegister), target);
#endif
return target;
}
@@ -1093,7 +1078,7 @@ public:
// it's not in signed int range, so load it as a double, and truncate it down
loadDouble(addr, FPGpr0);
- Address inversionAddress = constantTable().loadValueAddress(QV4::Primitive::fromDouble(double(INT_MAX) + 1), scratchReg);
+ Address inversionAddress = loadConstant(QV4::Primitive::fromDouble(double(INT_MAX) + 1), scratchReg);
subDouble(inversionAddress, FPGpr0);
Jump canNeverHappen = branchTruncateDoubleToUint32(FPGpr0, scratchReg);
canNeverHappen.link(this);
@@ -1111,14 +1096,12 @@ public:
void setStackLayout(int maxArgCountForBuiltins, int regularRegistersToSave, int fpRegistersToSave);
const StackLayout &stackLayout() const { return *_stackLayout.data(); }
- ConstantTable &constantTable() { return _constTable; }
Label exceptionReturnLabel;
IR::BasicBlock * catchBlock;
QVector<Jump> exceptionPropagationJumps;
private:
QScopedPointer<const StackLayout> _stackLayout;
- ConstantTable _constTable;
IR::Function *_function;
QHash<IR::BasicBlock *, Label> _addrs;
QHash<IR::BasicBlock *, QVector<Jump> > _patches;
diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp
index c09fc6fdca..45cc9259c3 100644
--- a/src/qml/jit/qv4binop.cpp
+++ b/src/qml/jit/qv4binop.cpp
@@ -162,7 +162,7 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
#if CPU(X86)
if (IR::Const *c = rhs->asConst()) { // Y = X + constant -> Y = X; Y += [constant-address]
as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg);
- Assembler::Address addr = as->constantTable().loadValueAddress(c, Assembler::ScratchRegister);
+ Assembler::Address addr = as->loadConstant(c, Assembler::ScratchRegister);
as->addDouble(addr, targetReg);
break;
}
@@ -184,7 +184,7 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
#if CPU(X86)
if (IR::Const *c = rhs->asConst()) { // Y = X * constant -> Y = X; Y *= [constant-address]
as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg);
- Assembler::Address addr = as->constantTable().loadValueAddress(c, Assembler::ScratchRegister);
+ Assembler::Address addr = as->loadConstant(c, Assembler::ScratchRegister);
as->mulDouble(addr, targetReg);
break;
}
@@ -203,7 +203,7 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
#if CPU(X86)
if (IR::Const *c = rhs->asConst()) { // Y = X - constant -> Y = X; Y -= [constant-address]
as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg);
- Assembler::Address addr = as->constantTable().loadValueAddress(c, Assembler::ScratchRegister);
+ Assembler::Address addr = as->loadConstant(c, Assembler::ScratchRegister);
as->subDouble(addr, targetReg);
break;
}
@@ -231,7 +231,7 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
#if CPU(X86)
if (IR::Const *c = rhs->asConst()) { // Y = X / constant -> Y = X; Y /= [constant-address]
as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg);
- Assembler::Address addr = as->constantTable().loadValueAddress(c, Assembler::ScratchRegister);
+ Assembler::Address addr = as->loadConstant(c, Assembler::ScratchRegister);
as->divDouble(addr, targetReg);
break;
}
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index bde2c59526..da28df817d 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -177,7 +177,6 @@ JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
linkBuffer.patch(label, linkBuffer.locationOf(target));
}
}
- _constTable.finalize(linkBuffer, _isel);
*codeSize = linkBuffer.offsetOf(endOfCode);
@@ -258,8 +257,8 @@ JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
return codeRef;
}
-InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, Compiler::JSUnitGenerator *jsGenerator)
- : EvalInstructionSelection(execAllocator, module, jsGenerator)
+InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, Compiler::JSUnitGenerator *jsGenerator, EvalISelFactory *iselFactory)
+ : EvalInstructionSelection(execAllocator, module, jsGenerator, iselFactory)
, _block(0)
, _as(0)
, compilationUnit(new CompilationUnit)
@@ -370,16 +369,6 @@ void InstructionSelection::run(int functionIndex)
qSwap(_removableJumps, removableJumps);
}
-const void *InstructionSelection::addConstantTable(QVector<Primitive> *values)
-{
- compilationUnit->constantValues.append(*values);
- values->clear();
-
- QVector<QV4::Primitive> &finalValues = compilationUnit->constantValues.last();
- finalValues.squeeze();
- return finalValues.constData();
-}
-
QQmlRefPointer<QV4::CompiledData::CompilationUnit> InstructionSelection::backendCompileStep()
{
QQmlRefPointer<QV4::CompiledData::CompilationUnit> result;
@@ -1719,38 +1708,6 @@ bool operator==(const Primitive &v1, const Primitive &v2)
} // QV4 namespace
QT_END_NAMESPACE
-int Assembler::ConstantTable::add(const Primitive &v)
-{
- int idx = _values.indexOf(v);
- if (idx == -1) {
- idx = _values.size();
- _values.append(v);
- }
- return idx;
-}
-
-Assembler::Address Assembler::ConstantTable::loadValueAddress(IR::Const *c, RegisterID baseReg)
-{
- return loadValueAddress(convertToValue(c), baseReg);
-}
-
-Assembler::Address Assembler::ConstantTable::loadValueAddress(const Primitive &v, RegisterID baseReg)
-{
- _toPatch.append(_as->moveWithPatch(TrustedImmPtr(0), baseReg));
- Address addr(baseReg);
- addr.offset = add(v) * sizeof(QV4::Primitive);
- Q_ASSERT(addr.offset >= 0);
- return addr;
-}
-
-void Assembler::ConstantTable::finalize(JSC::LinkBuffer &linkBuffer, InstructionSelection *isel)
-{
- const void *tablePtr = isel->addConstantTable(&_values);
-
- foreach (DataLabelPtr label, _toPatch)
- linkBuffer.patch(label, const_cast<void *>(tablePtr));
-}
-
bool InstructionSelection::visitCJumpDouble(IR::AluOp op, IR::Expr *left, IR::Expr *right,
IR::BasicBlock *iftrue, IR::BasicBlock *iffalse)
{
diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h
index 7616ba147f..93453f71be 100644
--- a/src/qml/jit/qv4isel_masm_p.h
+++ b/src/qml/jit/qv4isel_masm_p.h
@@ -76,12 +76,11 @@ class Q_QML_EXPORT InstructionSelection:
public EvalInstructionSelection
{
public:
- InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator);
+ InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator, EvalISelFactory *iselFactory);
~InstructionSelection();
virtual void run(int functionIndex);
- const void *addConstantTable(QVector<QV4::Primitive> *values);
protected:
virtual QQmlRefPointer<QV4::CompiledData::CompilationUnit> backendCompileStep();
@@ -285,12 +284,13 @@ private:
class Q_QML_EXPORT ISelFactory: public EvalISelFactory
{
public:
+ ISelFactory() : EvalISelFactory(QStringLiteral("jit")) {}
virtual ~ISelFactory() {}
- virtual EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
- { return new InstructionSelection(qmlEngine, execAllocator, module, jsGenerator); }
- virtual bool jitCompileRegexps() const
+ EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator) Q_DECL_OVERRIDE Q_DECL_FINAL
+ { return new InstructionSelection(qmlEngine, execAllocator, module, jsGenerator, this); }
+ bool jitCompileRegexps() const Q_DECL_OVERRIDE Q_DECL_FINAL
{ return true; }
- QQmlRefPointer<CompiledData::CompilationUnit> createUnitForLoading() Q_DECL_OVERRIDE;
+ QQmlRefPointer<CompiledData::CompilationUnit> createUnitForLoading() Q_DECL_OVERRIDE Q_DECL_FINAL;
};
} // end of namespace JIT
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index 7b58e60b9d..e72b06359e 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -6,7 +6,6 @@ SOURCES += \
$$PWD/qv4engine.cpp \
$$PWD/qv4context.cpp \
$$PWD/qv4persistent.cpp \
- $$PWD/qv4debugging.cpp \
$$PWD/qv4lookup.cpp \
$$PWD/qv4identifier.cpp \
$$PWD/qv4identifiertable.cpp \
@@ -40,11 +39,12 @@ SOURCES += \
$$PWD/qv4include.cpp \
$$PWD/qv4qobjectwrapper.cpp \
$$PWD/qv4vme_moth.cpp \
- $$PWD/qv4profiling.cpp \
$$PWD/qv4arraybuffer.cpp \
$$PWD/qv4typedarray.cpp \
$$PWD/qv4dataview.cpp
+!contains(QT_CONFIG, no-qml-debug): SOURCES += $$PWD/qv4profiling.cpp
+
HEADERS += \
$$PWD/qv4global_p.h \
$$PWD/qv4engine_p.h \
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 97b3e26a26..1abaca3dd1 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -73,6 +73,7 @@ Heap::CallContext *ExecutionContext::newCallContext(const FunctionObject *functi
c->compilationUnit = function->function()->compilationUnit;
c->lookups = c->compilationUnit->runtimeLookups;
+ c->constantTable = c->compilationUnit->constants;
c->locals = (Value *)((quintptr(c + 1) + 7) & ~7);
const CompiledData::Function *compiledFunction = function->function()->compiledFunction;
@@ -172,6 +173,7 @@ Heap::WithContext::WithContext(ExecutionContext *outerContext, Object *with)
outer = outerContext;
callData = outer->callData;
lookups = outer->lookups;
+ constantTable = outer->constantTable;
compilationUnit = outer->compilationUnit;
withObject = with;
@@ -184,6 +186,7 @@ Heap::CatchContext::CatchContext(ExecutionContext *outerContext, String *excepti
strictMode = outer->strictMode;
callData = outer->callData;
lookups = outer->lookups;
+ constantTable = outer->constantTable;
compilationUnit = outer->compilationUnit;
this->exceptionVarName = exceptionVarName;
@@ -197,6 +200,7 @@ Heap::QmlContext::QmlContext(QV4::ExecutionContext *outerContext, QV4::QmlContex
strictMode = false;
callData = outer->callData;
lookups = outer->lookups;
+ constantTable = outer->constantTable;
compilationUnit = outer->compilationUnit;
this->qml = qml->d();
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 2e6773a927..368605ca4a 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -108,6 +108,7 @@ struct ExecutionContext : Base {
ExecutionEngine *engine;
Pointer<ExecutionContext> outer;
Lookup *lookups;
+ const QV4::Value *constantTable;
CompiledData::CompilationUnit *compilationUnit;
ContextType type : 8;
@@ -118,9 +119,10 @@ struct ExecutionContext : Base {
inline
ExecutionContext::ExecutionContext(ExecutionEngine *engine, ContextType t)
: engine(engine)
- , outer(0)
- , lookups(0)
- , compilationUnit(0)
+ , outer(nullptr)
+ , lookups(nullptr)
+ , constantTable(nullptr)
+ , compilationUnit(nullptr)
, type(t)
, strictMode(false)
, lineNumber(-1)
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
deleted file mode 100644
index 9fcba64038..0000000000
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qv4debugging_p.h"
-#include "qv4object_p.h"
-#include "qv4functionobject_p.h"
-#include "qv4function_p.h"
-#include "qv4instr_moth_p.h"
-#include "qv4runtime_p.h"
-#include "qv4script_p.h"
-#include "qv4identifier_p.h"
-#include "qv4string_p.h"
-#include "qv4objectiterator_p.h"
-
-#include <iostream>
-#include <algorithm>
-
-#include <QtCore/QJsonArray>
-#include <QtCore/QJsonDocument>
-#include <QtCore/QJsonValue>
-
-QT_BEGIN_NAMESPACE
-
-QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4debugging_p.h b/src/qml/jsruntime/qv4debugging_p.h
index 9dca7e9979..3b589a41f1 100644
--- a/src/qml/jsruntime/qv4debugging_p.h
+++ b/src/qml/jsruntime/qv4debugging_p.h
@@ -59,6 +59,19 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
namespace Debugging {
+#ifdef QT_NO_QML_DEBUGGER
+
+struct Debugger
+{
+ bool pauseAtNextOpportunity() const { return false; }
+ void maybeBreakAtInstruction() {}
+ void enteringFunction() {}
+ void leavingFunction(const ReturnedValue &) {}
+ void aboutToThrow() {}
+};
+
+#else
+
class Q_QML_EXPORT Debugger : public QObject
{
Q_OBJECT
@@ -72,6 +85,8 @@ public:
virtual void aboutToThrow() = 0;
};
+#endif // QT_NO_QML_DEBUGGING
+
} // namespace Debugging
} // namespace QV4
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index fe2d4e6575..f5bae4b258 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -136,8 +136,6 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
, currentContext(0)
, bumperPointerAllocator(new WTF::BumpPointerAllocator)
, jsStack(new WTF::PageAllocation)
- , debugger(0)
- , profiler(0)
, globalCode(0)
, v8Engine(0)
, argumentsAccessors(0)
@@ -145,6 +143,10 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
, m_engineId(engineSerial.fetchAndAddOrdered(1))
, regExpCache(0)
, m_multiplyWrappedQObjects(0)
+#ifndef QT_NO_QML_DEBUGGER
+ , m_debugger(0)
+ , m_profiler(0)
+#endif
{
if (maxCallDepth == -1) {
bool ok = false;
@@ -442,10 +444,12 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
ExecutionEngine::~ExecutionEngine()
{
- delete debugger;
- debugger = 0;
- delete profiler;
- profiler = 0;
+#ifndef QT_NO_QML_DEBUGGER
+ delete m_debugger;
+ m_debugger = 0;
+ delete m_profiler;
+ m_profiler = 0;
+#endif
delete m_multiplyWrappedQObjects;
m_multiplyWrappedQObjects = 0;
delete identifierTable;
@@ -467,17 +471,19 @@ ExecutionEngine::~ExecutionEngine()
delete [] argumentsAccessors;
}
-void ExecutionEngine::setDebugger(Debugging::Debugger *debugger_)
+#ifndef QT_NO_QML_DEBUGGER
+void ExecutionEngine::setDebugger(Debugging::Debugger *debugger)
{
- Q_ASSERT(!debugger);
- debugger = debugger_;
+ Q_ASSERT(!m_debugger);
+ m_debugger = debugger;
}
-void ExecutionEngine::enableProfiler()
+void ExecutionEngine::setProfiler(Profiling::Profiler *profiler)
{
- Q_ASSERT(!profiler);
- profiler = new QV4::Profiling::Profiler(this);
+ Q_ASSERT(!m_profiler);
+ m_profiler = profiler;
}
+#endif // QT_NO_QML_DEBUGGER
void ExecutionEngine::initRootContext()
{
@@ -910,8 +916,8 @@ ReturnedValue ExecutionEngine::throwError(const Value &value)
else
exceptionStackTrace = stackTrace();
- if (debugger)
- debugger->aboutToThrow();
+ if (QV4::Debugging::Debugger *debug = debugger())
+ debug->aboutToThrow();
return Encode::undefined();
}
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 8743df771c..f42f727295 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -137,9 +137,6 @@ public:
IdentifierTable *identifierTable;
- QV4::Debugging::Debugger *debugger;
- QV4::Profiling::Profiler *profiler;
-
Object *globalObject;
Function *globalCode;
@@ -382,8 +379,19 @@ public:
ExecutionEngine(EvalISelFactory *iselFactory = 0);
~ExecutionEngine();
+#ifdef QT_NO_QML_DEBUGGER
+ QV4::Debugging::Debugger *debugger() const { return nullptr; }
+ QV4::Profiling::Profiler *profiler() const { return nullptr; }
+
+ void setDebugger(Debugging::Debugger *) {}
+ void setProfiler(Profiling::Profiler *) {}
+#else
+ QV4::Debugging::Debugger *debugger() const { return m_debugger; }
+ QV4::Profiling::Profiler *profiler() const { return m_profiler; }
+
void setDebugger(Debugging::Debugger *debugger);
- void enableProfiler();
+ void setProfiler(Profiling::Profiler *profiler);
+#endif // QT_NO_QML_DEBUGGER
ExecutionContext *pushGlobalContext();
void pushContext(Heap::ExecutionContext *context);
@@ -484,6 +492,11 @@ public:
private:
void failStackLimitCheck(Scope &scope);
+
+#ifndef QT_NO_QML_DEBUGGER
+ QV4::Debugging::Debugger *m_debugger;
+ QV4::Profiling::Profiler *m_profiler;
+#endif
};
// This is a trick to tell the code generators that functions taking a NoThrowContext won't
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index fce80c46eb..276a069a77 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -283,7 +283,7 @@ void FunctionCtor::construct(const Managed *that, Scope &scope, CallData *callDa
return;
}
- IR::Module module(scope.engine->debugger != 0);
+ IR::Module module(scope.engine->debugger() != 0);
QQmlJS::RuntimeCodegen cg(scope.engine, f->strictMode());
cg.generateFromFunctionExpression(QString(), function, fe, &module);
@@ -535,6 +535,7 @@ void SimpleScriptFunction::construct(const Managed *that, Scope &scope, CallData
ctx.function = f->d();
ctx.compilationUnit = f->function()->compilationUnit;
ctx.lookups = ctx.compilationUnit->runtimeLookups;
+ ctx.constantTable = ctx.compilationUnit->constants;
ctx.outer = f->scope();
ctx.locals = scope.alloc(f->varCount());
for (int i = callData->argc; i < (int)f->formalParameterCount(); ++i)
@@ -572,6 +573,7 @@ void SimpleScriptFunction::call(const Managed *that, Scope &scope, CallData *cal
ctx.function = f->d();
ctx.compilationUnit = f->function()->compilationUnit;
ctx.lookups = ctx.compilationUnit->runtimeLookups;
+ ctx.constantTable = ctx.compilationUnit->constants;
ctx.outer = f->scope();
ctx.locals = scope.alloc(f->varCount());
for (int i = callData->argc; i < (int)f->formalParameterCount(); ++i)
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index f46f581168..bac45e18c8 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -147,8 +147,8 @@ static void insertHoleIntoPropertyData(Object *object, int idx)
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 oldSize = object->internalClass()->size + delta;
int to = idx;
int from = to + delta;
if (from < inlineSize) {
@@ -156,15 +156,15 @@ static void removeFromPropertyData(Object *object, int idx, bool accessor = fals
to = inlineSize - delta;
from = inlineSize;
}
- if (to < inlineSize && from < icSize) {
+ if (to < inlineSize && from < oldSize) {
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) {
+ if (from < oldSize) {
Q_ASSERT(to >= inlineSize && from > to);
- memmove(object->propertyData(to), object->d()->propertyData(from), (icSize + delta - to)*sizeof(Value));
+ memmove(object->propertyData(to), object->d()->propertyData(from), (oldSize - to)*sizeof(Value));
}
}
diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h
index 01fdf2951e..e06cb64a61 100644
--- a/src/qml/jsruntime/qv4profiling_p.h
+++ b/src/qml/jsruntime/qv4profiling_p.h
@@ -57,6 +57,40 @@
#include <QElapsedTimer>
+#ifdef QT_NO_QML_DEBUGGER
+
+#define Q_V4_PROFILE_ALLOC(engine, size, type) (!engine)
+#define Q_V4_PROFILE_DEALLOC(engine, size, type) (!engine)
+#define Q_V4_PROFILE(engine, function) (function->code(engine, function->codeData))
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+namespace Profiling {
+struct Profiler {};
+}
+}
+
+QT_END_NAMESPACE
+
+#else
+
+#define Q_V4_PROFILE_ALLOC(engine, size, type)\
+ (engine->profiler() &&\
+ (engine->profiler()->featuresEnabled & (1 << Profiling::FeatureMemoryAllocation)) ?\
+ engine->profiler()->trackAlloc(size, type) : false)
+
+#define Q_V4_PROFILE_DEALLOC(engine, size, type) \
+ (engine->profiler() &&\
+ (engine->profiler()->featuresEnabled & (1 << Profiling::FeatureMemoryAllocation)) ?\
+ engine->profiler()->trackDealloc(size, type) : false)
+
+#define Q_V4_PROFILE(engine, function)\
+ (engine->profiler() &&\
+ (engine->profiler()->featuresEnabled & (1 << Profiling::FeatureFunctionCall)) ?\
+ Profiling::FunctionCallProfiler::profileCall(engine->profiler(), engine, function) :\
+ function->code(engine, function->codeData))
+
QT_BEGIN_NAMESPACE
namespace QV4 {
@@ -150,25 +184,8 @@ private:
qint64 m_end;
};
-#define Q_V4_PROFILE_ALLOC(engine, size, type)\
- (engine->profiler &&\
- (engine->profiler->featuresEnabled & (1 << Profiling::FeatureMemoryAllocation)) ?\
- engine->profiler->trackAlloc(size, type) : size)
-
-#define Q_V4_PROFILE_DEALLOC(engine, pointer, size, type) \
- (engine->profiler &&\
- (engine->profiler->featuresEnabled & (1 << Profiling::FeatureMemoryAllocation)) ?\
- engine->profiler->trackDealloc(pointer, size, type) : pointer)
-
-#define Q_V4_PROFILE(engine, function)\
- (engine->profiler &&\
- (engine->profiler->featuresEnabled & (1 << Profiling::FeatureFunctionCall)) ?\
- Profiling::FunctionCallProfiler::profileCall(engine->profiler, engine, function) :\
- function->code(engine, function->codeData))
-
class Q_QML_EXPORT Profiler : public QObject {
Q_OBJECT
- Q_DISABLE_COPY(Profiler)
public:
struct SentMarker {
SentMarker() : m_function(nullptr) {}
@@ -212,23 +229,22 @@ public:
Profiler(QV4::ExecutionEngine *engine);
- size_t trackAlloc(size_t size, MemoryType type)
+ bool trackAlloc(size_t size, MemoryType type)
{
MemoryAllocationProperties allocation = {m_timer.nsecsElapsed(), (qint64)size, type};
m_memory_data.append(allocation);
- return size;
+ return true;
}
- void *trackDealloc(void *pointer, size_t size, MemoryType type)
+ bool trackDealloc(size_t size, MemoryType type)
{
MemoryAllocationProperties allocation = {m_timer.nsecsElapsed(), -(qint64)size, type};
m_memory_data.append(allocation);
- return pointer;
+ return true;
}
quint64 featuresEnabled;
-public slots:
void stopProfiling();
void startProfiling(quint64 features);
void reportData(bool trackLocations);
@@ -290,4 +306,6 @@ Q_DECLARE_METATYPE(QV4::Profiling::FunctionLocationHash)
Q_DECLARE_METATYPE(QVector<QV4::Profiling::FunctionCallProperties>)
Q_DECLARE_METATYPE(QVector<QV4::Profiling::MemoryAllocationProperties>)
+#endif // QT_NO_QML_DEBUGGER
+
#endif // QV4PROFILING_H
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 97f5cbb786..e3475e5cd6 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -148,7 +148,7 @@ void Script::parse()
MemoryManager::GCBlocker gcBlocker(v4->memoryManager);
- IR::Module module(v4->debugger != 0);
+ IR::Module module(v4->debugger() != 0);
QQmlJS::Engine ee, *engine = &ee;
Lexer lexer(engine);
@@ -222,6 +222,7 @@ ReturnedValue Script::run()
ContextStateSaver stateSaver(valueScope, scope);
scope->d()->strictMode = vmFunction->isStrict();
scope->d()->lookups = vmFunction->compilationUnit->runtimeLookups;
+ scope->d()->constantTable = vmFunction->compilationUnit->constants;
scope->d()->compilationUnit = vmFunction->compilationUnit;
return Q_V4_PROFILE(engine, vmFunction);
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index e81bc3049c..2e87a7692b 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -71,6 +71,7 @@ struct ContextStateSaver {
Value *savedContext;
bool strictMode;
Lookup *lookups;
+ const QV4::Value *constantTable;
CompiledData::CompilationUnit *compilationUnit;
int lineNumber;
@@ -78,6 +79,7 @@ struct ContextStateSaver {
: savedContext(scope.alloc(1))
, strictMode(context->d()->strictMode)
, lookups(context->d()->lookups)
+ , constantTable(context->d()->constantTable)
, compilationUnit(context->d()->compilationUnit)
, lineNumber(context->d()->lineNumber)
{
@@ -87,6 +89,7 @@ struct ContextStateSaver {
: savedContext(scope.alloc(1))
, strictMode(context->strictMode)
, lookups(context->lookups)
+ , constantTable(context->constantTable)
, compilationUnit(context->compilationUnit)
, lineNumber(context->lineNumber)
{
@@ -98,6 +101,7 @@ struct ContextStateSaver {
Heap::ExecutionContext *ctx = static_cast<Heap::ExecutionContext *>(savedContext->m());
ctx->strictMode = strictMode;
ctx->lookups = lookups;
+ ctx->constantTable = constantTable;
ctx->compilationUnit = compilationUnit;
ctx->lineNumber = lineNumber;
}
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index d3b021ac37..b15ac7eb5e 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -531,7 +531,7 @@ public:
Q_ASSERT(d()->object);
Q_ASSERT(d()->isReference);
int status = -1;
- QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding;
+ QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding;
void *a[] = { &d()->container, 0, &status, &flags };
QMetaObject::metacall(d()->object, QMetaObject::WriteProperty, d()->propertyIndex, a);
}
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index d24a5c4c76..dae4d11767 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -102,13 +102,13 @@ public:
Q_ALWAYS_INLINE quint64 rawValue() const { return _val; }
Q_ALWAYS_INLINE void setRawValue(quint64 raw) { _val = raw; }
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN || defined(QV4_USE_64_BIT_VALUE_ENCODING)
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
+#else // !Q_LITTLE_ENDIAN && !defined(QV4_USE_64_BIT_VALUE_ENCODING)
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; }
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index b83bae8a38..420abd1458 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -142,6 +142,7 @@ Q_QML_EXPORT int qt_v4DebuggerHook(const char *json);
} // extern "C"
+#ifndef QT_NO_QML_DEBUGGER
static int qt_v4BreakpointCount = 0;
static bool qt_v4IsDebugging = true;
static bool qt_v4IsStepping = false;
@@ -285,6 +286,7 @@ static void qt_v4CheckForBreak(QV4::ExecutionContext *context, QV4::Value **scop
}
}
+#endif // QT_NO_QML_DEBUGGER
// End of debugger interface
using namespace QV4;
@@ -400,7 +402,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
QV4::Value **scopes = static_cast<QV4::Value **>(alloca(sizeof(QV4::Value *)*(2 + 2*scopeDepth)));
{
- scopes[0] = const_cast<QV4::Value *>(context->d()->compilationUnit->data->constants());
+ scopes[0] = const_cast<QV4::Value *>(context->d()->compilationUnit->constants);
// stack gets setup in push instruction
scopes[1] = 0;
QV4::Heap::ExecutionContext *scope = context->d();
@@ -904,9 +906,10 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
return VALUE(instr.result).asReturnedValue();
MOTH_END_INSTR(Ret)
+#ifndef QT_NO_QML_DEBUGGER
MOTH_BEGIN_INSTR(Debug)
engine->current->lineNumber = instr.lineNumber;
- QV4::Debugging::Debugger *debugger = context->engine()->debugger;
+ QV4::Debugging::Debugger *debugger = context->engine()->debugger();
if (debugger && debugger->pauseAtNextOpportunity())
debugger->maybeBreakAtInstruction();
if (qt_v4IsDebugging)
@@ -918,6 +921,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
if (qt_v4IsDebugging)
qt_v4CheckForBreak(context, scopes, scopeDepth);
MOTH_END_INSTR(Line)
+#endif // QT_NO_QML_DEBUGGER
MOTH_BEGIN_INSTR(LoadThis)
VALUE(instr.result) = context->thisObject();
@@ -970,7 +974,7 @@ void **VME::instructionJumpTable()
QV4::ReturnedValue VME::exec(ExecutionEngine *engine, const uchar *code)
{
VME vme;
- QV4::Debugging::Debugger *debugger = engine->debugger;
+ QV4::Debugging::Debugger *debugger = engine->debugger();
if (debugger)
debugger->enteringFunction();
QV4::ReturnedValue retVal = vme.run(engine, code);
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index a8d5624550..a6d7c3b1ed 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -185,7 +185,7 @@ struct MemoryManager::Data
~Data()
{
for (std::vector<PageAllocation>::iterator i = heapChunks.begin(), ei = heapChunks.end(); i != ei; ++i) {
- Q_V4_PROFILE_DEALLOC(engine, 0, i->size(), Profiling::HeapPage);
+ Q_V4_PROFILE_DEALLOC(engine, i->size(), Profiling::HeapPage);
i->deallocate();
}
}
@@ -239,7 +239,7 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec
#ifdef V4_USE_HEAPTRACK
heaptrack_report_free(m);
#endif
- Q_V4_PROFILE_DEALLOC(engine, m, header->itemSize, Profiling::SmallItem);
+ Q_V4_PROFILE_DEALLOC(engine, header->itemSize, Profiling::SmallItem);
++(*itemsInUse);
}
// Relink all free blocks to rewrite references to any released chunk.
@@ -302,10 +302,11 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
runGC();
// we use malloc for this
- MemoryManager::Data::LargeItem *item = static_cast<MemoryManager::Data::LargeItem *>(
- malloc(Q_V4_PROFILE_ALLOC(engine, size + sizeof(MemoryManager::Data::LargeItem),
- Profiling::LargeItem)));
- memset(item, 0, size + sizeof(MemoryManager::Data::LargeItem));
+ const size_t totalSize = size + sizeof(MemoryManager::Data::LargeItem);
+ Q_V4_PROFILE_ALLOC(engine, totalSize, Profiling::LargeItem);
+ MemoryManager::Data::LargeItem *item =
+ static_cast<MemoryManager::Data::LargeItem *>(malloc(totalSize));
+ memset(item, 0, totalSize);
item->next = m_d->largeItems;
item->size = size;
m_d->largeItems = item;
@@ -338,9 +339,8 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
shift = m_d->maxShift;
std::size_t allocSize = m_d->maxChunkSize*(size_t(1) << shift);
allocSize = roundUpToMultipleOf(m_d->pageSize, allocSize);
- PageAllocation allocation = PageAllocation::allocate(
- Q_V4_PROFILE_ALLOC(engine, allocSize, Profiling::HeapPage),
- OSAllocator::JSGCHeapPages);
+ Q_V4_PROFILE_ALLOC(engine, allocSize, Profiling::HeapPage);
+ PageAllocation allocation = PageAllocation::allocate(allocSize, OSAllocator::JSGCHeapPages);
m_d->heapChunks.push_back(allocation);
header = reinterpret_cast<Data::ChunkHeader *>(allocation.base());
@@ -507,7 +507,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(engine, 0, chunkIter->size(), Profiling::HeapPage);
+ Q_V4_PROFILE_DEALLOC(engine, chunkIter->size(), Profiling::HeapPage);
#ifdef V4_USE_VALGRIND
VALGRIND_MEMPOOL_FREE(this, header);
#endif
@@ -542,8 +542,8 @@ void MemoryManager::sweep(bool lastSweep)
m->vtable()->destroy(m);
*last = i->next;
- free(Q_V4_PROFILE_DEALLOC(engine, i, i->size + sizeof(Data::LargeItem),
- Profiling::LargeItem));
+ Q_V4_PROFILE_DEALLOC(engine, i->size + sizeof(Data::LargeItem), Profiling::LargeItem);
+ free(i);
i = *last;
}
diff --git a/src/qml/qml.pro b/src/qml/qml.pro
index d9452a6257..cc5023f12a 100644
--- a/src/qml/qml.pro
+++ b/src/qml/qml.pro
@@ -22,7 +22,7 @@ exists("qqml_enable_gcov") {
LIBS_PRIVATE += -lgcov
}
-greaterThan(QT_GCC_MAJOR_VERSION, 5) {
+gcc:!intel_icc:greaterThan(QT_GCC_MAJOR_VERSION, 5) {
# Our code is bad. Temporary workaround.
QMAKE_CXXFLAGS += -fno-delete-null-pointer-checks
}
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index 75e1eb9345..cc394b78cb 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -38,7 +38,6 @@ SOURCES += \
$$PWD/qqmlvaluetypeproxybinding.cpp \
$$PWD/qqmlglobal.cpp \
$$PWD/qqmlfile.cpp \
- $$PWD/qqmlmemoryprofiler.cpp \
$$PWD/qqmlplatform.cpp \
$$PWD/qqmlbinding.cpp \
$$PWD/qqmlabstracturlinterceptor.cpp \
@@ -107,7 +106,6 @@ HEADERS += \
$$PWD/qqmlabstractbinding_p.h \
$$PWD/qqmlvaluetypeproxybinding_p.h \
$$PWD/qqmlfile.h \
- $$PWD/qqmlmemoryprofiler_p.h \
$$PWD/qqmlplatform_p.h \
$$PWD/qqmlbinding_p.h \
$$PWD/qqmlextensionplugin_p.h \
diff --git a/src/qml/qml/qqmlabstractbinding_p.h b/src/qml/qml/qqmlabstractbinding_p.h
index d25c0c6288..0ccfae4610 100644
--- a/src/qml/qml/qqmlabstractbinding_p.h
+++ b/src/qml/qml/qqmlabstractbinding_p.h
@@ -82,7 +82,7 @@ public:
// binding is not enabled or added to the object.
QObject *targetObject() const { return m_target.data(); }
- virtual void setEnabled(bool e, QQmlPropertyPrivate::WriteFlags f = QQmlPropertyPrivate::DontRemoveBinding) = 0;
+ virtual void setEnabled(bool e, QQmlPropertyData::WriteFlags f = QQmlPropertyData::DontRemoveBinding) = 0;
void addToObject();
void removeFromObject();
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 9737dfdd6b..ffe1b4287d 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -51,6 +51,8 @@
#include <private/qqmlbuiltinfunctions_p.h>
#include <private/qqmlvmemetaobject_p.h>
#include <private/qqmlvaluetypewrapper_p.h>
+#include <private/qv4qobjectwrapper_p.h>
+#include <private/qv4variantobject_p.h>
#include <QVariant>
#include <QtCore/qdebug.h>
@@ -59,7 +61,7 @@ QT_BEGIN_NAMESPACE
QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QString &str, QObject *obj, QQmlContext *ctxt)
{
- QQmlBinding *b = newBinding(property);
+ QQmlBinding *b = newBinding(QQmlEnginePrivate::get(ctxt), property);
b->setNotifyOnValueChanged(true);
b->QQmlJavaScriptExpression::setContext(QQmlContextData::get(ctxt));
b->setScopeObject(obj);
@@ -71,7 +73,7 @@ QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QString
QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QQmlScriptString &script, QObject *obj, QQmlContext *ctxt)
{
- QQmlBinding *b = newBinding(property);
+ QQmlBinding *b = newBinding(QQmlEnginePrivate::get(ctxt), property);
if (ctxt && !ctxt->isValid())
return b;
@@ -108,7 +110,7 @@ QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QQmlScr
QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QString &str, QObject *obj, QQmlContextData *ctxt)
{
- QQmlBinding *b = newBinding(property);
+ QQmlBinding *b = newBinding(QQmlEnginePrivate::get(ctxt), property);
b->setNotifyOnValueChanged(true);
b->QQmlJavaScriptExpression::setContext(ctxt);
@@ -123,7 +125,7 @@ QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QString
QQmlContextData *ctxt, const QString &url, quint16 lineNumber,
quint16 columnNumber)
{
- QQmlBinding *b = newBinding(property);
+ QQmlBinding *b = newBinding(QQmlEnginePrivate::get(ctxt), property);
Q_UNUSED(columnNumber);
b->setNotifyOnValueChanged(true);
@@ -137,7 +139,7 @@ QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QString
QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QV4::Value &functionPtr, QObject *obj, QQmlContextData *ctxt)
{
- QQmlBinding *b = newBinding(property);
+ QQmlBinding *b = newBinding(QQmlEnginePrivate::get(ctxt), property);
b->setNotifyOnValueChanged(true);
b->QQmlJavaScriptExpression::setContext(ctxt);
@@ -157,7 +159,7 @@ void QQmlBinding::setNotifyOnValueChanged(bool v)
QQmlJavaScriptExpression::setNotifyOnValueChanged(v);
}
-void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
+void QQmlBinding::update(QQmlPropertyData::WriteFlags flags)
{
if (!enabledFlag() || !context() || !context()->isValid())
return;
@@ -181,6 +183,9 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
QV4::ScopedFunctionObject f(scope, m_function.value());
Q_ASSERT(f);
+ if (canUseAccessor())
+ flags.setFlag(QQmlPropertyData::BypassInterceptor);
+
QQmlBindingProfiler prof(ep->profiler, this, f);
doUpdate(this, watcher, flags, scope, f);
@@ -197,26 +202,21 @@ class QQmlBindingBinding: public QQmlBinding
{
protected:
void doUpdate(QQmlBinding *binding, const DeleteWatcher &,
- QQmlPropertyPrivate::WriteFlags flags, QV4::Scope &,
+ QQmlPropertyData::WriteFlags flags, QV4::Scope &,
const QV4::ScopedFunctionObject &) Q_DECL_OVERRIDE Q_DECL_FINAL
{
QQmlPropertyData pd = getPropertyData();
-
- int idx = pd.coreIndex;
- Q_ASSERT(idx != -1);
-
- int status = -1;
- void *a[] = { &binding, 0, &status, &flags };
- QMetaObject::metacall(*m_target, QMetaObject::WriteProperty, idx, a);
+ pd.writeProperty(*m_target, &binding, flags);
}
};
-template<int StaticPropType>
-class GenericBinding: public QQmlBinding
+// For any target that's not a binding, we have a common doUpdate. However, depending on the type
+// of the target property, there is a specialized write method.
+class QQmlNonbindingBinding: public QQmlBinding
{
protected:
void doUpdate(QQmlBinding *binding, const DeleteWatcher &watcher,
- QQmlPropertyPrivate::WriteFlags flags, QV4::Scope &scope,
+ QQmlPropertyData::WriteFlags flags, QV4::Scope &scope,
const QV4::ScopedFunctionObject &f) Q_DECL_OVERRIDE Q_DECL_FINAL
{
auto ep = QQmlEnginePrivate::get(scope.engine);
@@ -249,9 +249,16 @@ protected:
ep->dereferenceScarceResources();
}
+ virtual bool write(const QV4::Value &result, bool isUndefined, QQmlPropertyData::WriteFlags flags) = 0;
+};
+
+template<int StaticPropType>
+class GenericBinding: public QQmlNonbindingBinding
+{
+protected:
// Returns true if successful, false if an error description was set on expression
Q_ALWAYS_INLINE bool write(const QV4::Value &result, bool isUndefined,
- QQmlPropertyPrivate::WriteFlags flags)
+ QQmlPropertyData::WriteFlags flags) Q_DECL_OVERRIDE Q_DECL_FINAL
{
QQmlPropertyData pd = getPropertyData();
int propertyType = StaticPropType; // If the binding is specialized to a type, the if and switch below will be constant-folded.
@@ -298,22 +305,15 @@ protected:
}
template <typename T>
- Q_ALWAYS_INLINE bool doStore(T value, const QQmlPropertyData &pd, QQmlPropertyPrivate::WriteFlags flags) const
+ Q_ALWAYS_INLINE bool doStore(T value, const QQmlPropertyData &pd, QQmlPropertyData::WriteFlags flags) const
{
void *o = &value;
- if (pd.hasAccessors() && canUseAccessor()) {
- pd.accessors->write(m_target.data(), o);
- } else {
- int status = -1;
- void *argv[] = { o, 0, &status, &flags };
- QMetaObject::metacall(targetObject(), QMetaObject::WriteProperty, pd.coreIndex, argv);
- }
- return true;
+ return pd.writeProperty(targetObject(), o, flags);
}
};
Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core, const QV4::Value &result,
- bool isUndefined, QQmlPropertyPrivate::WriteFlags flags)
+ bool isUndefined, QQmlPropertyData::WriteFlags flags)
{
QQmlEngine *engine = context()->engine;
QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(engine);
@@ -458,7 +458,7 @@ void QQmlBinding::refresh()
update();
}
-void QQmlBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags)
+void QQmlBinding::setEnabled(bool e, QQmlPropertyData::WriteFlags flags)
{
setEnabledFlag(e);
setNotifyOnValueChanged(e);
@@ -576,8 +576,68 @@ Q_ALWAYS_INLINE int QQmlBinding::getPropertyCoreIndex() const
}
}
-QQmlBinding *QQmlBinding::newBinding(const QQmlPropertyData *property)
+class QObjectPointerBinding: public QQmlNonbindingBinding
+{
+ QQmlMetaObject targetMetaObject;
+
+public:
+ QObjectPointerBinding(QQmlEnginePrivate *engine, int propertyType)
+ : targetMetaObject(QQmlPropertyPrivate::rawMetaObjectForType(engine, propertyType))
+ {}
+
+protected:
+ Q_ALWAYS_INLINE bool write(const QV4::Value &result, bool isUndefined,
+ QQmlPropertyData::WriteFlags flags) Q_DECL_OVERRIDE Q_DECL_FINAL
+ {
+ QQmlPropertyData pd = getPropertyData();
+ if (Q_UNLIKELY(isUndefined || pd.isValueTypeVirtual()))
+ return slowWrite(pd, result, isUndefined, flags);
+
+ // Check if the result is a QObject:
+ QObject *resultObject = nullptr;
+ QQmlMetaObject resultMo;
+ if (result.isNull()) {
+ // Special case: we can always write a nullptr. Don't bother checking anything else.
+ return pd.writeProperty(targetObject(), &resultObject, flags);
+ } else if (auto wrapper = result.as<QV4::QObjectWrapper>()) {
+ resultObject = wrapper->object();
+ if (!resultObject)
+ return pd.writeProperty(targetObject(), &resultObject, flags);
+ if (QQmlData *ddata = QQmlData::get(resultObject, false))
+ resultMo = ddata->propertyCache;
+ if (resultMo.isNull()) {
+ resultMo = resultObject->metaObject();
+ }
+ } else if (auto variant = result.as<QV4::VariantObject>()) {
+ QVariant value = variant->d()->data;
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context());
+ resultMo = QQmlPropertyPrivate::rawMetaObjectForType(ep, value.userType());
+ if (resultMo.isNull())
+ return slowWrite(pd, result, isUndefined, flags);
+ resultObject = *static_cast<QObject *const *>(value.constData());
+ } else {
+ return slowWrite(pd, result, isUndefined, flags);
+ }
+
+ // Compare & set:
+ if (QQmlMetaObject::canConvert(resultMo, targetMetaObject)) {
+ return pd.writeProperty(targetObject(), &resultObject, flags);
+ } else if (!resultObject && QQmlMetaObject::canConvert(targetMetaObject, resultMo)) {
+ // In the case of a null QObject, we assign the null if there is
+ // any change that the null variant type could be up or down cast to
+ // the property type.
+ return pd.writeProperty(targetObject(), &resultObject, flags);
+ } else {
+ return slowWrite(pd, result, isUndefined, flags);
+ }
+ }
+};
+
+QQmlBinding *QQmlBinding::newBinding(QQmlEnginePrivate *engine, const QQmlPropertyData *property)
{
+ if (property && property->isQObject())
+ return new QObjectPointerBinding(engine, property->propType);
+
const int type = (property && property->isFullyResolved()) ? property->propType : QMetaType::UnknownType;
if (type == qMetaTypeId<QQmlBinding *>()) {
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index a7c90603f6..67fbeb693e 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -87,9 +87,9 @@ public:
void refresh() Q_DECL_OVERRIDE;
- void setEnabled(bool, QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding) Q_DECL_OVERRIDE;
+ void setEnabled(bool, QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding) Q_DECL_OVERRIDE;
QString expression() const Q_DECL_OVERRIDE;
- void update(QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding);
+ void update(QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding);
typedef int Identifier;
enum {
@@ -103,7 +103,7 @@ public:
protected:
virtual void doUpdate(QQmlBinding *binding, const DeleteWatcher &watcher,
- QQmlPropertyPrivate::WriteFlags flags, QV4::Scope &scope,
+ QQmlPropertyData::WriteFlags flags, QV4::Scope &scope,
const QV4::ScopedFunctionObject &f) = 0;
QQmlPropertyData getPropertyData() const;
@@ -111,7 +111,7 @@ protected:
int getPropertyType() const;
bool slowWrite(const QQmlPropertyData &core, const QV4::Value &result, bool isUndefined,
- QQmlPropertyPrivate::WriteFlags flags);
+ QQmlPropertyData::WriteFlags flags);
private:
inline bool updatingFlag() const;
@@ -119,7 +119,7 @@ private:
inline bool enabledFlag() const;
inline void setEnabledFlag(bool);
- static QQmlBinding *newBinding(const QQmlPropertyData *property);
+ static QQmlBinding *newBinding(QQmlEnginePrivate *engine, const QQmlPropertyData *property);
};
bool QQmlBinding::updatingFlag() const
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 854090f20b..9c7b4fe1c0 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -874,11 +874,13 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
depthIncreased = false;
}
- QQmlEngineDebugService *service = QQmlDebugConnector::service<QQmlEngineDebugService>();
- if (service && rv) {
- if (!context->isInternal)
- context->asQQmlContextPrivate()->instances.append(rv);
- service->objectCreated(engine, rv);
+ if (rv) {
+ if (QQmlEngineDebugService *service =
+ QQmlDebugConnector::service<QQmlEngineDebugService>()) {
+ if (!context->isInternal)
+ context->asQQmlContextPrivate()->instances.append(rv);
+ service->objectCreated(engine, rv);
+ }
}
return rv;
@@ -1133,7 +1135,7 @@ static void QQmlComponent_setQmlParent(QObject *me, QObject *parent)
}
/*!
- \qmlmethod object Component::createObject(Item parent, object properties)
+ \qmlmethod object Component::createObject(QtObject parent, object properties)
Creates and returns an object instance of this component that will have
the given \a parent and \a properties. The \a properties argument is optional.
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index d391f38b61..5cfb546718 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -57,7 +57,6 @@
#include "qqmllist_p.h"
#include "qqmltypenamecache_p.h"
#include "qqmlnotifier_p.h"
-#include <private/qqmldebugconnector_p.h>
#include "qqmlincubator.h"
#include "qqmlabstracturlinterceptor.h"
#include <private/qqmlboundsignal_p.h>
@@ -603,7 +602,10 @@ the same object as is returned from the Qt.include() call.
QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
: propertyCapture(0), rootContext(0),
- profiler(0), outputWarningsToMsgLog(true),
+#ifndef QT_NO_QML_DEBUGGER
+ profiler(0),
+#endif
+ outputWarningsToMsgLog(true),
cleanup(0), erroredBindings(0), inProgressCreations(0),
workerScriptEngine(0),
activeObjectCreator(0),
@@ -646,12 +648,9 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
QMetaType::unregisterType(iter.value()->metaTypeId);
QMetaType::unregisterType(iter.value()->listMetaTypeId);
}
+#ifndef QT_NO_QML_DEBUGGER
delete profiler;
-}
-
-void QQmlEnginePrivate::enableProfiler()
-{
- profiler = new QQmlProfiler();
+#endif
}
void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
@@ -848,8 +847,8 @@ void QQmlData::flushPendingBindingImpl(int coreIndex)
b = b->nextBinding();
if (b && b->targetPropertyIndex() == coreIndex)
- b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::DontRemoveBinding);
+ b->setEnabled(true, QQmlPropertyData::BypassInterceptor |
+ QQmlPropertyData::DontRemoveBinding);
}
bool QQmlEnginePrivate::baseModulesUninitialized = true;
@@ -1714,6 +1713,8 @@ void QQmlData::destroyed(QObject *object)
if (ownMemory)
delete this;
+ else
+ this->~QQmlData();
}
DEFINE_BOOL_CONFIG_OPTION(parentTest, QML_PARENT_TEST);
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index bd4b4e536e..949060f395 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -134,8 +134,12 @@ public:
QRecyclePool<QQmlJavaScriptExpressionGuard> jsExpressionGuardPool;
QQmlContext *rootContext;
+
+#ifdef QT_NO_QML_DEBUGGER
+ static const quintptr profiler = 0;
+#else
QQmlProfiler *profiler;
- void enableProfiler();
+#endif
bool outputWarningsToMsgLog;
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 7cb7047b04..b354104b6e 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -89,9 +89,12 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QV4::Compil
sharedState->creationContext = creationContext;
sharedState->rootContext = 0;
- QQmlProfiler *profiler = QQmlEnginePrivate::get(engine)->profiler;
- Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler,
- sharedState->profiler.init(profiler, compilationUnit->totalParserStatusCount));
+ if (auto profiler = QQmlEnginePrivate::get(engine)->profiler) {
+ Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler,
+ sharedState->profiler.init(profiler, compilationUnit->totalParserStatusCount));
+ } else {
+ Q_UNUSED(profiler);
+ }
}
QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QV4::CompiledData::CompilationUnit *compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState)
@@ -275,11 +278,7 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
{
- QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
- int propertyWriteStatus = -1;
- void *argv[] = { 0, 0, &propertyWriteStatus, &propertyWriteFlags };
-
+ QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor | QQmlPropertyData::RemoveBindingOnAliasWrite;
QV4::Scope scope(v4);
int propertyType = property->propType;
@@ -307,16 +306,14 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
} else {
int i = int(n);
QVariant value(i);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
} else {
if (property->isVarProperty()) {
_vmeMetaObject->setVMEProperty(property->coreIndex, QV4::Primitive::fromDouble(n));
} else {
QVariant value(n);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
}
} else if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
@@ -324,8 +321,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
_vmeMetaObject->setVMEProperty(property->coreIndex, QV4::Primitive::fromBoolean(binding->valueAsBoolean()));
} else {
QVariant value(binding->valueAsBoolean());
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
} else {
QString stringValue = binding->valueAsString(qmlUnit);
@@ -334,8 +330,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
_vmeMetaObject->setVMEProperty(property->coreIndex, s);
} else {
QVariant value = QQmlStringConverters::variantFromString(stringValue);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
}
}
@@ -343,26 +338,19 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
case QVariant::String: {
Q_ASSERT(binding->evaluatesToString());
QString value = binding->valueAsString(qmlUnit);
- if (property->hasAccessors()) {
- property->accessors->write(_qobject, &value);
- } else {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- }
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::StringList: {
Q_ASSERT(binding->evaluatesToString());
QStringList value(binding->valueAsString(qmlUnit));
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::ByteArray: {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
QByteArray value(binding->valueAsString(qmlUnit).toUtf8());
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Url: {
@@ -374,16 +362,14 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
// Apply URL interceptor
if (engine->urlInterceptor())
value = engine->urlInterceptor()->intercept(value, QQmlAbstractUrlInterceptor::UrlString);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::UInt: {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
double d = binding->valueAsNumber();
uint value = uint(d);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
}
break;
@@ -391,35 +377,20 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
double d = binding->valueAsNumber();
int value = int(d);
- if (property->hasAccessors()) {
- property->accessors->write(_qobject, &value);
- } else {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- }
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
}
break;
case QMetaType::Float: {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
float value = float(binding->valueAsNumber());
- if (property->hasAccessors()) {
- property->accessors->write(_qobject, &value);
- } else {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- }
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Double: {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
double value = binding->valueAsNumber();
- if (property->hasAccessors()) {
- property->accessors->write(_qobject, &value);
- } else {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- }
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Color: {
@@ -428,8 +399,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
Q_ASSERT(ok);
struct { void *data[4]; } buffer;
if (QQml_valueTypeProvider()->storeValueType(property->propType, &colorValue, &buffer, sizeof(buffer))) {
- argv[0] = reinterpret_cast<void *>(&buffer);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &buffer, propertyWriteFlags);
}
}
break;
@@ -438,16 +408,14 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
bool ok = false;
QDate value = QQmlStringConverters::dateFromString(binding->valueAsString(qmlUnit), &ok);
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Time: {
bool ok = false;
QTime value = QQmlStringConverters::timeFromString(binding->valueAsString(qmlUnit), &ok);
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::DateTime: {
@@ -460,8 +428,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
value = QDateTime(QDate::fromJulianDay(date), QTime::fromMSecsSinceStartOfDay(msecsSinceStartOfDay));
}
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
#endif // QT_NO_DATESTRING
@@ -469,59 +436,59 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
bool ok = false;
QPoint value = QQmlStringConverters::pointFFromString(binding->valueAsString(qmlUnit), &ok).toPoint();
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::PointF: {
bool ok = false;
QPointF value = QQmlStringConverters::pointFFromString(binding->valueAsString(qmlUnit), &ok);
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Size: {
bool ok = false;
QSize value = QQmlStringConverters::sizeFFromString(binding->valueAsString(qmlUnit), &ok).toSize();
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::SizeF: {
bool ok = false;
QSizeF value = QQmlStringConverters::sizeFFromString(binding->valueAsString(qmlUnit), &ok);
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Rect: {
bool ok = false;
QRect value = QQmlStringConverters::rectFFromString(binding->valueAsString(qmlUnit), &ok).toRect();
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::RectF: {
bool ok = false;
QRectF value = QQmlStringConverters::rectFFromString(binding->valueAsString(qmlUnit), &ok);
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Bool: {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Boolean);
bool value = binding->valueAsBoolean();
- if (property->hasAccessors()) {
- property->accessors->write(_qobject, &value);
- } else {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- }
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
+ }
+ break;
+ case QVariant::Vector2D: {
+ struct {
+ float xp;
+ float yp;
+ } vec;
+ bool ok = QQmlStringConverters::createFromString(QMetaType::QVector2D, binding->valueAsString(qmlUnit), &vec, sizeof(vec));
+ Q_ASSERT(ok);
+ Q_UNUSED(ok);
+ property->writeProperty(_qobject, &vec, propertyWriteFlags);
}
break;
case QVariant::Vector3D: {
@@ -533,8 +500,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
bool ok = QQmlStringConverters::createFromString(QMetaType::QVector3D, binding->valueAsString(qmlUnit), &vec, sizeof(vec));
Q_ASSERT(ok);
Q_UNUSED(ok);
- argv[0] = reinterpret_cast<void *>(&vec);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &vec, propertyWriteFlags);
}
break;
case QVariant::Vector4D: {
@@ -547,8 +513,20 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
bool ok = QQmlStringConverters::createFromString(QMetaType::QVector4D, binding->valueAsString(qmlUnit), &vec, sizeof(vec));
Q_ASSERT(ok);
Q_UNUSED(ok);
- argv[0] = reinterpret_cast<void *>(&vec);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &vec, propertyWriteFlags);
+ }
+ break;
+ case QVariant::Quaternion: {
+ struct {
+ float wp;
+ float xp;
+ float yp;
+ float zp;
+ } vec;
+ bool ok = QQmlStringConverters::createFromString(QMetaType::QQuaternion, binding->valueAsString(qmlUnit), &vec, sizeof(vec));
+ Q_ASSERT(ok);
+ Q_UNUSED(ok);
+ property->writeProperty(_qobject, &vec, propertyWriteFlags);
}
break;
case QVariant::RegExp:
@@ -560,23 +538,20 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
QList<qreal> value;
value.append(binding->valueAsNumber());
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
} else if (property->propType == qMetaTypeId<QList<int> >()) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
double n = binding->valueAsNumber();
QList<int> value;
value.append(int(n));
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
} else if (property->propType == qMetaTypeId<QList<bool> >()) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Boolean);
QList<bool> value;
value.append(binding->valueAsBoolean());
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
} else if (property->propType == qMetaTypeId<QList<QUrl> >()) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
@@ -584,15 +559,13 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
QUrl u = urlString.isEmpty() ? QUrl() : compilationUnit->url().resolved(QUrl(urlString));
QList<QUrl> value;
value.append(u);
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
} else if (property->propType == qMetaTypeId<QList<QString> >()) {
Q_ASSERT(binding->evaluatesToString());
QList<QString> value;
value.append(binding->valueAsString(qmlUnit));
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
} else if (property->propType == qMetaTypeId<QJSValue>()) {
QJSValue value;
@@ -607,8 +580,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
} else {
value = QJSValue(binding->valueAsString(qmlUnit));
}
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
}
@@ -624,8 +596,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
break;
}
- argv[0] = value.data();
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, value.data(), propertyWriteFlags);
}
break;
}
@@ -728,7 +699,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
{
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
Q_ASSERT(stringAt(qmlUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty());
- QV4::CompiledData::CompilationUnit::ResolvedTypeReference *tr = resolvedTypes.value(binding->propertyNameIndex);
+ QV4::CompiledData::ResolvedTypeReference *tr = resolvedTypes.value(binding->propertyNameIndex);
Q_ASSERT(tr);
QQmlType *attachedType = tr->type;
if (!attachedType) {
@@ -755,8 +726,8 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
ss.d.data()->isNumberLiteral = binding->type == QV4::CompiledData::Binding::Type_Number;
ss.d.data()->numberValue = binding->valueAsNumber();
- QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
+ QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor |
+ QQmlPropertyData::RemoveBindingOnAliasWrite;
int propertyWriteStatus = -1;
void *argv[] = { &ss, 0, &propertyWriteStatus, &propertyWriteFlags };
QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
@@ -808,7 +779,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
return false;
if (valueType)
- valueType->write(_qobject, property->coreIndex, QQmlPropertyPrivate::BypassInterceptor);
+ valueType->write(_qobject, property->coreIndex, QQmlPropertyData::BypassInterceptor);
return true;
}
@@ -934,8 +905,8 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
return true;
}
- QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
+ QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor |
+ QQmlPropertyData::RemoveBindingOnAliasWrite;
int propertyWriteStatus = -1;
void *argv[] = { 0, 0, &propertyWriteStatus, &propertyWriteFlags };
@@ -1061,19 +1032,27 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
instance = component;
ddata = QQmlData::get(instance, /*create*/true);
} else {
- QV4::CompiledData::CompilationUnit::ResolvedTypeReference *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
+ QV4::CompiledData::ResolvedTypeReference *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
Q_ASSERT(typeRef);
installPropertyCache = !typeRef->isFullyDynamicType;
QQmlType *type = typeRef->type;
if (type) {
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
compilationUnit, obj, type->qmlTypeName(), context->url()));
- instance = type->create();
+
+ void *ddataMemory = 0;
+ type->create(&instance, &ddataMemory, sizeof(QQmlData));
if (!instance) {
recordError(obj->location, tr("Unable to create object of type %1").arg(stringAt(obj->inheritedTypeNameIndex)));
return 0;
}
+ {
+ QQmlData *ddata = new (ddataMemory) QQmlData;
+ ddata->ownMemory = false;
+ QObjectPrivate::get(instance)->declarativeData = ddata;
+ }
+
const int parserStatusCast = type->parserStatusCast();
if (parserStatusCast != -1)
parserStatus = reinterpret_cast<QQmlParserStatus*>(reinterpret_cast<char *>(instance) + parserStatusCast);
@@ -1213,8 +1192,8 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
QQmlData *data = QQmlData::get(b->targetObject());
Q_ASSERT(data);
data->clearPendingBindingBit(b->targetPropertyIndex());
- b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::DontRemoveBinding);
+ b->setEnabled(true, QQmlPropertyData::BypassInterceptor |
+ QQmlPropertyData::DontRemoveBinding);
if (watcher.hasRecursed() || interrupt.shouldInterrupt())
return 0;
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 2320edf809..e3312f9df5 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -65,7 +65,6 @@ QT_BEGIN_NAMESPACE
class QQmlAbstractBinding;
struct QQmlTypeCompiler;
class QQmlInstantiationInterrupt;
-struct QQmlVmeProfiler;
struct QQmlObjectCreatorSharedState : public QSharedData
{
@@ -139,7 +138,7 @@ private:
const QV4::CompiledData::Unit *qmlUnit;
QQmlGuardedContextData parentContext;
QQmlContextData *context;
- const QHash<int, QV4::CompiledData::CompilationUnit::ResolvedTypeReference*> &resolvedTypes;
+ const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypes;
const QQmlPropertyCacheVector *propertyCaches;
QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState;
bool topLevelCreator;
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp
index 22c4072aec..0fd9e63bde 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -278,7 +278,7 @@ int QQmlOpenMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void *
propertyRead(propId);
*reinterpret_cast<QVariant *>(a[0]) = d->getData(propId);
} else if (c == QMetaObject::WriteProperty) {
- if (propId <= d->data.count() || d->data[propId].first != *reinterpret_cast<QVariant *>(a[0])) {
+ if (propId >= d->data.count() || d->data[propId].first != *reinterpret_cast<QVariant *>(a[0])) {
propertyWrite(propId);
QPair<QVariant, bool> &prop = d->getDataRef(propId);
prop.first = propertyWriteValue(propId, *reinterpret_cast<QVariant *>(a[0]));
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index e04b1114ad..b3eb0a5619 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -42,6 +42,7 @@
#include "qqml.h"
#include "qqmlbinding_p.h"
+#include "qqmlboundsignal_p.h"
#include "qqmlcontext.h"
#include "qqmlcontext_p.h"
#include "qqmlboundsignal_p.h"
@@ -316,8 +317,7 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
if (!property->isQObject())
return; // Not an object property
- void *args[] = { &currentObject, 0 };
- QMetaObject::metacall(currentObject, QMetaObject::ReadProperty, property->coreIndex, args);
+ property->readProperty(currentObject, &currentObject);
if (!currentObject) return; // No value
}
@@ -858,7 +858,7 @@ void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex,
}
-void QQmlPropertyPrivate::setBinding(QQmlAbstractBinding *binding, BindingFlags flags, WriteFlags writeFlags)
+void QQmlPropertyPrivate::setBinding(QQmlAbstractBinding *binding, BindingFlags flags, QQmlPropertyData::WriteFlags writeFlags)
{
Q_ASSERT(binding);
@@ -1034,15 +1034,13 @@ QVariant QQmlPropertyPrivate::readValueProperty()
} else if (core.isQList()) {
QQmlListProperty<QObject> prop;
- void *args[] = { &prop, 0 };
- QMetaObject::metacall(object, QMetaObject::ReadProperty, core.coreIndex, args);
+ core.readProperty(object, &prop);
return QVariant::fromValue(QQmlListReferencePrivate::init(prop, core.propType, engine));
} else if (core.isQObject()) {
QObject *rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(object, QMetaObject::ReadProperty, core.coreIndex, args);
+ core.readProperty(object, &rv);
return QVariant::fromValue(rv);
} else {
@@ -1059,7 +1057,7 @@ QVariant QQmlPropertyPrivate::readValueProperty()
value = QVariant(core.propType, (void*)0);
args[0] = value.data();
}
- QMetaObject::metacall(object, QMetaObject::ReadProperty, core.coreIndex, args);
+ core.readPropertyWithArgs(object, args);
if (core.propType != QMetaType::QVariant && args[0] != value.data())
return QVariant((QVariant::Type)core.propType, args[0]);
@@ -1147,7 +1145,7 @@ bool QQmlPropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int idx,
return status;
}
-bool QQmlPropertyPrivate::writeValueProperty(const QVariant &value, WriteFlags flags)
+bool QQmlPropertyPrivate::writeValueProperty(const QVariant &value, QQmlPropertyData::WriteFlags flags)
{
return writeValueProperty(object, core, value, effectiveContext(), flags);
}
@@ -1156,10 +1154,10 @@ bool
QQmlPropertyPrivate::writeValueProperty(QObject *object,
const QQmlPropertyData &core,
const QVariant &value,
- QQmlContextData *context, WriteFlags flags)
+ QQmlContextData *context,QQmlPropertyData::WriteFlags flags)
{
// Remove any existing bindings on this property
- if (!(flags & DontRemoveBinding) && object)
+ if (!(flags & QQmlPropertyData::DontRemoveBinding) && object)
removeBinding(object, core.encodedIndex());
bool rv = false;
@@ -1189,145 +1187,151 @@ QQmlPropertyPrivate::writeValueProperty(QObject *object,
bool QQmlPropertyPrivate::write(QObject *object,
const QQmlPropertyData &property,
const QVariant &value, QQmlContextData *context,
- WriteFlags flags)
+ QQmlPropertyData::WriteFlags flags)
{
- int coreIdx = property.coreIndex;
- int status = -1; //for dbus
+ const int propertyType = property.propType;
+ const int variantType = value.userType();
if (property.isEnum()) {
QMetaProperty prop = object->metaObject()->property(property.coreIndex);
QVariant v = value;
// Enum values come through the script engine as doubles
- if (value.userType() == QVariant::Double) {
+ if (variantType == QVariant::Double) {
double integral;
double fractional = std::modf(value.toDouble(), &integral);
if (qFuzzyIsNull(fractional))
v.convert(QVariant::Int);
}
- return writeEnumProperty(prop, coreIdx, object, v, flags);
+ return writeEnumProperty(prop, property.coreIndex, object, v, flags);
}
- int propertyType = property.propType;
- int variantType = value.userType();
-
QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(context);
+ const bool isUrl = propertyType == QVariant::Url; // handled separately
+
+ // The cases below are in approximate order of likelyhood:
+ if (propertyType == variantType && !isUrl && propertyType != qMetaTypeId<QList<QUrl>>() && !property.isQList()) {
+ return property.writeProperty(object, const_cast<void *>(value.constData()), flags);
+ } else if (property.isQObject()) {
+ QQmlMetaObject valMo = rawMetaObjectForType(enginePriv, variantType);
+ if (valMo.isNull())
+ return false;
+ QObject *o = *static_cast<QObject *const *>(value.constData());
+ QQmlMetaObject propMo = rawMetaObjectForType(enginePriv, propertyType);
- if (propertyType == QVariant::Url) {
+ if (o)
+ valMo = o;
+ if (QQmlMetaObject::canConvert(valMo, propMo)) {
+ return property.writeProperty(object, &o, flags);
+ } else if (!o && QQmlMetaObject::canConvert(propMo, valMo)) {
+ // In the case of a null QObject, we assign the null if there is
+ // any change that the null variant type could be up or down cast to
+ // the property type.
+ return property.writeProperty(object, &o, flags);
+ } else {
+ return false;
+ }
+ } else if (value.canConvert(propertyType) && !isUrl && variantType != QVariant::String && propertyType != qMetaTypeId<QList<QUrl>>() && !property.isQList()) {
+ // common cases:
+ switch (propertyType) {
+ case QMetaType::Bool: {
+ bool b = value.toBool();
+ return property.writeProperty(object, &b, flags);
+ }
+ case QMetaType::Int: {
+ int i = value.toInt();
+ return property.writeProperty(object, &i, flags);
+ }
+ case QMetaType::Double: {
+ double d = value.toDouble();
+ return property.writeProperty(object, &d, flags);
+ }
+ case QMetaType::Float: {
+ float f = value.toFloat();
+ return property.writeProperty(object, &f, flags);
+ }
+ case QMetaType::QString: {
+ QString s = value.toString();
+ return property.writeProperty(object, &s, flags);
+ }
+ default: { // "fallback":
+ QVariant v = value;
+ v.convert(propertyType);
+ return property.writeProperty(object, const_cast<void *>(v.constData()), flags);
+ }
+ }
+ } else if (propertyType == qMetaTypeId<QVariant>()) {
+ return property.writeProperty(object, const_cast<QVariant *>(&value), flags);
+ } else if (isUrl) {
QUrl u;
- bool found = false;
if (variantType == QVariant::Url) {
u = value.toUrl();
- found = true;
} else if (variantType == QVariant::ByteArray) {
QString input(QString::fromUtf8(value.toByteArray()));
// Encoded dir-separators defeat QUrl processing - decode them first
input.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
u = QUrl(input);
- found = true;
} else if (variantType == QVariant::String) {
QString input(value.toString());
// Encoded dir-separators defeat QUrl processing - decode them first
input.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
u = QUrl(input);
- found = true;
- }
-
- if (!found)
- return false;
-
- if (context && u.isRelative() && !u.isEmpty())
- u = context->resolvedUrl(u);
- int status = -1;
- void *argv[] = { &u, 0, &status, &flags };
- QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv);
-
- } else if (propertyType == qMetaTypeId<QList<QUrl> >()) {
- QList<QUrl> urlSeq = resolvedUrlSequence(value, context).value<QList<QUrl> >();
- int status = -1;
- void *argv[] = { &urlSeq, 0, &status, &flags };
- QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv);
- } else if (variantType == propertyType) {
-
- void *a[] = { const_cast<void *>(value.constData()), 0, &status, &flags };
- QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
-
- } else if (qMetaTypeId<QVariant>() == propertyType) {
-
- void *a[] = { const_cast<QVariant *>(&value), 0, &status, &flags };
- QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
-
- } else if (property.isQObject()) {
-
- QQmlMetaObject valMo = rawMetaObjectForType(enginePriv, value.userType());
-
- if (valMo.isNull())
- return false;
-
- QObject *o = *(QObject *const *)value.constData();
- QQmlMetaObject propMo = rawMetaObjectForType(enginePriv, propertyType);
-
- if (o) valMo = o;
-
- if (QQmlMetaObject::canConvert(valMo, propMo)) {
- void *args[] = { &o, 0, &status, &flags };
- QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, args);
- } else if (!o && QQmlMetaObject::canConvert(propMo, valMo)) {
- // In the case of a null QObject, we assign the null if there is
- // any change that the null variant type could be up or down cast to
- // the property type.
- void *args[] = { &o, 0, &status, &flags };
- QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, args);
} else {
return false;
}
+ if (context && u.isRelative() && !u.isEmpty())
+ u = context->resolvedUrl(u);
+ return property.writeProperty(object, &u, flags);
+ } else if (propertyType == qMetaTypeId<QList<QUrl>>()) {
+ QList<QUrl> urlSeq = resolvedUrlSequence(value, context).value<QList<QUrl>>();
+ return property.writeProperty(object, &urlSeq, flags);
} else if (property.isQList()) {
-
QQmlMetaObject listType;
if (enginePriv) {
listType = enginePriv->rawMetaObjectForType(enginePriv->listType(property.propType));
} else {
QQmlType *type = QQmlMetaType::qmlType(QQmlMetaType::listType(property.propType));
- if (!type) return false;
+ if (!type)
+ return false;
listType = type->baseMetaObject();
}
- if (listType.isNull()) return false;
+ if (listType.isNull())
+ return false;
QQmlListProperty<void> prop;
- void *args[] = { &prop, 0 };
- QMetaObject::metacall(object, QMetaObject::ReadProperty, coreIdx, args);
+ property.readProperty(object, &prop);
- if (!prop.clear) return false;
+ if (!prop.clear)
+ return false;
prop.clear(&prop);
- if (value.userType() == qMetaTypeId<QQmlListReference>()) {
+ if (variantType == qMetaTypeId<QQmlListReference>()) {
QQmlListReference qdlr = value.value<QQmlListReference>();
for (int ii = 0; ii < qdlr.count(); ++ii) {
QObject *o = qdlr.at(ii);
if (o && !QQmlMetaObject::canConvert(o, listType))
- o = 0;
- prop.append(&prop, (void *)o);
+ o = nullptr;
+ prop.append(&prop, o);
}
- } else if (value.userType() == qMetaTypeId<QList<QObject *> >()) {
+ } else if (variantType == qMetaTypeId<QList<QObject *> >()) {
const QList<QObject *> &list = qvariant_cast<QList<QObject *> >(value);
for (int ii = 0; ii < list.count(); ++ii) {
QObject *o = list.at(ii);
if (o && !QQmlMetaObject::canConvert(o, listType))
- o = 0;
- prop.append(&prop, (void *)o);
+ o = nullptr;
+ prop.append(&prop, o);
}
} else {
QObject *o = enginePriv?enginePriv->toQObject(value):QQmlMetaType::toQObject(value);
if (o && !QQmlMetaObject::canConvert(o, listType))
- o = 0;
- prop.append(&prop, (void *)o);
+ o = nullptr;
+ prop.append(&prop, o);
}
-
} else {
Q_ASSERT(variantType != propertyType);
@@ -1367,7 +1371,8 @@ bool QQmlPropertyPrivate::write(QObject *object,
// successful conversion.
Q_ASSERT(v.userType() == propertyType);
ok = true;
- } else if ((uint)propertyType >= QVariant::UserType && variantType == QVariant::String) {
+ } else if (static_cast<uint>(propertyType) >= QVariant::UserType &&
+ variantType == QVariant::String) {
QQmlMetaType::StringConverter con = QQmlMetaType::customStringConverter(propertyType);
if (con) {
v = con(value.toString());
@@ -1410,8 +1415,7 @@ bool QQmlPropertyPrivate::write(QObject *object,
}
if (ok) {
- void *a[] = { const_cast<void *>(v.constData()), 0, &status, &flags};
- QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
+ return property.writeProperty(object, const_cast<void *>(v.constData()), flags);
} else {
return false;
}
@@ -1427,10 +1431,9 @@ QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engi
return metaType.metaObject();
if (engine)
return engine->rawMetaObjectForType(userType);
- QQmlType *type = QQmlMetaType::qmlType(userType);
- if (type)
+ if (QQmlType *type = QQmlMetaType::qmlType(userType))
return QQmlMetaObject(type->baseMetaObject());
- return QQmlMetaObject((QObject*)0);
+ return QQmlMetaObject();
}
/*!
@@ -1512,7 +1515,7 @@ bool QQmlProperty::reset() const
}
bool QQmlPropertyPrivate::write(const QQmlProperty &that,
- const QVariant &value, WriteFlags flags)
+ const QVariant &value, QQmlPropertyData::WriteFlags flags)
{
if (!that.d)
return false;
diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h
index 58fea9c239..9398c74621 100644
--- a/src/qml/qml/qqmlproperty_p.h
+++ b/src/qml/qml/qqmlproperty_p.h
@@ -68,13 +68,6 @@ class QQmlJavaScriptExpression;
class Q_QML_PRIVATE_EXPORT QQmlPropertyPrivate : public QQmlRefCount
{
public:
- enum WriteFlag {
- BypassInterceptor = 0x01,
- DontRemoveBinding = 0x02,
- RemoveBindingOnAliasWrite = 0x04
- };
- Q_DECLARE_FLAGS(WriteFlags, WriteFlag)
-
QQmlContextData *context;
QPointer<QQmlEngine> engine;
QPointer<QObject> object;
@@ -97,7 +90,7 @@ public:
QQmlProperty::PropertyTypeCategory propertyTypeCategory() const;
QVariant readValueProperty();
- bool writeValueProperty(const QVariant &, WriteFlags);
+ bool writeValueProperty(const QVariant &, QQmlPropertyData::WriteFlags);
static QQmlMetaObject rawMetaObjectForType(QQmlEnginePrivate *, int);
static bool writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object,
@@ -105,9 +98,9 @@ public:
static bool writeValueProperty(QObject *,
const QQmlPropertyData &,
const QVariant &, QQmlContextData *,
- WriteFlags flags = 0);
+ QQmlPropertyData::WriteFlags flags = 0);
static bool write(QObject *, const QQmlPropertyData &, const QVariant &,
- QQmlContextData *, WriteFlags flags = 0);
+ QQmlContextData *, QQmlPropertyData::WriteFlags flags = 0);
static void findAliasTarget(QObject *, int, QObject **, int *);
enum BindingFlag {
@@ -116,7 +109,7 @@ public:
};
Q_DECLARE_FLAGS(BindingFlags, BindingFlag)
- static void setBinding(QQmlAbstractBinding *binding, BindingFlags flags = None, WriteFlags writeFlags = DontRemoveBinding);
+ static void setBinding(QQmlAbstractBinding *binding, BindingFlags flags = None, QQmlPropertyData::WriteFlags writeFlags = QQmlPropertyData::DontRemoveBinding);
static void removeBinding(const QQmlProperty &that);
static void removeBinding(QObject *o, int index);
@@ -144,7 +137,7 @@ public:
QQmlBoundSignalExpression *);
static void takeSignalExpression(const QQmlProperty &that,
QQmlBoundSignalExpression *);
- static bool write(const QQmlProperty &that, const QVariant &, WriteFlags);
+ static bool write(const QQmlProperty &that, const QVariant &, QQmlPropertyData::WriteFlags);
static int valueTypeCoreIndex(const QQmlProperty &that);
static int bindingIndex(const QQmlProperty &that);
static int bindingIndex(const QQmlPropertyData &that);
@@ -157,7 +150,6 @@ public:
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 502557fa9f..322e519706 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -1246,6 +1246,215 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
}
}
+namespace {
+template <typename StringVisitor, typename TypeInfoVisitor>
+int visitMethods(const QMetaObject &mo, int methodOffset, int methodCount,
+ StringVisitor visitString, TypeInfoVisitor visitTypeInfo)
+{
+ const int intsPerMethod = 5;
+
+ int fieldsForParameterData = 0;
+
+ bool hasRevisionedMethods = false;
+
+ for (int i = 0; i < methodCount; ++i) {
+ const int handle = methodOffset + i * intsPerMethod;
+
+ const uint flags = mo.d.data[handle + 4];
+ if (flags & MethodRevisioned)
+ hasRevisionedMethods = true;
+
+ visitString(mo.d.data[handle + 0]); // name
+ visitString(mo.d.data[handle + 3]); // tag
+
+ const int argc = mo.d.data[handle + 1];
+ const int paramIndex = mo.d.data[handle + 2];
+
+ fieldsForParameterData += argc * 2; // type and name
+ fieldsForParameterData += 1; // + return type
+
+ // return type + args
+ for (int i = 0; i < 1 + argc; ++i) {
+ // type name (maybe)
+ visitTypeInfo(mo.d.data[paramIndex + i]);
+
+ // parameter name
+ if (i > 0)
+ visitString(mo.d.data[paramIndex + argc + i]);
+ }
+ }
+
+ int fieldsForRevisions = 0;
+ if (hasRevisionedMethods)
+ fieldsForRevisions = methodCount;
+
+ return methodCount * intsPerMethod + fieldsForRevisions + fieldsForParameterData;
+}
+
+template <typename StringVisitor, typename TypeInfoVisitor>
+int visitProperties(const QMetaObject &mo, StringVisitor visitString, TypeInfoVisitor visitTypeInfo)
+{
+ const QMetaObjectPrivate *const priv = reinterpret_cast<const QMetaObjectPrivate*>(mo.d.data);
+ const int intsPerProperty = 3;
+
+ bool hasRevisionedProperties = false;
+ bool hasNotifySignals = false;
+
+ for (int i = 0; i < priv->propertyCount; ++i) {
+ const int handle = priv->propertyData + i * intsPerProperty;
+
+ const auto flags = mo.d.data[handle + 2];
+ if (flags & Revisioned) {
+ hasRevisionedProperties = true;
+ }
+ if (flags & Notify)
+ hasNotifySignals = true;
+
+ visitString(mo.d.data[handle]); // name
+ visitTypeInfo(mo.d.data[handle + 1]);
+ }
+
+ int fieldsForPropertyRevisions = 0;
+ if (hasRevisionedProperties)
+ fieldsForPropertyRevisions = priv->propertyCount;
+
+ int fieldsForNotifySignals = 0;
+ if (hasNotifySignals)
+ fieldsForNotifySignals = priv->propertyCount;
+
+ return priv->propertyCount * intsPerProperty + fieldsForPropertyRevisions
+ + fieldsForNotifySignals;
+}
+
+template <typename StringVisitor>
+int visitClassInfo(const QMetaObject &mo, StringVisitor visitString)
+{
+ const QMetaObjectPrivate *const priv = reinterpret_cast<const QMetaObjectPrivate*>(mo.d.data);
+ const int intsPerClassInfo = 2;
+
+ for (int i = 0; i < priv->classInfoCount; ++i) {
+ const int handle = priv->classInfoData + i * intsPerClassInfo;
+
+ visitString(mo.d.data[handle]); // key
+ visitString(mo.d.data[handle + 1]); // value
+ }
+
+ return priv->classInfoCount * intsPerClassInfo;
+}
+
+template <typename StringVisitor>
+int visitEnumerations(const QMetaObject &mo, StringVisitor visitString)
+{
+ const QMetaObjectPrivate *const priv = reinterpret_cast<const QMetaObjectPrivate*>(mo.d.data);
+ const int intsPerEnumerator = 4;
+
+ int fieldCount = priv->enumeratorCount * intsPerEnumerator;
+
+ for (int i = 0; i < priv->enumeratorCount; ++i) {
+ const uint *enumeratorData = mo.d.data + priv->enumeratorData + i * intsPerEnumerator;
+
+ const uint keyCount = enumeratorData[2];
+ fieldCount += keyCount * 2;
+
+ visitString(enumeratorData[0]); // name
+
+ const uint keyOffset = enumeratorData[3];
+
+ for (uint j = 0; j < keyCount; ++j) {
+ visitString(mo.d.data[keyOffset + 2 * j]);
+ }
+ }
+
+ return fieldCount;
+}
+
+template <typename StringVisitor>
+int countMetaObjectFields(const QMetaObject &mo, StringVisitor stringVisitor)
+{
+ const QMetaObjectPrivate *const priv = reinterpret_cast<const QMetaObjectPrivate*>(mo.d.data);
+
+ const auto typeInfoVisitor = [&stringVisitor](uint typeInfo) {
+ if (typeInfo & IsUnresolvedType)
+ stringVisitor(typeInfo & TypeNameIndexMask);
+ };
+
+ int fieldCount = MetaObjectPrivateFieldCount;
+
+ fieldCount += visitMethods(mo, priv->methodData, priv->methodCount, stringVisitor,
+ typeInfoVisitor);
+ fieldCount += visitMethods(mo, priv->constructorData, priv->constructorCount, stringVisitor,
+ typeInfoVisitor);
+
+ fieldCount += visitProperties(mo, stringVisitor, typeInfoVisitor);
+ fieldCount += visitClassInfo(mo, stringVisitor);
+ fieldCount += visitEnumerations(mo, stringVisitor);
+
+ return fieldCount;
+}
+
+} // anonymous namespace
+
+bool QQmlPropertyCache::determineMetaObjectSizes(const QMetaObject &mo, int *fieldCount,
+ int *stringCount)
+{
+ const QMetaObjectPrivate *priv = reinterpret_cast<const QMetaObjectPrivate*>(mo.d.data);
+ if (priv->revision != 7) {
+ return false;
+ }
+
+ uint highestStringIndex = 0;
+ const auto stringIndexVisitor = [&highestStringIndex](uint index) {
+ highestStringIndex = qMax(highestStringIndex, index);
+ };
+
+ *fieldCount = countMetaObjectFields(mo, stringIndexVisitor);
+ *stringCount = highestStringIndex + 1;
+
+ return true;
+}
+
+bool QQmlPropertyCache::addToHash(QCryptographicHash &hash, const QMetaObject &mo)
+{
+ int fieldCount = 0;
+ int stringCount = 0;
+ if (!determineMetaObjectSizes(mo, &fieldCount, &stringCount)) {
+ return false;
+ }
+
+ hash.addData(reinterpret_cast<const char *>(mo.d.data), fieldCount * sizeof(uint));
+ for (int i = 0; i < stringCount; ++i) {
+ const QByteArrayDataPtr data = { const_cast<QByteArrayData*>(&mo.d.stringdata[i]) };
+ hash.addData(QByteArray(data));
+ }
+
+ return true;
+}
+
+QByteArray QQmlPropertyCache::checksum(bool *ok)
+{
+ if (!_checksum.isEmpty()) {
+ *ok = true;
+ return _checksum;
+ }
+
+ QCryptographicHash hash(QCryptographicHash::Md5);
+
+ if (_parent) {
+ hash.addData(_parent->checksum(ok));
+ if (!*ok)
+ return QByteArray();
+ }
+
+ if (!addToHash(hash, *createMetaObject())) {
+ *ok = false;
+ return QByteArray();
+ }
+
+ _checksum = hash.result();
+ *ok = !_checksum.isEmpty();
+ return _checksum;
+}
+
/*! \internal
\a index MUST be in the signal index range (see QObjectPrivate::signalIndex()).
This is different from QMetaMethod::methodIndex().
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index baba5347a7..750537e707 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -61,9 +61,11 @@
#include <QtCore/qvector.h>
#include <private/qv4value_p.h>
+#include <private/qqmlaccessors_p.h>
QT_BEGIN_NAMESPACE
+class QCryptographicHash;
class QMetaProperty;
class QQmlEngine;
class QJSEngine;
@@ -228,6 +230,13 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyRawData::Flags)
class QQmlPropertyData : public QQmlPropertyRawData
{
public:
+ enum WriteFlag {
+ BypassInterceptor = 0x01,
+ DontRemoveBinding = 0x02,
+ RemoveBindingOnAliasWrite = 0x04
+ };
+ Q_DECLARE_FLAGS(WriteFlags, WriteFlag)
+
inline QQmlPropertyData();
inline QQmlPropertyData(const QQmlPropertyRawData &);
@@ -241,6 +250,33 @@ public:
void markAsOverrideOf(QQmlPropertyData *predecessor);
+ inline void readProperty(QObject *target, void *property) const
+ {
+ void *args[] = { property, 0 };
+ readPropertyWithArgs(target, args);
+ }
+
+ inline void readPropertyWithArgs(QObject *target, void *args[]) const
+ {
+ if (hasAccessors()) {
+ accessors->read(target, args[0]);
+ } else {
+ QMetaObject::metacall(target, QMetaObject::ReadProperty, coreIndex, args);
+ }
+ }
+
+ bool writeProperty(QObject *target, void *value, WriteFlags flags) const
+ {
+ if (flags.testFlag(BypassInterceptor) && hasAccessors() && accessors->write) {
+ accessors->write(target, value);
+ } else {
+ int status = -1;
+ void *argv[] = { value, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty, coreIndex, argv);
+ }
+ return true;
+ }
+
private:
friend class QQmlPropertyCache;
void lazyLoad(const QMetaProperty &);
@@ -331,6 +367,11 @@ public:
void toMetaObjectBuilder(QMetaObjectBuilder &);
+ static bool determineMetaObjectSizes(const QMetaObject &mo, int *fieldCount, int *stringCount);
+ static bool addToHash(QCryptographicHash &hash, const QMetaObject &mo);
+
+ QByteArray checksum(bool *ok);
+
protected:
virtual void destroy();
virtual void clear();
@@ -400,6 +441,7 @@ private:
QByteArray _dynamicStringData;
QString _defaultPropertyName;
QQmlPropertyCacheMethodArguments *argumentsCache;
+ QByteArray _checksum;
};
// QQmlMetaObject serves as a wrapper around either QMetaObject or QQmlPropertyCache.
@@ -770,6 +812,8 @@ private:
QVector<QFlagPointer<QQmlPropertyCache>> data;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyData::WriteFlags)
+
QT_END_NAMESPACE
#endif // QQMLPROPERTYCACHE_P_H
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 52fed14ecb..5bc9c8ac25 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -54,6 +54,7 @@
#include <QtCore/qdir.h>
#include <QtCore/qfile.h>
+#include <QtCore/qdatetime.h>
#include <QtCore/qdebug.h>
#include <QtCore/qmutex.h>
#include <QtCore/qthread.h>
@@ -61,8 +62,11 @@
#include <QtCore/qdiriterator.h>
#include <QtQml/qqmlcomponent.h>
#include <QtCore/qwaitcondition.h>
+#include <QtCore/qloggingcategory.h>
#include <QtQml/qqmlextensioninterface.h>
+#include <functional>
+
#if defined (Q_OS_UNIX)
#include <sys/types.h>
#include <sys/stat.h>
@@ -102,6 +106,9 @@ DEFINE_BOOL_CONFIG_OPTION(dumpErrors, QML_DUMP_ERRORS);
DEFINE_BOOL_CONFIG_OPTION(diskCache, QML_DISK_CACHE);
DEFINE_BOOL_CONFIG_OPTION(forceDiskCacheRefresh, QML_FORCE_DISK_CACHE_REFRESH);
+Q_DECLARE_LOGGING_CATEGORY(DBG_DISK_CACHE)
+Q_LOGGING_CATEGORY(DBG_DISK_CACHE, "qt.qml.diskcache")
+
QT_BEGIN_NAMESPACE
namespace {
@@ -113,6 +120,20 @@ namespace {
LockHolder(LockType *l) : lock(*l) { lock.lock(); }
~LockHolder() { lock.unlock(); }
};
+
+ struct DeferredCall
+ {
+ std::function<void()> callback;
+ ~DeferredCall() { callback(); }
+ };
+
+ template <typename Callback>
+ DeferredCall defer(Callback &&cb)
+ {
+ DeferredCall c;
+ c.callback = std::move(cb);
+ return c;
+ }
}
#ifndef QT_NO_NETWORK
@@ -2012,7 +2033,7 @@ QQmlTypeData::~QQmlTypeData()
if (QQmlTypeData *tdata = m_compositeSingletons.at(ii).typeData)
tdata->release();
}
- for (QHash<int, TypeReference>::ConstIterator it = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd();
+ for (auto it = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd();
it != end; ++it) {
if (QQmlTypeData *tdata = it->typeData)
tdata->release();
@@ -2057,8 +2078,8 @@ bool QQmlTypeData::tryLoadFromDiskCache()
QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = v4->iselFactory->createUnitForLoading();
{
QString error;
- if (!unit->loadFromDisk(url(), &error)) {
- qDebug() << "Error loading" << url().toString() << "from disk cache:" << error;
+ if (!unit->loadFromDisk(url(), v4->iselFactory.data(), &error)) {
+ qCDebug(DBG_DISK_CACHE) << "Error loading" << url().toString() << "from disk cache:" << error;
return false;
}
}
@@ -2144,8 +2165,18 @@ void QQmlTypeData::rebuildTypeAndPropertyCaches()
void QQmlTypeData::done()
{
+ auto cleanup = defer([this]{
+ m_document.reset();
+ m_typeReferences.clear();
+ if (isError())
+ m_compiledData = nullptr;
+ });
+
+ if (isError())
+ return;
+
// Check all script dependencies for errors
- for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) {
+ for (int ii = 0; ii < m_scripts.count(); ++ii) {
const ScriptReference &script = m_scripts.at(ii);
Q_ASSERT(script.script->isCompleteOrError());
if (script.script->isError()) {
@@ -2157,12 +2188,13 @@ void QQmlTypeData::done()
error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->url().toString()));
errors.prepend(error);
setError(errors);
+ return;
}
}
// Check all type dependencies for errors
- for (QHash<int, TypeReference>::ConstIterator it = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd();
- !isError() && it != end; ++it) {
+ for (auto it = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd(); it != end;
+ ++it) {
const TypeReference &type = *it;
Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError());
if (type.typeData && type.typeData->isError()) {
@@ -2176,11 +2208,12 @@ void QQmlTypeData::done()
error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
errors.prepend(error);
setError(errors);
+ return;
}
}
// Check all composite singleton type dependencies for errors
- for (int ii = 0; !isError() && ii < m_compositeSingletons.count(); ++ii) {
+ for (int ii = 0; ii < m_compositeSingletons.count(); ++ii) {
const TypeReference &type = m_compositeSingletons.at(ii);
Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError());
if (type.typeData && type.typeData->isError()) {
@@ -2194,19 +2227,21 @@ void QQmlTypeData::done()
error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
errors.prepend(error);
setError(errors);
+ return;
}
}
- if (!isError()) {
- if (!m_document.isNull()) {
- // Compile component
- compile();
- } else {
- rebuildTypeAndPropertyCaches();
- }
+ if (!m_document.isNull()) {
+ // Compile component
+ compile();
+ } else {
+ rebuildTypeAndPropertyCaches();
}
- if (!isError()) {
+ if (isError())
+ return;
+
+ {
QQmlEnginePrivate * const engine = QQmlEnginePrivate::get(typeLoader()->engine());
{
// Sanity check property bindings
@@ -2214,23 +2249,26 @@ void QQmlTypeData::done()
QVector<QQmlCompileError> errors = validator.validate();
if (!errors.isEmpty()) {
setError(errors);
+ return;
}
}
m_compiledData->finalize(engine);
}
- if (!isError()) {
+ {
QQmlType *type = QQmlMetaType::qmlType(finalUrl(), true);
if (m_compiledData && m_compiledData->data->flags & QV4::CompiledData::Unit::IsSingleton) {
if (!type) {
QQmlError error;
error.setDescription(QQmlTypeLoader::tr("No matching type found, pragma Singleton files cannot be used by QQmlComponent."));
setError(error);
+ return;
} else if (!type->isCompositeSingleton()) {
QQmlError error;
error.setDescription(QQmlTypeLoader::tr("pragma Singleton used with a non composite singleton type %1").arg(type->qmlTypeName()));
setError(error);
+ return;
}
} else {
// If the type is CompositeSingleton but there was no pragma Singleton in the
@@ -2238,11 +2276,12 @@ void QQmlTypeData::done()
if (type && type->isCompositeSingleton()) {
QString typeName = type->qmlTypeName();
setError(QQmlTypeLoader::tr("qmldir defines type as singleton, but no pragma Singleton found in type %1.").arg(typeName));
+ return;
}
}
}
- if (!isError()) {
+ {
// Collect imported scripts
m_compiledData->dependentScripts.reserve(m_scripts.count());
for (int scriptIndex = 0; scriptIndex < m_scripts.count(); ++scriptIndex) {
@@ -2262,12 +2301,7 @@ void QQmlTypeData::done()
scriptData->addref();
m_compiledData->dependentScripts << scriptData;
}
- } else {
- m_compiledData = nullptr;
}
-
- m_document.reset();
- m_typeReferences.clear();
}
void QQmlTypeData::completed()
@@ -2313,7 +2347,7 @@ void QQmlTypeData::dataReceived(const Data &data)
return;
}
QQmlEngine *qmlEngine = typeLoader()->engine();
- m_document.reset(new QmlIR::Document(QV8Engine::getV4(qmlEngine)->debugger != 0));
+ m_document.reset(new QmlIR::Document(QV8Engine::getV4(qmlEngine)->debugger() != 0));
m_document->jsModule.sourceTimeStamp = sourceTimeStamp;
QmlIR::IRBuilder compiler(QV8Engine::get(qmlEngine)->illegalNames());
if (!compiler.generateFromQml(code, finalUrlString(), m_document.data())) {
@@ -2337,7 +2371,7 @@ void QQmlTypeData::dataReceived(const Data &data)
void QQmlTypeData::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit)
{
QQmlEngine *qmlEngine = typeLoader()->engine();
- m_document.reset(new QmlIR::Document(QV8Engine::getV4(qmlEngine)->debugger != 0));
+ m_document.reset(new QmlIR::Document(QV8Engine::getV4(qmlEngine)->debugger() != 0));
unit->loadIR(m_document.data(), unit);
continueLoadFromIR();
}
@@ -2439,7 +2473,7 @@ void QQmlTypeData::compile()
Q_ASSERT(m_compiledData.isNull());
QQmlRefPointer<QQmlTypeNameCache> importCache;
- QV4::CompiledData::CompilationUnit::ResolvedTypeReferenceMap resolvedTypeCache;
+ QV4::CompiledData::ResolvedTypeReferenceMap resolvedTypeCache;
QQmlCompileError error = buildTypeResolutionCaches(&importCache, &resolvedTypeCache);
if (error.isSet()) {
setError(error);
@@ -2455,7 +2489,7 @@ void QQmlTypeData::compile()
if (diskCache() || forceDiskCacheRefresh()) {
QString errorString;
if (!m_compiledData->saveToDisk(&errorString)) {
- qDebug() << "Error saving cached version of" << m_compiledData->url().toString() << "to disk:" << errorString;
+ qCDebug(DBG_DISK_CACHE) << "Error saving cached version of" << m_compiledData->url().toString() << "to disk:" << errorString;
}
}
}
@@ -2579,7 +2613,10 @@ void QQmlTypeData::resolveTypes()
}
}
-QQmlCompileError QQmlTypeData::buildTypeResolutionCaches(QQmlRefPointer<QQmlTypeNameCache> *importCache, QV4::CompiledData::CompilationUnit::ResolvedTypeReferenceMap *resolvedTypeCache) const
+QQmlCompileError QQmlTypeData::buildTypeResolutionCaches(
+ QQmlRefPointer<QQmlTypeNameCache> *importCache,
+ QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache
+ ) const
{
importCache->adopt(new QQmlTypeNameCache);
@@ -2595,7 +2632,7 @@ QQmlCompileError QQmlTypeData::buildTypeResolutionCaches(QQmlRefPointer<QQmlType
QQmlEnginePrivate * const engine = QQmlEnginePrivate::get(typeLoader()->engine());
for (auto resolvedType = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd(); resolvedType != end; ++resolvedType) {
- QScopedPointer<QV4::CompiledData::CompilationUnit::ResolvedTypeReference> ref(new QV4::CompiledData::CompilationUnit::ResolvedTypeReference);
+ QScopedPointer<QV4::CompiledData::ResolvedTypeReference> ref(new QV4::CompiledData::ResolvedTypeReference);
QQmlType *qmlType = resolvedType->type;
if (resolvedType->typeData) {
if (resolvedType->needsCreation && qmlType->isCompositeSingleton()) {
@@ -2840,16 +2877,16 @@ void QQmlScriptBlob::dataReceived(const Data &data)
if (diskCache() && !forceDiskCacheRefresh()) {
QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = v4->iselFactory->createUnitForLoading();
QString error;
- if (unit->loadFromDisk(url(), &error)) {
+ if (unit->loadFromDisk(url(), v4->iselFactory.data(), &error)) {
initializeFromCompilationUnit(unit);
return;
} else {
- qDebug() << "Error loading" << url().toString() << "from disk cache:" << error;
+ qCDebug(DBG_DISK_CACHE()) << "Error loading" << url().toString() << "from disk cache:" << error;
}
}
- QmlIR::Document irUnit(v4->debugger != 0);
+ QmlIR::Document irUnit(v4->debugger() != 0);
QString error;
QString source = QString::fromUtf8(data.readAll(&error, &irUnit.jsModule.sourceTimeStamp));
@@ -2877,7 +2914,8 @@ void QQmlScriptBlob::dataReceived(const Data &data)
irUnit.unitFlags |= QV4::CompiledData::Unit::IsSharedLibrary;
QmlIR::QmlUnitGenerator qmlGenerator;
- QV4::CompiledData::Unit *unitData = qmlGenerator.generate(irUnit);
+ QV4::CompiledData::ResolvedTypeReferenceMap emptyDependencies;
+ QV4::CompiledData::Unit *unitData = qmlGenerator.generate(irUnit, m_typeLoader->engine(), emptyDependencies);
Q_ASSERT(!unit->data);
// The js unit owns the data and will free the qml unit.
unit->data = unitData;
@@ -2885,7 +2923,7 @@ void QQmlScriptBlob::dataReceived(const Data &data)
if (diskCache() || forceDiskCacheRefresh()) {
QString errorString;
if (!unit->saveToDisk(&errorString)) {
- qDebug() << "Error saving cached version of" << unit->url().toString() << "to disk:" << errorString;
+ qCDebug(DBG_DISK_CACHE()) << "Error saving cached version of" << unit->url().toString() << "to disk:" << errorString;
}
}
@@ -2899,8 +2937,11 @@ void QQmlScriptBlob::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *
void QQmlScriptBlob::done()
{
+ if (isError())
+ return;
+
// Check all script dependencies for errors
- for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) {
+ for (int ii = 0; ii < m_scripts.count(); ++ii) {
const ScriptReference &script = m_scripts.at(ii);
Q_ASSERT(script.script->isCompleteOrError());
if (script.script->isError()) {
@@ -2912,17 +2953,15 @@ void QQmlScriptBlob::done()
error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->url().toString()));
errors.prepend(error);
setError(errors);
+ return;
}
}
- if (isError())
- return;
-
m_scriptData->importCache = new QQmlTypeNameCache();
QSet<QString> ns;
- for (int scriptIndex = 0; !isError() && scriptIndex < m_scripts.count(); ++scriptIndex) {
+ for (int scriptIndex = 0; scriptIndex < m_scripts.count(); ++scriptIndex) {
const ScriptReference &script = m_scripts.at(scriptIndex);
m_scriptData->scripts.append(script.script);
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 4c57306ed7..5f754df1fc 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -444,7 +444,10 @@ private:
bool tryLoadFromDiskCache();
void continueLoadFromIR();
void resolveTypes();
- QQmlCompileError buildTypeResolutionCaches(QQmlRefPointer<QQmlTypeNameCache> *importCache, QV4::CompiledData::CompilationUnit::ResolvedTypeReferenceMap *resolvedTypeCache) const;
+ QQmlCompileError buildTypeResolutionCaches(
+ QQmlRefPointer<QQmlTypeNameCache> *importCache,
+ QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache
+ ) const;
void compile();
void rebuildTypeAndPropertyCaches();
bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion, TypeReference &ref);
@@ -460,7 +463,9 @@ private:
QList<TypeReference> m_compositeSingletons;
// map from name index to resolved type
- QHash<int, TypeReference> m_resolvedTypes;
+ // While this could be a hash, a map is chosen here to provide a stable
+ // order, which is used to calculating a check-sum on dependent meta-objects.
+ QMap<int, TypeReference> m_resolvedTypes;
bool m_typesResolved:1;
QQmlRefPointer<QV4::CompiledData::CompilationUnit> m_compiledData;
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 44fd47244d..8e87ec7f63 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -219,7 +219,7 @@ void QQmlValueType::read(QObject *obj, int idx)
QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
}
-void QQmlValueType::write(QObject *obj, int idx, QQmlPropertyPrivate::WriteFlags flags)
+void QQmlValueType::write(QObject *obj, int idx, QQmlPropertyData::WriteFlags flags)
{
Q_ASSERT(gadgetPtr);
int status = -1;
diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h
index 910d39cf0a..11e1dfdb00 100644
--- a/src/qml/qml/qqmlvaluetype_p.h
+++ b/src/qml/qml/qqmlvaluetype_p.h
@@ -69,7 +69,7 @@ public:
QQmlValueType(int userType, const QMetaObject *metaObject);
~QQmlValueType();
void read(QObject *, int);
- void write(QObject *, int, QQmlPropertyPrivate::WriteFlags flags);
+ void write(QObject *, int, QQmlPropertyData::WriteFlags flags);
QVariant value();
void setValue(const QVariant &);
diff --git a/src/qml/qml/qqmlvaluetypeproxybinding.cpp b/src/qml/qml/qqmlvaluetypeproxybinding.cpp
index 6858215a79..595cd01d05 100644
--- a/src/qml/qml/qqmlvaluetypeproxybinding.cpp
+++ b/src/qml/qml/qqmlvaluetypeproxybinding.cpp
@@ -58,7 +58,7 @@ QQmlValueTypeProxyBinding::~QQmlValueTypeProxyBinding()
}
}
-void QQmlValueTypeProxyBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags)
+void QQmlValueTypeProxyBinding::setEnabled(bool e, QQmlPropertyData::WriteFlags flags)
{
QQmlAbstractBinding *b = m_bindings.data();
while (b) {
diff --git a/src/qml/qml/qqmlvaluetypeproxybinding_p.h b/src/qml/qml/qqmlvaluetypeproxybinding_p.h
index de5acc2984..6e297bb3ea 100644
--- a/src/qml/qml/qqmlvaluetypeproxybinding_p.h
+++ b/src/qml/qml/qqmlvaluetypeproxybinding_p.h
@@ -63,7 +63,7 @@ public:
QQmlAbstractBinding *binding(int targetPropertyIndex);
void removeBindings(quint32 mask);
- virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags);
+ virtual void setEnabled(bool, QQmlPropertyData::WriteFlags);
virtual bool isValueTypeProxy() const;
protected:
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index d7f6c5b3af..d5001674ad 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -220,7 +220,7 @@ int QQmlInterceptorMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id,
bool QQmlInterceptorMetaObject::intercept(QMetaObject::Call c, int id, void **a)
{
if (c == QMetaObject::WriteProperty && interceptors &&
- !(*reinterpret_cast<int*>(a[3]) & QQmlPropertyPrivate::BypassInterceptor)) {
+ !(*reinterpret_cast<int*>(a[3]) & QQmlPropertyData::BypassInterceptor)) {
for (QQmlPropertyValueInterceptor *vi = interceptors; vi; vi = vi->m_next) {
if (vi->m_coreIndex != id)
@@ -278,7 +278,7 @@ bool QQmlInterceptorMetaObject::intercept(QMetaObject::Call c, int id, void **a)
bool updated = false;
if (newComponentValue != prevComponentValue) {
valueProp.write(valueType, prevComponentValue);
- valueType->write(object, id, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
+ valueType->write(object, id, QQmlPropertyData::DontRemoveBinding | QQmlPropertyData::BypassInterceptor);
vi->write(newComponentValue);
updated = true;
@@ -872,7 +872,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
// Remove binding (if any) on write
if(c == QMetaObject::WriteProperty) {
int flags = *reinterpret_cast<int*>(a[3]);
- if (flags & QQmlPropertyPrivate::RemoveBindingOnAliasWrite) {
+ if (flags & QQmlPropertyData::RemoveBindingOnAliasWrite) {
QQmlData *targetData = QQmlData::get(target);
if (targetData && targetData->hasBindingBit(coreIndex))
QQmlPropertyPrivate::removeBinding(target, aliasData->encodedMetaPropertyIndex);
diff --git a/src/qmldebug/qqmldebugconnection.cpp b/src/qmldebug/qqmldebugconnection.cpp
index 35a540bff8..b5db71557f 100644
--- a/src/qmldebug/qqmldebugconnection.cpp
+++ b/src/qmldebug/qqmldebugconnection.cpp
@@ -77,7 +77,7 @@ public:
QStringList removedPlugins;
void advertisePlugins();
- void connectDeviceSignals();
+ void createProtocol();
void flush();
};
@@ -159,7 +159,7 @@ void QQmlDebugConnection::protocolReadyRead()
if (!validHello) {
qWarning("QQmlDebugConnection: Invalid hello message");
- QObject::disconnect(d->protocol, SIGNAL(protocolReadyRead()), this, SLOT(protocolReadyRead()));
+ close();
return;
}
d->gotHello = true;
@@ -254,7 +254,7 @@ QQmlDebugConnection::QQmlDebugConnection(QObject *parent) :
QObject(*(new QQmlDebugConnectionPrivate), parent)
{
Q_D(QQmlDebugConnection);
- connect(&d->handshakeTimer, SIGNAL(timeout()), this, SLOT(handshakeTimeout()));
+ connect(&d->handshakeTimer, &QTimer::timeout, this, &QQmlDebugConnection::handshakeTimeout);
}
QQmlDebugConnection::~QQmlDebugConnection()
@@ -374,8 +374,9 @@ bool QQmlDebugConnection::sendMessage(const QString &name, const QByteArray &mes
void QQmlDebugConnectionPrivate::flush()
{
- QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(device);
- if (socket)
+ if (QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(device))
+ socket->flush();
+ else if (QLocalSocket *socket = qobject_cast<QLocalSocket *>(device))
socket->flush();
}
@@ -386,12 +387,12 @@ void QQmlDebugConnection::connectToHost(const QString &hostName, quint16 port)
close();
QTcpSocket *socket = new QTcpSocket(this);
d->device = socket;
- d->connectDeviceSignals();
- connect(socket, SIGNAL(connected()), this, SLOT(socketConnected()));
- connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
- this, SIGNAL(socketError(QAbstractSocket::SocketError)));
- connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
- this, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)));
+ d->createProtocol();
+ connect(socket, &QAbstractSocket::disconnected, this, &QQmlDebugConnection::socketDisconnected);
+ connect(socket, &QAbstractSocket::connected, this, &QQmlDebugConnection::socketConnected);
+ connect(socket, static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(
+ &QAbstractSocket::error), this, &QQmlDebugConnection::socketError);
+ connect(socket, &QAbstractSocket::stateChanged, this, &QQmlDebugConnection::socketStateChanged);
socket->connectToHost(hostName, port);
}
@@ -404,7 +405,8 @@ void QQmlDebugConnection::startLocalServer(const QString &fileName)
d->server->deleteLater();
d->server = new QLocalServer(this);
// QueuedConnection so that waitForNewConnection() returns true.
- connect(d->server, SIGNAL(newConnection()), this, SLOT(newConnection()), Qt::QueuedConnection);
+ connect(d->server, &QLocalServer::newConnection,
+ this, &QQmlDebugConnection::newConnection, Qt::QueuedConnection);
d->server->listen(fileName);
}
@@ -414,17 +416,12 @@ class LocalSocketSignalTranslator : public QObject
public:
LocalSocketSignalTranslator(QLocalSocket *parent) : QObject(parent)
{
- connect(parent, SIGNAL(stateChanged(QLocalSocket::LocalSocketState)),
- this, SLOT(onStateChanged(QLocalSocket::LocalSocketState)));
- connect(parent, SIGNAL(error(QLocalSocket::LocalSocketError)),
- this, SLOT(onError(QLocalSocket::LocalSocketError)));
+ connect(parent, &QLocalSocket::stateChanged,
+ this, &LocalSocketSignalTranslator::onStateChanged);
+ connect(parent, static_cast<void(QLocalSocket::*)(QLocalSocket::LocalSocketError)>(
+ &QLocalSocket::error), this, &LocalSocketSignalTranslator::onError);
}
-signals:
- void socketError(QAbstractSocket::SocketError error);
- void socketStateChanged(QAbstractSocket::SocketState state);
-
-public slots:
void onError(QLocalSocket::LocalSocketError error)
{
emit socketError(static_cast<QAbstractSocket::SocketError>(error));
@@ -434,6 +431,10 @@ public slots:
{
emit socketStateChanged(static_cast<QAbstractSocket::SocketState>(state));
}
+
+signals:
+ void socketError(QAbstractSocket::SocketError error);
+ void socketStateChanged(QAbstractSocket::SocketState state);
};
void QQmlDebugConnection::newConnection()
@@ -443,23 +444,24 @@ void QQmlDebugConnection::newConnection()
QLocalSocket *socket = d->server->nextPendingConnection();
d->server->close();
d->device = socket;
- d->connectDeviceSignals();
+ d->createProtocol();
+ connect(socket, &QLocalSocket::disconnected, this, &QQmlDebugConnection::socketDisconnected);
LocalSocketSignalTranslator *translator = new LocalSocketSignalTranslator(socket);
- QObject::connect(translator, SIGNAL(socketError(QAbstractSocket::SocketError)),
- this, SIGNAL(socketError(QAbstractSocket::SocketError)));
- QObject::connect(translator, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)),
- this, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)));
+ connect(translator, &LocalSocketSignalTranslator::socketError,
+ this, &QQmlDebugConnection::socketError);
+ connect(translator, &LocalSocketSignalTranslator::socketStateChanged,
+ this, &QQmlDebugConnection::socketStateChanged);
socketConnected();
}
-void QQmlDebugConnectionPrivate::connectDeviceSignals()
+void QQmlDebugConnectionPrivate::createProtocol()
{
Q_Q(QQmlDebugConnection);
delete protocol;
protocol = new QPacketProtocol(device, q);
- QObject::connect(protocol, SIGNAL(readyRead()), q, SLOT(protocolReadyRead()));
- QObject::connect(device, SIGNAL(disconnected()), q, SLOT(socketDisconnected()));
+ QObject::connect(protocol, &QPacketProtocol::readyRead,
+ q, &QQmlDebugConnection::protocolReadyRead);
}
QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmldebugconnection_p.h b/src/qmldebug/qqmldebugconnection_p.h
index 40753fc998..be425b6cbf 100644
--- a/src/qmldebug/qqmldebugconnection_p.h
+++ b/src/qmldebug/qqmldebugconnection_p.h
@@ -92,7 +92,7 @@ signals:
void socketError(QAbstractSocket::SocketError socketError);
void socketStateChanged(QAbstractSocket::SocketState socketState);
-private Q_SLOTS:
+private:
void newConnection();
void socketConnected();
void socketDisconnected();
diff --git a/src/qmldebug/qqmlprofilerclient_p.h b/src/qmldebug/qqmlprofilerclient_p.h
index 832c05fef7..b4054ed0d9 100644
--- a/src/qmldebug/qqmlprofilerclient_p.h
+++ b/src/qmldebug/qqmlprofilerclient_p.h
@@ -67,8 +67,6 @@ class QQmlProfilerClient : public QQmlDebugClient
public:
QQmlProfilerClient(QQmlDebugConnection *connection);
void setFeatures(quint64 features);
-
-public slots:
void sendRecordingStatus(bool record, int engineId = -1, quint32 flushInterval = 0);
protected:
diff --git a/src/qmltest/qmltest.pro b/src/qmltest/qmltest.pro
index 42224e9751..ebbcbcd1eb 100644
--- a/src/qmltest/qmltest.pro
+++ b/src/qmltest/qmltest.pro
@@ -30,6 +30,6 @@ HEADERS += \
$$PWD/quicktestresult_p.h \
$$PWD/qtestoptions_p.h
-DEFINES += QT_QML_DEBUG_NO_WARNING
+!contains(QT_CONFIG, no-qml-debug): DEFINES += QT_QML_DEBUG_NO_WARNING
load(qt_module)
diff --git a/src/quick/designer/qquickdesignercustomobjectdata.cpp b/src/quick/designer/qquickdesignercustomobjectdata.cpp
index 42dcb08d45..3c8f4b281c 100644
--- a/src/quick/designer/qquickdesignercustomobjectdata.cpp
+++ b/src/quick/designer/qquickdesignercustomobjectdata.cpp
@@ -194,7 +194,7 @@ void QQuickDesignerCustomObjectData::doResetProperty(QQmlContext *context, const
#endif
if (qmlBinding)
qmlBinding->setTarget(property);
- QQmlPropertyPrivate::setBinding(binding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding);
+ QQmlPropertyPrivate::setBinding(binding, QQmlPropertyPrivate::None, QQmlPropertyData::DontRemoveBinding);
if (qmlBinding)
qmlBinding->update();
@@ -262,7 +262,7 @@ void QQuickDesignerCustomObjectData::setPropertyBinding(QQmlContext *context,
binding->setTarget(property);
binding->setNotifyOnValueChanged(true);
- QQmlPropertyPrivate::setBinding(binding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding);
+ QQmlPropertyPrivate::setBinding(binding, QQmlPropertyPrivate::None, QQmlPropertyData::DontRemoveBinding);
//Refcounting is taking take care of deletion
binding->update();
if (binding->hasError()) {
diff --git a/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc b/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
index cb281a2d4a..a764402c2f 100644
--- a/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
+++ b/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
@@ -156,6 +156,111 @@ with list models of QAbstractItemModel type:
\li \l DelegateModel::parentModelIndex() returns a QModelIndex which can be assigned to DelegateModel::rootIndex
\endlist
+\section2 SQL Models
+
+Qt provides C++ classes that support SQL data models. These classes work
+transparently on the underlying SQL data, reducing the need to run SQL
+queries for basic SQL operations such as create, insert, or update.
+For more details about these classes, see \l{Using the SQL Model Classes}.
+
+Although the C++ classes provide complete feature sets to operate on SQL
+data, they do not provide data access to QML. So you must implement a
+C++ custom data model as a subclass of one of these classes, and expose it
+to QML either as a type or context property.
+
+\section3 Read-only Data Model
+
+The custom model must reimplement the following methods to enable read-only
+access to the data from QML:
+
+\list
+\li \l{QAbstractItemModel::}{roleNames}() to expose the role names to the
+ QML frontend. For example, the following version returns the selected
+ table's field names as role names:
+ \code
+ QHash<int, QByteArray> SqlQueryModel::roleNames() const
+ {
+ QHash<int, QByteArray> roles;
+ // record() returns an empty QSqlRecord
+ for (int i = 0; i < this->record().count(); i ++) {
+ roles.insert(Qt::UserRole + i + 1, record().fieldName(i).toUtf8());
+ }
+ return roles;
+ }
+ \endcode
+\li \l{QSqlQueryModel::}{data}() to expose SQL data to the QML frontend.
+ For example, the following implementation returns data for the given
+ model index:
+ \code
+ QVariant SqlQueryModel::data(const QModelIndex &index, int role) const
+ {
+ QVariant value;
+
+ if (index.isValid()) {
+ if (role < Qt::UserRole) {
+ value = QSqlQueryModel::data(index, role);
+ } else {
+ int columnIdx = role - Qt::UserRole - 1;
+ QModelIndex modelIndex = this->index(index.row(), columnIdx);
+ value = QSqlQueryModel::data(modelIndex, Qt::DisplayRole);
+ }
+ }
+ return value;
+ }
+ \endcode
+\endlist
+
+The QSqlQueryModel class is good enough to implement a custom read-only
+model that represents data in an SQL database. The
+\l{Qt Quick Controls 2 - Chat Tutorial}{chat tutorial} example
+demonstrates this very well by implementing a custom model to fetch the
+contact details from an SQLite database.
+
+\section3 Editable Data Model
+
+Besides the \c roleNames() and \c data(), the editable models must reimplement
+the \l{QSqlTableModel::}{setData} method to save changes to existing SQL data.
+The following version of the method checks if the given model index is valid
+and the \c role is equal to \l Qt::EditRole, before calling the parent class
+version:
+
+\code
+bool SqlEditableModel::setData(const QModelIndex &item, const QVariant &value, int role)
+{
+ if (item.isValid() && role == Qt::EditRole) {
+ QSqlTableModel::setData(item, value,role);
+ emit dataChanged(item, item);
+ return true;
+ }
+ return false;
+
+}
+\endcode
+
+\note It is important to emit the \l{QAbstractItemModel::}{dataChanged}()
+signal after saving the changes.
+
+Unlike the C++ item views such as QListView or QTableView, the \c setData()
+method must be explicitly invoked from QML whenever appropriate. For example,
+on the \l[QML]{TextField::}{editingFinished}() or \l[QML]{TextField::}{accepted}()
+signal of \l[QtQuickControls]{TextField}. Depending on the
+\l{QSqlTableModel::}{EditStrategy} used by the model, the changes are either
+queued for submission later or submitted immediately.
+
+You can also insert new data into the model by calling
+\l {QSqlTableModel::insertRecord}(). In the following example snippet,
+a QSqlRecord is populated with book details and appended to the
+model:
+
+\code
+ ...
+ QSqlRecord newRecord = record();
+ newRecord.setValue("author", "John Grisham");
+ newRecord.setValue("booktitle", "The Litigators");
+ insertRecord(rowCount(), newRecord);
+ ...
+\endcode
+
\section2 Exposing C++ Data Models to QML
The above examples use QQmlContext::setContextProperty() to set
diff --git a/src/quick/doc/src/qmltypereference.qdoc b/src/quick/doc/src/qmltypereference.qdoc
index 6e6e66e026..2406722dbc 100644
--- a/src/quick/doc/src/qmltypereference.qdoc
+++ b/src/quick/doc/src/qmltypereference.qdoc
@@ -100,9 +100,9 @@ available when you import \c QtQuick.
\li By a hexadecimal triplet or quad in the form \c "#RRGGBB" and \c "#AARRGGBB"
respectively. For example, the color red corresponds to a triplet of \c "#FF0000"
and a slightly transparent blue to a quad of \c "#800000FF".
- \li Using the \l{QtQml::Qt::rgba()}{Qt.rgba()}, \l{QtQml::Qt::hsla()}{Qt.hsla()},
- \l{QtQml::Qt::darker()}{Qt.darker()}, \l{QtQml::Qt::lighter()}{Qt.lighter()} or
- \l{QtQml::Qt::tint()}{Qt.tint()} functions.
+ \li Using the \l{QtQml::Qt::rgba()}{Qt.rgba()}, \l{QtQml::Qt::hsva()}{Qt.hsva()},
+ \l{QtQml::Qt::hsla()}{Qt.hsla()}, \l{QtQml::Qt::darker()}{Qt.darker()},
+ \l{QtQml::Qt::lighter()}{Qt.lighter()} or \l{QtQml::Qt::tint()}{Qt.tint()} functions.
\endlist
Example:
@@ -112,8 +112,11 @@ available when you import \c QtQuick.
\enddiv
\snippet qml/colors.qml colors
- Additionally, a color type has \c r, \c g, \c b and \c a properties that refer to the
- red, green, blue and alpha values of the color, respectively:
+ A color type has \c r, \c g, \c b and \c a properties that refer to the red,
+ green, blue and alpha values of the color, respectively. Additionally it has
+ \c hsvHue, \c hsvSaturation, \c hsvValue and \c hslHue, \c hslSaturation,
+ \c hslLightness properties, which allow access to color values in HSV and HSL
+ color models accordingly:
\qml
Text {
diff --git a/src/quick/items/qquickclipnode.cpp b/src/quick/items/qquickclipnode.cpp
index 1114686a9a..7c7fee4a42 100644
--- a/src/quick/items/qquickclipnode.cpp
+++ b/src/quick/items/qquickclipnode.cpp
@@ -113,7 +113,7 @@ void QQuickDefaultClipNode::updateGeometry()
}
}
- markDirty(DirtyGeometry);
setClipRect(m_rect);
+ markDirty(DirtyGeometry);
}
diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h
index 47fda2fe01..f3e6fdddff 100644
--- a/src/quick/items/qquickevents_p_p.h
+++ b/src/quick/items/qquickevents_p_p.h
@@ -284,6 +284,8 @@ private:
bool m_valid : 1;
bool m_accept : 1;
int m_reserved : 30;
+
+ Q_DISABLE_COPY(QQuickEventPoint)
};
class Q_QUICK_PRIVATE_EXPORT QQuickEventTouchPoint : public QQuickEventPoint
@@ -306,6 +308,8 @@ private:
qreal m_rotation;
qreal m_pressure;
QPointerUniqueId m_uniqueId;
+
+ Q_DISABLE_COPY(QQuickEventTouchPoint)
};
class Q_QUICK_PRIVATE_EXPORT QQuickPointerEvent : public QObject
@@ -390,6 +394,8 @@ public:
private:
QQuickEventPoint *m_mousePoint;
+
+ Q_DISABLE_COPY(QQuickPointerMouseEvent)
};
class Q_QUICK_PRIVATE_EXPORT QQuickPointerTouchEvent : public QQuickPointerEvent
@@ -418,6 +424,8 @@ public:
private:
int m_pointCount;
QVector<QQuickEventTouchPoint *> m_touchPoints;
+
+ Q_DISABLE_COPY(QQuickPointerTouchEvent)
};
// ### Qt 6: move this to qtbase, replace QTouchDevice and the enums in QTabletEvent
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index a09088dfed..dcba5c2d71 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -1590,13 +1590,13 @@ qreal QQuickFlickable::minXExtent() const
qreal QQuickFlickable::maxXExtent() const
{
Q_D(const QQuickFlickable);
- return qMin<qreal>(0, width() - vWidth() - d->hData.endMargin);
+ return qMin<qreal>(minXExtent(), width() - vWidth() - d->hData.endMargin);
}
/* returns -ve */
qreal QQuickFlickable::maxYExtent() const
{
Q_D(const QQuickFlickable);
- return qMin<qreal>(0, height() - vHeight() - d->vData.endMargin);
+ return qMin<qreal>(minYExtent(), height() - vHeight() - d->vData.endMargin);
}
void QQuickFlickable::componentComplete()
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 695454af38..84f9b0f169 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -2090,6 +2090,9 @@ void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus)
\value ItemDevicePixelRatioHasChanged The device pixel ratio of the screen
the item is on has changed. ItemChangedData::realValue contains the new
device pixel ratio.
+
+ \value ItemAntialiasingHasChanged The antialiasing has changed. The current
+ (boolean) value can be found in QQuickItem::antialiasing.
*/
/*!
diff --git a/src/quick/items/qquickitemanimation.cpp b/src/quick/items/qquickitemanimation.cpp
index 962f410095..027c07ec07 100644
--- a/src/quick/items/qquickitemanimation.cpp
+++ b/src/quick/items/qquickitemanimation.cpp
@@ -200,6 +200,27 @@ QPointF QQuickParentAnimationPrivate::computeTransformOrigin(QQuickItem::Transfo
}
}
+struct QQuickParentAnimationData : public QAbstractAnimationAction
+{
+ QQuickParentAnimationData() : reverse(false) {}
+ ~QQuickParentAnimationData() { qDeleteAll(pc); }
+
+ QQuickStateActions actions;
+ //### reverse should probably apply on a per-action basis
+ bool reverse;
+ QList<QQuickParentChange *> pc;
+ void doAction() Q_DECL_OVERRIDE
+ {
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ const QQuickStateAction &action = actions.at(ii);
+ if (reverse)
+ action.event->reverse();
+ else
+ action.event->execute();
+ }
+ }
+};
+
QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &actions,
QQmlProperties &modified,
TransitionDirection direction,
@@ -207,27 +228,6 @@ QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &act
{
Q_D(QQuickParentAnimation);
- struct QQuickParentAnimationData : public QAbstractAnimationAction
- {
- QQuickParentAnimationData() : reverse(false) {}
- ~QQuickParentAnimationData() { qDeleteAll(pc); }
-
- QQuickStateActions actions;
- //### reverse should probably apply on a per-action basis
- bool reverse;
- QList<QQuickParentChange *> pc;
- void doAction() Q_DECL_OVERRIDE
- {
- for (int ii = 0; ii < actions.count(); ++ii) {
- const QQuickStateAction &action = actions.at(ii);
- if (reverse)
- action.event->reverse();
- else
- action.event->execute();
- }
- }
- };
-
QQuickParentAnimationData *data = new QQuickParentAnimationData;
QQuickParentAnimationData *viaData = new QQuickParentAnimationData;
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index eb568c48d4..d6d9d53a3b 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -1489,8 +1489,8 @@ void QQuickTextEdit::setSelectByKeyboard(bool on)
If true, the user can use the mouse to select text in some
platform-specific way. Note that for some platforms this may
- not be an appropriate interaction (eg. may conflict with how
- the text needs to behave inside a Flickable.
+ not be an appropriate interaction; it may conflict with how
+ the text needs to behave inside a Flickable, for example.
*/
bool QQuickTextEdit::selectByMouse() const
{
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp
index 1d89c8bfc2..8b74d26576 100644
--- a/src/quick/items/qquickview.cpp
+++ b/src/quick/items/qquickview.cpp
@@ -44,9 +44,6 @@
#include "qquickitem_p.h"
#include "qquickitemchangelistener_p.h"
-#include <private/qqmldebugconnector_p.h>
-#include <private/qquickprofiler_p.h>
-#include <private/qqmldebugserviceinterfaces_p.h>
#include <private/qqmlmemoryprofiler_p.h>
#include <QtQml/qqmlengine.h>
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 024f326c3e..ae3b272e72 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -697,10 +697,10 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QTouchEvent *eve
lastMousePosition = me->windowPos();
bool accepted = me->isAccepted();
- bool delivered = deliverHoverEvent(contentItem, me->windowPos(), last, me->modifiers(), accepted);
+ bool delivered = deliverHoverEvent(contentItem, me->windowPos(), last, me->modifiers(), me->timestamp(), accepted);
if (!delivered) {
//take care of any exits
- accepted = clearHover();
+ accepted = clearHover(me->timestamp());
}
me->setAccepted(accepted);
break;
@@ -1471,7 +1471,7 @@ QQuickItem *QQuickWindow::mouseGrabberItem() const
}
-bool QQuickWindowPrivate::clearHover()
+bool QQuickWindowPrivate::clearHover(ulong timestamp)
{
Q_Q(QQuickWindow);
if (hoverItems.isEmpty())
@@ -1481,7 +1481,7 @@ bool QQuickWindowPrivate::clearHover()
bool accepted = false;
foreach (QQuickItem* item, hoverItems)
- accepted = sendHoverEvent(QEvent::HoverLeave, item, pos, pos, QGuiApplication::keyboardModifiers(), true) || accepted;
+ accepted = sendHoverEvent(QEvent::HoverLeave, item, pos, pos, QGuiApplication::keyboardModifiers(), timestamp, true) || accepted;
hoverItems.clear();
return accepted;
}
@@ -1612,6 +1612,15 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven
lastMousePosition = point->scenePos();
QQuickItem *grabber = point->grabber();
if (grabber) {
+ // if the update consists of changing button state, then don't accept it
+ // unless the button is one in which the item is interested
+ if (pointerEvent->button() != Qt::NoButton
+ && grabber->acceptedMouseButtons()
+ && !(grabber->acceptedMouseButtons() & pointerEvent->button())) {
+ pointerEvent->setAccepted(false);
+ return;
+ }
+
// send update
QPointF localPos = grabber->mapFromScene(lastMousePosition);
auto me = pointerEvent->asMouseEvent(localPos);
@@ -1638,12 +1647,14 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven
bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item,
const QPointF &scenePos, const QPointF &lastScenePos,
- Qt::KeyboardModifiers modifiers, bool accepted)
+ Qt::KeyboardModifiers modifiers, ulong timestamp,
+ bool accepted)
{
const QTransform transform = QQuickItemPrivate::get(item)->windowToItemTransform();
//create copy of event
QHoverEvent hoverEvent(type, transform.map(scenePos), transform.map(lastScenePos), modifiers);
+ hoverEvent.setTimestamp(timestamp);
hoverEvent.setAccepted(accepted);
QSet<QQuickItem *> hasFiltered;
@@ -1657,7 +1668,7 @@ bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item,
}
bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &scenePos, const QPointF &lastScenePos,
- Qt::KeyboardModifiers modifiers, bool &accepted)
+ Qt::KeyboardModifiers modifiers, ulong timestamp, bool &accepted)
{
Q_Q(QQuickWindow);
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
@@ -1675,7 +1686,7 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce
QQuickItem *child = children.at(ii);
if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled)
continue;
- if (deliverHoverEvent(child, scenePos, lastScenePos, modifiers, accepted))
+ if (deliverHoverEvent(child, scenePos, lastScenePos, modifiers, timestamp, accepted))
return true;
}
}
@@ -1685,7 +1696,7 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce
if (item->contains(p)) {
if (!hoverItems.isEmpty() && hoverItems[0] == item) {
//move
- accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted);
+ accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, timestamp, accepted);
} else {
QList<QQuickItem *> itemsToHover;
QQuickItem* parent = item;
@@ -1696,12 +1707,12 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce
// Leaving from previous hovered items until we reach the item or one of its ancestors.
while (!hoverItems.isEmpty() && !itemsToHover.contains(hoverItems[0])) {
QQuickItem *hoverLeaveItem = hoverItems.takeFirst();
- sendHoverEvent(QEvent::HoverLeave, hoverLeaveItem, scenePos, lastScenePos, modifiers, accepted);
+ sendHoverEvent(QEvent::HoverLeave, hoverLeaveItem, scenePos, lastScenePos, modifiers, timestamp, accepted);
}
if (!hoverItems.isEmpty() && hoverItems[0] == item){//Not entering a new Item
// ### Shouldn't we send moves for the parent items as well?
- accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted);
+ accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, timestamp, accepted);
} else {
// Enter items that are not entered yet.
int startIdx = -1;
@@ -1720,7 +1731,7 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce
// itemToHoverPrivate->window here prevents that case.
if (itemToHoverPrivate->window == q && itemToHoverPrivate->hoverEnabled) {
hoverItems.prepend(itemToHover);
- sendHoverEvent(QEvent::HoverEnter, itemToHover, scenePos, lastScenePos, modifiers, accepted);
+ sendHoverEvent(QEvent::HoverEnter, itemToHover, scenePos, lastScenePos, modifiers, timestamp, accepted);
}
}
}
@@ -2009,10 +2020,10 @@ void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event)
lastMousePosition = event->windowPos();
bool accepted = event->isAccepted();
- bool delivered = deliverHoverEvent(contentItem, event->windowPos(), last, event->modifiers(), accepted);
+ bool delivered = deliverHoverEvent(contentItem, event->windowPos(), last, event->modifiers(), event->timestamp(), accepted);
if (!delivered) {
//take care of any exits
- accepted = clearHover();
+ accepted = clearHover(event->timestamp());
}
event->setAccepted(accepted);
return;
@@ -2045,7 +2056,7 @@ void QQuickWindowPrivate::flushFrameSynchronousEvents()
// whether it has moved into a position where it is now under the cursor.
if (!q->mouseGrabberItem() && !lastMousePosition.isNull()) {
bool accepted = false;
- bool delivered = deliverHoverEvent(contentItem, lastMousePosition, lastMousePosition, QGuiApplication::keyboardModifiers(), accepted);
+ bool delivered = deliverHoverEvent(contentItem, lastMousePosition, lastMousePosition, QGuiApplication::keyboardModifiers(), 0, accepted);
if (!delivered)
clearHover(); // take care of any exits
}
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index fca0f78de5..90e75fb751 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -174,10 +174,10 @@ public:
QVector<QQuickItem *> mergePointerTargets(const QVector<QQuickItem *> &list1, const QVector<QQuickItem *> &list2) const;
// hover delivery
- bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, bool &accepted);
+ bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, ulong timestamp, bool &accepted);
bool sendHoverEvent(QEvent::Type, QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos,
- Qt::KeyboardModifiers modifiers, bool accepted);
- bool clearHover();
+ Qt::KeyboardModifiers modifiers, ulong timestamp, bool accepted);
+ bool clearHover(ulong timestamp = 0);
#ifndef QT_NO_DRAGANDDROP
void deliverDragEvent(QQuickDragGrabber *, QEvent *);
diff --git a/src/quick/qtquick2.cpp b/src/quick/qtquick2.cpp
index bf5b0083e9..c36adf56ec 100644
--- a/src/quick/qtquick2.cpp
+++ b/src/quick/qtquick2.cpp
@@ -49,7 +49,6 @@
#include <private/qqmldebugstatesdelegate_p.h>
#include <private/qqmlbinding_p.h>
#include <private/qqmlcontext_p.h>
-#include <private/qquickprofiler_p.h>
#include <private/qquickapplication_p.h>
#include <QtQuick/private/qquickpropertychanges_p.h>
#include <QtQuick/private/qquickstate_p.h>
@@ -63,6 +62,12 @@ static void initResources()
QT_BEGIN_NAMESPACE
+#ifdef QT_NO_QML_DEBUGGER
+
+class QQmlQtQuick2DebugStatesDelegate : public QQmlDebugStatesDelegate {};
+
+#else
+
class QQmlQtQuick2DebugStatesDelegate : public QQmlDebugStatesDelegate
{
public:
@@ -175,6 +180,7 @@ void QQmlQtQuick2DebugStatesDelegate::resetBindingForInvalidProperty(QObject *ob
}
}
+#endif // QT_NO_QML_DEBUGGER
void QQmlQtQuick2Module::defineModule()
{
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareadaptation.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwareadaptation.cpp
index 0e2f4f5382..144e75d3e6 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwareadaptation.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareadaptation.cpp
@@ -40,6 +40,7 @@
#include "qsgsoftwareadaptation_p.h"
#include "qsgsoftwarecontext_p.h"
#include "qsgsoftwarerenderloop_p.h"
+#include "qsgsoftwarethreadedrenderloop_p.h"
#include <private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
@@ -73,6 +74,16 @@ QSGContextFactoryInterface::Flags QSGSoftwareAdaptation::flags(const QString &)
QSGRenderLoop *QSGSoftwareAdaptation::createWindowManager()
{
+ static bool threaded = false;
+ static bool envChecked = false;
+ if (!envChecked) {
+ envChecked = true;
+ threaded = qgetenv("QSG_RENDER_LOOP") == QByteArrayLiteral("threaded");
+ }
+
+ if (threaded)
+ return new QSGSoftwareThreadedRenderLoop;
+
return new QSGSoftwareRenderLoop();
}
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp
index 032a06f946..d900688173 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp
@@ -187,6 +187,12 @@ void QSGSoftwareRenderableNode::update()
boundingRect = m_handle.spriteNode->rect().toRect();
break;
case QSGSoftwareRenderableNode::RenderNode:
+ if (m_handle.renderNode->flags().testFlag(QSGRenderNode::OpaqueRendering) && !m_transform.isRotating())
+ m_isOpaque = true;
+ else
+ m_isOpaque = false;
+
+ boundingRect = m_handle.renderNode->rect().toRect();
break;
default:
break;
@@ -244,14 +250,20 @@ QRegion QSGSoftwareRenderableNode::renderNode(QPainter *painter, bool forceOpaqu
rd->m_opacity = m_opacity;
RenderNodeState rs;
rs.cr = m_clipRegion;
+
+ const QRect br = m_handle.renderNode->flags().testFlag(QSGRenderNode::BoundedRectRendering)
+ ? m_boundingRect :
+ QRect(0, 0, painter->device()->width(), painter->device()->height());
+
painter->save();
+ painter->setClipRegion(br, Qt::ReplaceClip);
m_handle.renderNode->render(&rs);
painter->restore();
- const QRect fullRect = QRect(0, 0, painter->device()->width(), painter->device()->height());
- m_previousDirtyRegion = fullRect;
+
+ m_previousDirtyRegion = QRegion(br);
m_isDirty = false;
m_dirtyRegion = QRegion();
- return fullRect;
+ return br;
}
}
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp
index 82f8623b74..12dbf63353 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp
@@ -218,12 +218,13 @@ void QSGSoftwareRenderableNodeUpdater::updateNodes(QSGNode *node, bool isNodeRem
m_opacityState.push(state.opacity);
m_transformState.push(state.transform);
m_clipState.push(state.clip);
-
+ m_hasClip = state.hasClip;
} else {
// There is no parent, and no previous parent, so likely a root node
m_opacityState.push(1.0f);
m_transformState.push(QTransform());
m_clipState.push(QRegion());
+ m_hasClip = false;
}
// If the node is being removed, then cleanup the state data
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp
new file mode 100644
index 0000000000..5d5485ed8f
--- /dev/null
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp
@@ -0,0 +1,991 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgsoftwarethreadedrenderloop_p.h"
+#include "qsgsoftwarecontext_p.h"
+#include "qsgsoftwarerenderer_p.h"
+
+#include <private/qsgrenderer_p.h>
+#include <private/qquickwindow_p.h>
+#include <private/qquickprofiler_p.h>
+#include <private/qquickanimatorcontroller_p.h>
+#include <private/qquickprofiler_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qqmldebugconnector_p.h>
+
+#include <qpa/qplatformbackingstore.h>
+
+#include <QtCore/QQueue>
+#include <QtCore/QElapsedTimer>
+#include <QtCore/QThread>
+#include <QtCore/QMutex>
+#include <QtCore/QWaitCondition>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QBackingStore>
+#include <QtQuick/QQuickWindow>
+
+QT_BEGIN_NAMESPACE
+
+// Passed from the RL to the RT when a window is removed obscured and should be
+// removed from the render loop.
+const QEvent::Type WM_Obscure = QEvent::Type(QEvent::User + 1);
+
+// Passed from the RL to RT when GUI has been locked, waiting for sync.
+const QEvent::Type WM_RequestSync = QEvent::Type(QEvent::User + 2);
+
+// Passed by the RT to itself to trigger another render pass. This is typically
+// a result of QQuickWindow::update().
+const QEvent::Type WM_RequestRepaint = QEvent::Type(QEvent::User + 3);
+
+// Passed by the RL to the RT to maybe release resource if no windows are
+// rendering.
+const QEvent::Type WM_TryRelease = QEvent::Type(QEvent::User + 4);
+
+// Passed by the RL to the RT when a QQuickWindow::grabWindow() is 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);
+
+class QSGSoftwareWindowEvent : public QEvent
+{
+public:
+ QSGSoftwareWindowEvent(QQuickWindow *c, QEvent::Type type) : QEvent(type), window(c) { }
+ QQuickWindow *window;
+};
+
+class QSGSoftwareTryReleaseEvent : public QSGSoftwareWindowEvent
+{
+public:
+ QSGSoftwareTryReleaseEvent(QQuickWindow *win, bool destroy)
+ : QSGSoftwareWindowEvent(win, WM_TryRelease), destroying(destroy) { }
+ bool destroying;
+};
+
+class QSGSoftwareSyncEvent : public QSGSoftwareWindowEvent
+{
+public:
+ QSGSoftwareSyncEvent(QQuickWindow *c, bool inExpose, bool force)
+ : QSGSoftwareWindowEvent(c, WM_RequestSync)
+ , size(c->size())
+ , dpr(c->effectiveDevicePixelRatio())
+ , syncInExpose(inExpose)
+ , forceRenderPass(force) { }
+ QSize size;
+ float dpr;
+ bool syncInExpose;
+ bool forceRenderPass;
+};
+
+class QSGSoftwareGrabEvent : public QSGSoftwareWindowEvent
+{
+public:
+ QSGSoftwareGrabEvent(QQuickWindow *c, QImage *result)
+ : QSGSoftwareWindowEvent(c, WM_Grab), image(result) { }
+ QImage *image;
+};
+
+class QSGSoftwareJobEvent : public QSGSoftwareWindowEvent
+{
+public:
+ QSGSoftwareJobEvent(QQuickWindow *c, QRunnable *postedJob)
+ : QSGSoftwareWindowEvent(c, WM_PostJob), job(postedJob) { }
+ ~QSGSoftwareJobEvent() { delete job; }
+ QRunnable *job;
+};
+
+class QSGSoftwareEventQueue : public QQueue<QEvent *>
+{
+public:
+ void addEvent(QEvent *e) {
+ mutex.lock();
+ enqueue(e);
+ if (waiting)
+ condition.wakeOne();
+ mutex.unlock();
+ }
+
+ QEvent *takeEvent(bool wait) {
+ mutex.lock();
+ if (isEmpty() && wait) {
+ waiting = true;
+ condition.wait(&mutex);
+ waiting = false;
+ }
+ QEvent *e = dequeue();
+ mutex.unlock();
+ return e;
+ }
+
+ bool hasMoreEvents() {
+ mutex.lock();
+ bool has = !isEmpty();
+ mutex.unlock();
+ return has;
+ }
+
+private:
+ QMutex mutex;
+ QWaitCondition condition;
+ bool waiting = false;
+};
+
+static inline int qsgrl_animation_interval()
+{
+ const qreal refreshRate = QGuiApplication::primaryScreen() ? QGuiApplication::primaryScreen()->refreshRate() : 0;
+ return refreshRate < 1 ? 16 : int(1000 / refreshRate);
+}
+
+class QSGSoftwareRenderThread : public QThread
+{
+ Q_OBJECT
+public:
+ QSGSoftwareRenderThread(QSGSoftwareThreadedRenderLoop *rl, QSGRenderContext *renderContext)
+ : renderLoop(rl)
+ {
+ rc = static_cast<QSGSoftwareRenderContext *>(renderContext);
+ vsyncDelta = qsgrl_animation_interval();
+ }
+
+ ~QSGSoftwareRenderThread()
+ {
+ delete rc;
+ }
+
+ bool event(QEvent *e);
+ void run();
+
+ void syncAndRender();
+ void sync(bool inExpose);
+
+ void requestRepaint()
+ {
+ if (sleeping)
+ stopEventProcessing = true;
+ if (exposedWindow)
+ pendingUpdate |= RepaintRequest;
+ }
+
+ void processEventsAndWaitForMore();
+ void processEvents();
+ void postEvent(QEvent *e);
+
+ enum UpdateRequest {
+ SyncRequest = 0x01,
+ RepaintRequest = 0x02,
+ ExposeRequest = 0x04 | RepaintRequest | SyncRequest
+ };
+
+ QSGSoftwareThreadedRenderLoop *renderLoop;
+ QSGSoftwareRenderContext *rc;
+ QAnimationDriver *rtAnim = nullptr;
+ volatile bool active = false;
+ uint pendingUpdate = 0;
+ bool sleeping = false;
+ bool syncResultedInChanges = false;
+ float vsyncDelta;
+ QMutex mutex;
+ QWaitCondition waitCondition;
+ QQuickWindow *exposedWindow = nullptr;
+ QBackingStore *backingStore = nullptr;
+ bool stopEventProcessing = false;
+ QSGSoftwareEventQueue eventQueue;
+ QElapsedTimer renderThrottleTimer;
+ qint64 syncTime;
+ qint64 renderTime;
+ qint64 sinceLastTime;
+
+public slots:
+ void onSceneGraphChanged() {
+ syncResultedInChanges = true;
+ }
+};
+
+bool QSGSoftwareRenderThread::event(QEvent *e)
+{
+ switch ((int)e->type()) {
+
+ case WM_Obscure:
+ Q_ASSERT(!exposedWindow || exposedWindow == static_cast<QSGSoftwareWindowEvent *>(e)->window);
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "RT - WM_Obscure" << exposedWindow;
+ mutex.lock();
+ if (exposedWindow) {
+ QQuickWindowPrivate::get(exposedWindow)->fireAboutToStop();
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - WM_Obscure - window removed");
+ exposedWindow = nullptr;
+ delete backingStore;
+ backingStore = nullptr;
+ }
+ waitCondition.wakeOne();
+ mutex.unlock();
+ return true;
+
+ case WM_RequestSync: {
+ QSGSoftwareSyncEvent *wme = static_cast<QSGSoftwareSyncEvent *>(e);
+ if (sleeping)
+ stopEventProcessing = true;
+ exposedWindow = wme->window;
+ if (backingStore == nullptr)
+ backingStore = new QBackingStore(exposedWindow);
+ if (backingStore->size() != exposedWindow->size())
+ backingStore->resize(exposedWindow->size());
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "RT - WM_RequestSync" << exposedWindow;
+ pendingUpdate |= SyncRequest;
+ if (wme->syncInExpose) {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - WM_RequestSync - triggered from expose");
+ pendingUpdate |= ExposeRequest;
+ }
+ if (wme->forceRenderPass) {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - WM_RequestSync - repaint regardless");
+ pendingUpdate |= RepaintRequest;
+ }
+ return true;
+ }
+
+ case WM_TryRelease: {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - WM_TryRelease");
+ mutex.lock();
+ renderLoop->lockedForSync = true;
+ QSGSoftwareTryReleaseEvent *wme = static_cast<QSGSoftwareTryReleaseEvent *>(e);
+ // Only when no windows are exposed anymore or we are shutting down.
+ if (!exposedWindow || wme->destroying) {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - WM_TryRelease - invalidating rc");
+ if (wme->window) {
+ QQuickWindowPrivate *wd = QQuickWindowPrivate::get(wme->window);
+ if (wme->destroying) {
+ // Bye bye nodes...
+ wd->cleanupNodesOnShutdown();
+ }
+ rc->invalidate();
+ QCoreApplication::processEvents();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ if (wme->destroying)
+ delete wd->animationController;
+ }
+ if (wme->destroying)
+ active = false;
+ if (sleeping)
+ stopEventProcessing = true;
+ } else {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - WM_TryRelease - not releasing because window is still active");
+ }
+ waitCondition.wakeOne();
+ renderLoop->lockedForSync = false;
+ mutex.unlock();
+ return true;
+ }
+
+ case WM_Grab: {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - WM_Grab");
+ QSGSoftwareGrabEvent *wme = static_cast<QSGSoftwareGrabEvent *>(e);
+ Q_ASSERT(wme->window);
+ Q_ASSERT(wme->window == exposedWindow || !exposedWindow);
+ mutex.lock();
+ if (wme->window) {
+ // Grabbing is generally done by rendering a frame and reading the
+ // color buffer contents back, without presenting, and then
+ // creating a QImage from the returned data. It is terribly
+ // inefficient since it involves a full blocking wait for the GPU.
+ // However, our hands are tied by the existing, synchronous APIs of
+ // QQuickWindow and such.
+ QQuickWindowPrivate *wd = QQuickWindowPrivate::get(wme->window);
+ auto softwareRenderer = static_cast<QSGSoftwareRenderer*>(wd->renderer);
+ if (softwareRenderer)
+ softwareRenderer->setBackingStore(backingStore);
+ rc->initialize(nullptr);
+ wd->syncSceneGraph();
+ wd->renderSceneGraph(wme->window->size());
+ *wme->image = backingStore->handle()->toImage();
+ }
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - WM_Grab - waking gui to handle result");
+ waitCondition.wakeOne();
+ mutex.unlock();
+ return true;
+ }
+
+ case WM_PostJob: {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - WM_PostJob");
+ QSGSoftwareJobEvent *wme = static_cast<QSGSoftwareJobEvent *>(e);
+ Q_ASSERT(wme->window == exposedWindow);
+ if (exposedWindow) {
+ wme->job->run();
+ delete wme->job;
+ wme->job = nullptr;
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - WM_PostJob - job done");
+ }
+ return true;
+ }
+
+ case WM_RequestRepaint:
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - WM_RequestPaint");
+ // When GUI posts this event, it is followed by a polishAndSync, so we
+ // must not exit the event loop yet.
+ pendingUpdate |= RepaintRequest;
+ break;
+
+ default:
+ break;
+ }
+
+ return QThread::event(e);
+}
+
+void QSGSoftwareRenderThread::postEvent(QEvent *e)
+{
+ eventQueue.addEvent(e);
+}
+
+void QSGSoftwareRenderThread::processEvents()
+{
+ while (eventQueue.hasMoreEvents()) {
+ QEvent *e = eventQueue.takeEvent(false);
+ event(e);
+ delete e;
+ }
+}
+
+void QSGSoftwareRenderThread::processEventsAndWaitForMore()
+{
+ stopEventProcessing = false;
+ while (!stopEventProcessing) {
+ QEvent *e = eventQueue.takeEvent(true);
+ event(e);
+ delete e;
+ }
+}
+
+void QSGSoftwareRenderThread::run()
+{
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - run()");
+
+ rtAnim = rc->sceneGraphContext()->createAnimationDriver(nullptr);
+ rtAnim->install();
+
+ if (QQmlDebugConnector::service<QQmlProfilerService>())
+ QQuickProfiler::registerAnimationCallback();
+
+ renderThrottleTimer.start();
+
+ while (active) {
+ if (exposedWindow)
+ syncAndRender();
+
+ processEvents();
+ QCoreApplication::processEvents();
+
+ if (pendingUpdate == 0 || !exposedWindow) {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - done drawing, sleep");
+ sleeping = true;
+ processEventsAndWaitForMore();
+ sleeping = false;
+ }
+ }
+
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - run() exiting");
+
+ delete rtAnim;
+ rtAnim = nullptr;
+
+ rc->moveToThread(renderLoop->thread());
+ moveToThread(renderLoop->thread());
+}
+
+void QSGSoftwareRenderThread::sync(bool inExpose)
+{
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - sync");
+
+ mutex.lock();
+ Q_ASSERT_X(renderLoop->lockedForSync, "QSGD3D12RenderThread::sync()", "sync triggered with gui not locked");
+
+ if (exposedWindow) {
+ QQuickWindowPrivate *wd = QQuickWindowPrivate::get(exposedWindow);
+ bool hadRenderer = wd->renderer != nullptr;
+ // If the scene graph was touched since the last sync() make sure it sends the
+ // changed signal.
+ if (wd->renderer)
+ wd->renderer->clearChangedFlag();
+
+ rc->initialize(nullptr);
+ wd->syncSceneGraph();
+
+ if (!hadRenderer && wd->renderer) {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - created renderer");
+ syncResultedInChanges = true;
+ connect(wd->renderer, &QSGRenderer::sceneGraphChanged, this,
+ &QSGSoftwareRenderThread::onSceneGraphChanged, Qt::DirectConnection);
+ }
+
+ // Process deferred deletes now, directly after the sync as deleteLater
+ // on the GUI must now also have resulted in SG changes and the delete
+ // is a safe operation.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ }
+
+ if (!inExpose) {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - sync complete, waking gui");
+ waitCondition.wakeOne();
+ mutex.unlock();
+ }
+}
+
+void QSGSoftwareRenderThread::syncAndRender()
+{
+ Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphRenderLoopFrame);
+
+ QElapsedTimer waitTimer;
+ waitTimer.start();
+
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - syncAndRender()");
+
+ syncResultedInChanges = false;
+ QQuickWindowPrivate *wd = QQuickWindowPrivate::get(exposedWindow);
+
+ const bool repaintRequested = (pendingUpdate & RepaintRequest) || wd->customRenderStage;
+ const bool syncRequested = pendingUpdate & SyncRequest;
+ const bool exposeRequested = (pendingUpdate & ExposeRequest) == ExposeRequest;
+ pendingUpdate = 0;
+
+ if (syncRequested)
+ sync(exposeRequested);
+
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
+
+ if (!syncResultedInChanges && !repaintRequested) {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - no changes, render aborted");
+ int waitTime = vsyncDelta - (int) waitTimer.elapsed();
+ if (waitTime > 0)
+ msleep(waitTime);
+ return;
+ }
+
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - rendering started");
+
+ if (rtAnim->isRunning()) {
+ wd->animationController->lock();
+ rtAnim->advance();
+ wd->animationController->unlock();
+ }
+
+ bool canRender = wd->renderer != nullptr;
+
+ if (canRender) {
+ auto softwareRenderer = static_cast<QSGSoftwareRenderer*>(wd->renderer);
+ if (softwareRenderer)
+ softwareRenderer->setBackingStore(backingStore);
+ wd->renderSceneGraph(exposedWindow->size());
+
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
+
+ if (softwareRenderer && (!wd->customRenderStage || !wd->customRenderStage->swap()))
+ backingStore->flush(softwareRenderer->flushRegion());
+
+ // Since there is no V-Sync with QBackingStore, throttle rendering the refresh
+ // rate of the current screen the window is on.
+ int blockTime = vsyncDelta - (int) renderThrottleTimer.elapsed();
+ if (blockTime > 0) {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "RT - blocking for " << blockTime << "ms";
+ msleep(blockTime);
+ }
+ renderThrottleTimer.restart();
+
+ wd->fireFrameSwapped();
+ } else {
+ Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphRenderLoopFrame, 1);
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - window not ready, skipping render");
+ }
+
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - rendering done");
+
+ if (exposeRequested) {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - wake gui after initial expose");
+ waitCondition.wakeOne();
+ mutex.unlock();
+ }
+
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame);
+}
+
+template<class T> T *windowFor(const QVector<T> &list, QQuickWindow *window)
+{
+ for (const T &t : list) {
+ if (t.window == window)
+ return const_cast<T *>(&t);
+ }
+ return nullptr;
+}
+
+
+QSGSoftwareThreadedRenderLoop::QSGSoftwareThreadedRenderLoop()
+{
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "software threaded render loop constructor");
+ m_sg = new QSGSoftwareContext;
+ m_anim = m_sg->createAnimationDriver(this);
+ connect(m_anim, &QAnimationDriver::started, this, &QSGSoftwareThreadedRenderLoop::onAnimationStarted);
+ connect(m_anim, &QAnimationDriver::stopped, this, &QSGSoftwareThreadedRenderLoop::onAnimationStopped);
+ m_anim->install();
+}
+
+QSGSoftwareThreadedRenderLoop::~QSGSoftwareThreadedRenderLoop()
+{
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "software threaded render loop destructor");
+ delete m_sg;
+}
+
+void QSGSoftwareThreadedRenderLoop::show(QQuickWindow *window)
+{
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "show" << window;
+}
+
+void QSGSoftwareThreadedRenderLoop::hide(QQuickWindow *window)
+{
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "hide" << window;
+
+ if (window->isExposed())
+ handleObscurity(windowFor(m_windows, window));
+
+ releaseResources(window);
+}
+
+void QSGSoftwareThreadedRenderLoop::resize(QQuickWindow *window)
+{
+ if (!window->isExposed() || window->size().isEmpty())
+ return;
+
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "resize" << window << window->size();
+}
+
+void QSGSoftwareThreadedRenderLoop::windowDestroyed(QQuickWindow *window)
+{
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "window destroyed" << window;
+
+ WindowData *w = windowFor(m_windows, window);
+ if (!w)
+ return;
+
+ handleObscurity(w);
+ handleResourceRelease(w, true);
+
+ QSGSoftwareRenderThread *thread = w->thread;
+ while (thread->isRunning())
+ QThread::yieldCurrentThread();
+
+ Q_ASSERT(thread->thread() == QThread::currentThread());
+ delete thread;
+
+ for (int i = 0; i < m_windows.size(); ++i) {
+ if (m_windows.at(i).window == window) {
+ m_windows.removeAt(i);
+ break;
+ }
+ }
+}
+
+void QSGSoftwareThreadedRenderLoop::exposureChanged(QQuickWindow *window)
+{
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "exposure changed" << window;
+
+ if (window->isExposed()) {
+ handleExposure(window);
+ } else {
+ WindowData *w = windowFor(m_windows, window);
+ if (w)
+ handleObscurity(w);
+ }
+}
+
+QImage QSGSoftwareThreadedRenderLoop::grab(QQuickWindow *window)
+{
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "grab" << window;
+
+ WindowData *w = windowFor(m_windows, window);
+ // Have to support invisible (but created()'ed) windows as well.
+ // Unlike with GL, leaving that case for QQuickWindow to handle is not feasible.
+ const bool tempExpose = !w;
+ if (tempExpose) {
+ handleExposure(window);
+ w = windowFor(m_windows, window);
+ Q_ASSERT(w);
+ }
+
+ if (!w->thread->isRunning())
+ return QImage();
+
+ if (!window->handle())
+ window->create();
+
+ QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window);
+ wd->polishItems();
+
+ QImage result;
+ w->thread->mutex.lock();
+ lockedForSync = true;
+ w->thread->postEvent(new QSGSoftwareGrabEvent(window, &result));
+ w->thread->waitCondition.wait(&w->thread->mutex);
+ lockedForSync = false;
+ w->thread->mutex.unlock();
+
+ result.setDevicePixelRatio(window->effectiveDevicePixelRatio());
+
+ if (tempExpose)
+ handleObscurity(w);
+
+ return result;
+}
+
+void QSGSoftwareThreadedRenderLoop::update(QQuickWindow *window)
+{
+ WindowData *w = windowFor(m_windows, window);
+ if (!w)
+ return;
+
+ if (w->thread == QThread::currentThread()) {
+ w->thread->requestRepaint();
+ return;
+ }
+
+ // We set forceRenderPass because we want to make sure the QQuickWindow
+ // actually does a full render pass after the next sync.
+ w->forceRenderPass = true;
+ scheduleUpdate(w);
+}
+
+void QSGSoftwareThreadedRenderLoop::maybeUpdate(QQuickWindow *window)
+{
+ WindowData *w = windowFor(m_windows, window);
+ if (w)
+ scheduleUpdate(w);
+}
+
+void QSGSoftwareThreadedRenderLoop::handleUpdateRequest(QQuickWindow *window)
+{
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "handleUpdateRequest" << window;
+
+ WindowData *w = windowFor(m_windows, window);
+ if (w)
+ polishAndSync(w, false);
+}
+
+QAnimationDriver *QSGSoftwareThreadedRenderLoop::animationDriver() const
+{
+ return m_anim;
+}
+
+QSGContext *QSGSoftwareThreadedRenderLoop::sceneGraphContext() const
+{
+ return m_sg;
+}
+
+QSGRenderContext *QSGSoftwareThreadedRenderLoop::createRenderContext(QSGContext *) const
+{
+ return m_sg->createRenderContext();
+}
+
+void QSGSoftwareThreadedRenderLoop::releaseResources(QQuickWindow *window)
+{
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "releaseResources" << window;
+
+ WindowData *w = windowFor(m_windows, window);
+ if (w)
+ handleResourceRelease(w, false);
+}
+
+void QSGSoftwareThreadedRenderLoop::postJob(QQuickWindow *window, QRunnable *job)
+{
+ WindowData *w = windowFor(m_windows, window);
+ if (w && w->thread && w->thread->exposedWindow)
+ w->thread->postEvent(new QSGSoftwareJobEvent(window, job));
+ else
+ delete job;
+}
+
+QSurface::SurfaceType QSGSoftwareThreadedRenderLoop::windowSurfaceType() const
+{
+ return QSurface::RasterSurface;
+}
+
+bool QSGSoftwareThreadedRenderLoop::interleaveIncubation() const
+{
+ bool somethingVisible = false;
+ for (const WindowData &w : m_windows) {
+ if (w.window->isVisible() && w.window->isExposed()) {
+ somethingVisible = true;
+ break;
+ }
+ }
+ return somethingVisible && m_anim->isRunning();
+}
+
+int QSGSoftwareThreadedRenderLoop::flags() const
+{
+ return SupportsGrabWithoutExpose;
+}
+
+bool QSGSoftwareThreadedRenderLoop::event(QEvent *e)
+{
+ if (e->type() == QEvent::Timer) {
+ QTimerEvent *te = static_cast<QTimerEvent *>(e);
+ if (te->timerId() == animationTimer) {
+ m_anim->advance();
+ emit timeToIncubate();
+ return true;
+ }
+ }
+
+ return QObject::event(e);
+}
+
+void QSGSoftwareThreadedRenderLoop::onAnimationStarted()
+{
+ startOrStopAnimationTimer();
+
+ for (const WindowData &w : qAsConst(m_windows))
+ w.window->requestUpdate();
+}
+
+void QSGSoftwareThreadedRenderLoop::onAnimationStopped()
+{
+ startOrStopAnimationTimer();
+}
+
+void QSGSoftwareThreadedRenderLoop::startOrStopAnimationTimer()
+{
+ int exposedWindowCount = 0;
+ const WindowData *exposed = nullptr;
+
+ for (int i = 0; i < m_windows.size(); ++i) {
+ const WindowData &w(m_windows[i]);
+ if (w.window->isVisible() && w.window->isExposed()) {
+ ++exposedWindowCount;
+ exposed = &w;
+ }
+ }
+
+ if (animationTimer && (exposedWindowCount == 1 || !m_anim->isRunning())) {
+ killTimer(animationTimer);
+ animationTimer = 0;
+ // If animations are running, make sure we keep on animating
+ if (m_anim->isRunning())
+ exposed->window->requestUpdate();
+ } else if (!animationTimer && exposedWindowCount != 1 && m_anim->isRunning()) {
+ animationTimer = startTimer(qsgrl_animation_interval());
+ }
+}
+
+void QSGSoftwareThreadedRenderLoop::handleExposure(QQuickWindow *window)
+{
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "handleExposure" << window;
+
+ WindowData *w = windowFor(m_windows, window);
+ if (!w) {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "adding window to list");
+ WindowData win;
+ win.window = window;
+ QSGRenderContext *rc = QQuickWindowPrivate::get(window)->context; // will transfer ownership
+ win.thread = new QSGSoftwareRenderThread(this, rc);
+ win.updateDuringSync = false;
+ win.forceRenderPass = true; // also covered by polishAndSync(inExpose=true), but doesn't hurt
+ m_windows.append(win);
+ w = &m_windows.last();
+ }
+
+ // set this early as we'll be rendering shortly anyway and this avoids
+ // special casing exposure in polishAndSync.
+ w->thread->exposedWindow = window;
+
+ if (w->window->size().isEmpty()
+ || (w->window->isTopLevel() && !w->window->geometry().intersects(w->window->screen()->availableGeometry()))) {
+#ifndef QT_NO_DEBUG
+ qWarning().noquote().nospace() << "QSGSotwareThreadedRenderLoop: expose event received for window "
+ << w->window << " with invalid geometry: " << w->window->geometry()
+ << " on " << w->window->screen();
+#endif
+ }
+
+ if (!w->window->handle())
+ w->window->create();
+
+ // Start render thread if it is not running
+ if (!w->thread->isRunning()) {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "starting render thread");
+ // Push a few things to the render thread.
+ QQuickAnimatorController *controller = QQuickWindowPrivate::get(w->window)->animationController;
+ if (controller->thread() != w->thread)
+ controller->moveToThread(w->thread);
+ if (w->thread->thread() == QThread::currentThread()) {
+ w->thread->rc->moveToThread(w->thread);
+ w->thread->moveToThread(w->thread);
+ }
+
+ w->thread->active = true;
+ w->thread->start();
+
+ if (!w->thread->isRunning())
+ qFatal("Render thread failed to start, aborting application.");
+ }
+
+ polishAndSync(w, true);
+
+ startOrStopAnimationTimer();
+}
+
+void QSGSoftwareThreadedRenderLoop::handleObscurity(QSGSoftwareThreadedRenderLoop::WindowData *w)
+{
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "handleObscurity" << w->window;
+
+ if (w->thread->isRunning()) {
+ w->thread->mutex.lock();
+ w->thread->postEvent(new QSGSoftwareWindowEvent(w->window, WM_Obscure));
+ w->thread->waitCondition.wait(&w->thread->mutex);
+ w->thread->mutex.unlock();
+ }
+
+ startOrStopAnimationTimer();
+}
+
+void QSGSoftwareThreadedRenderLoop::scheduleUpdate(QSGSoftwareThreadedRenderLoop::WindowData *w)
+{
+ if (!QCoreApplication::instance())
+ return;
+
+ if (!w || !w->thread->isRunning())
+ return;
+
+ QThread *current = QThread::currentThread();
+ if (current != QCoreApplication::instance()->thread() && (current != w->thread || !lockedForSync)) {
+ qWarning() << "Updates can only be scheduled from GUI thread or from QQuickItem::updatePaintNode()";
+ return;
+ }
+
+ if (current == w->thread) {
+ w->updateDuringSync = true;
+ return;
+ }
+
+ w->window->requestUpdate();
+}
+
+void QSGSoftwareThreadedRenderLoop::handleResourceRelease(QSGSoftwareThreadedRenderLoop::WindowData *w, bool destroying)
+{
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "handleResourceRelease" << (destroying ? "destroying" : "hide/releaseResources") << w->window;
+
+ w->thread->mutex.lock();
+ if (w->thread->isRunning() && w->thread->active) {
+ QQuickWindow *window = w->window;
+
+ // Note that window->handle() is typically null by this time because
+ // the platform window is already destroyed. This should not be a
+ // problem for the D3D cleanup.
+
+ w->thread->postEvent(new QSGSoftwareTryReleaseEvent(window, destroying));
+ w->thread->waitCondition.wait(&w->thread->mutex);
+
+ // Avoid a shutdown race condition.
+ // If SG is invalidated and 'active' becomes false, the thread's run()
+ // method will exit. handleExposure() relies on QThread::isRunning() (because it
+ // potentially needs to start the thread again) and our mutex cannot be used to
+ // track the thread stopping, so we wait a few nanoseconds extra so the thread
+ // can exit properly.
+ if (!w->thread->active)
+ w->thread->wait();
+ }
+ w->thread->mutex.unlock();
+}
+
+void QSGSoftwareThreadedRenderLoop::polishAndSync(QSGSoftwareThreadedRenderLoop::WindowData *w, bool inExpose)
+{
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "polishAndSync" << (inExpose ? "(in expose)" : "(normal)") << w->window;
+
+ QQuickWindow *window = w->window;
+ if (!w->thread || !w->thread->exposedWindow) {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "polishAndSync - not exposed, abort");
+ return;
+ }
+
+ // Flush pending touch events.
+ QQuickWindowPrivate::get(window)->flushFrameSynchronousEvents();
+ // The delivery of the event might have caused the window to stop rendering
+ w = windowFor(m_windows, window);
+ if (!w || !w->thread || !w->thread->exposedWindow) {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "polishAndSync - removed after touch event flushing, abort");
+ return;
+ }
+
+ Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphPolishAndSync);
+
+ QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window);
+ wd->polishItems();
+
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
+
+ w->updateDuringSync = false;
+
+ emit window->afterAnimating();
+
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "polishAndSync - lock for sync");
+ w->thread->mutex.lock();
+ lockedForSync = true;
+ w->thread->postEvent(new QSGSoftwareSyncEvent(window, inExpose, w->forceRenderPass));
+ w->forceRenderPass = false;
+
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "polishAndSync - wait for sync");
+
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
+ w->thread->waitCondition.wait(&w->thread->mutex);
+ lockedForSync = false;
+ w->thread->mutex.unlock();
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "polishAndSync - unlock after sync");
+
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
+
+ if (!animationTimer && m_anim->isRunning()) {
+ qCDebug(QSG_RASTER_LOG_RENDERLOOP, "polishAndSync - advancing animations");
+ m_anim->advance();
+ // We need to trigger another sync to keep animations running...
+ w->window->requestUpdate();
+ emit timeToIncubate();
+ } else if (w->updateDuringSync) {
+ w->window->requestUpdate();
+ }
+
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphPolishAndSync);
+}
+
+#include "qsgsoftwarethreadedrenderloop.moc"
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop_p.h
new file mode 100644
index 0000000000..99993d651c
--- /dev/null
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop_p.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGSOFTWARETHREADEDRENDERLOOP_H
+#define QSGSOFTWARETHREADEDRENDERLOOP_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists 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/qsgrenderloop_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSGSoftwareRenderThread;
+class QSGSoftwareContext;
+
+class QSGSoftwareThreadedRenderLoop : public QSGRenderLoop
+{
+ Q_OBJECT
+public:
+ QSGSoftwareThreadedRenderLoop();
+ ~QSGSoftwareThreadedRenderLoop();
+
+ void show(QQuickWindow *window) override;
+ void hide(QQuickWindow *window) override;
+ void resize(QQuickWindow *window) override;
+ void windowDestroyed(QQuickWindow *window) override;
+ void exposureChanged(QQuickWindow *window) override;
+ QImage grab(QQuickWindow *window) override;
+ void update(QQuickWindow *window) override;
+ void maybeUpdate(QQuickWindow *window) override;
+ void handleUpdateRequest(QQuickWindow *window) override;
+ QAnimationDriver *animationDriver() const override;
+ QSGContext *sceneGraphContext() const override;
+ QSGRenderContext *createRenderContext(QSGContext *) const override;
+ void releaseResources(QQuickWindow *window) override;
+ void postJob(QQuickWindow *window, QRunnable *job) override;
+ QSurface::SurfaceType windowSurfaceType() const override;
+ bool interleaveIncubation() const override;
+ int flags() const override;
+
+ bool event(QEvent *e) override;
+
+public Q_SLOTS:
+ void onAnimationStarted();
+ void onAnimationStopped();
+
+private:
+ struct WindowData {
+ QQuickWindow *window;
+ QSGSoftwareRenderThread *thread;
+ uint updateDuringSync : 1;
+ uint forceRenderPass : 1;
+ };
+
+ void startOrStopAnimationTimer();
+ void handleExposure(QQuickWindow *window);
+ void handleObscurity(WindowData *w);
+ void scheduleUpdate(WindowData *w);
+ void handleResourceRelease(WindowData *w, bool destroying);
+ void polishAndSync(WindowData *w, bool inExpose);
+
+ QSGSoftwareContext *m_sg;
+ QAnimationDriver *m_anim;
+ int animationTimer = 0;
+ bool lockedForSync = false;
+ QVector<WindowData> m_windows;
+
+ friend class QSGSoftwareRenderThread;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSGSOFTWARETHREADEDRENDERLOOP_H
diff --git a/src/quick/scenegraph/adaptations/software/software.pri b/src/quick/scenegraph/adaptations/software/software.pri
index 1933a37d48..97644fc36a 100644
--- a/src/quick/scenegraph/adaptations/software/software.pri
+++ b/src/quick/scenegraph/adaptations/software/software.pri
@@ -19,7 +19,8 @@ SOURCES += \
$$PWD/qsgsoftwarerenderloop.cpp \
$$PWD/qsgsoftwarelayer.cpp \
$$PWD/qsgsoftwareadaptation.cpp \
- $$PWD/qsgsoftwarespritenode.cpp
+ $$PWD/qsgsoftwarespritenode.cpp \
+ $$PWD/qsgsoftwarethreadedrenderloop.cpp
HEADERS += \
$$PWD/qsgsoftwarecontext_p.h \
@@ -38,4 +39,5 @@ HEADERS += \
$$PWD/qsgsoftwarerenderloop_p.h \
$$PWD/qsgsoftwarelayer_p.h \
$$PWD/qsgsoftwareadaptation_p.h \
- $$PWD/qsgsoftwarespritenode_p.h
+ $$PWD/qsgsoftwarespritenode_p.h \
+ $$PWD/qsgsoftwarethreadedrenderloop_p.h
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index bee2015007..49bbbf0ba8 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -1033,11 +1033,13 @@ void Renderer::nodeWasAdded(QSGNode *node, Node *shadowParent)
m_rebuild |= FullRebuild;
} else if (node->type() == QSGNode::RenderNodeType) {
- RenderNodeElement *e = new RenderNodeElement(static_cast<QSGRenderNode *>(node));
+ QSGRenderNode *rn = static_cast<QSGRenderNode *>(node);
+ RenderNodeElement *e = new RenderNodeElement(rn);
snode->data = e;
- Q_ASSERT(!m_renderNodeElements.contains(static_cast<QSGRenderNode *>(node)));
+ Q_ASSERT(!m_renderNodeElements.contains(rn));
m_renderNodeElements.insert(e->renderNode, e);
- m_useDepthBuffer = false;
+ if (!rn->flags().testFlag(QSGRenderNode::DepthAwareRendering))
+ m_useDepthBuffer = false;
m_rebuild |= FullRebuild;
}
diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.cpp b/src/quick/scenegraph/coreapi/qsgrendernode.cpp
index 365abd09e2..5915d51f2b 100644
--- a/src/quick/scenegraph/coreapi/qsgrendernode.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrendernode.cpp
@@ -179,6 +179,11 @@ QSGRenderNode::StateFlags QSGRenderNode::changedStates() const
default value according to the OpenGL specification. For other APIs, see
the documentation for changedStates() for more information.
+ \note Depth writes are disabled when this function is called (for example,
+ glDepthMask(false) in case of OpenGL). Enabling depth writes can lead to
+ unexpected results, depending on the scenegraph backend in use, so nodes
+ should avoid this.
+
For APIs other than OpenGL, it will likely be necessary to query certain
API-specific resources (for example, the graphics device or the command
list/buffer to add the commands to). This is done via QSGRendererInterface.
@@ -211,6 +216,68 @@ void QSGRenderNode::releaseResources()
}
/*!
+ \enum QSGRenderNode::RenderingFlag
+
+ Possible values for the bitmask returned from flags().
+
+ \value BoundedRectRendering Indicates that the implementation of render()
+ does not render outside the area reported from rect() in item
+ coordinates. Such node implementations can lead to more efficient rendering,
+ depending on the scenegraph backend. For example, the software backend can
+ continue to use the more optimal partial update path when all render nodes
+ in the scene have this flag set.
+
+ \value DepthAwareRendering Indicates that the implementations of render()
+ conforms to scenegraph expectations by only generating a Z value of 0 in
+ scene coordinates which is then transformed by the matrices retrieved from
+ RenderState::projectionMatrix() and matrix(), as described in the notes for
+ render(). Such node implementations can lead to more efficient rendering,
+ depending on the scenegraph backend. For example, the batching OpenGL
+ renderer can continue to use a more optimal path when all render nodes in
+ the scene have this flag set.
+
+ \value OpaqueRendering Indicates that the implementation of render() writes
+ out opaque pixels for the entire area reported from rect(). By default the
+ renderers must assume that render() can also output semi or fully
+ transparent pixels. Setting this flag can improve performance in some
+ cases.
+
+ \sa render(), rect()
+ */
+
+/*!
+ \return flags describing the behavior of this render node.
+
+ The default implementation returns 0.
+
+ \sa RenderingFlag, rect()
+ */
+QSGRenderNode::RenderingFlags QSGRenderNode::flags() const
+{
+ return 0;
+}
+
+/*!
+ \return the bounding rectangle in item coordinates for the area render()
+ touches. The value is only in use when flags() includes
+ BoundedRectRendering, ignored otherwise.
+
+ Reporting the rectangle in combination with BoundedRectRendering is
+ particularly important with the \c software backend because otherwise
+ having a rendernode in the scene would trigger fullscreen updates, skipping
+ all partial update optimizations.
+
+ For rendernodes covering the entire area of a corresponding QQuickItem the
+ return value will be (0, 0, item->width(), item->height()).
+
+ \sa flags()
+*/
+QRectF QSGRenderNode::rect() const
+{
+ return QRectF();
+}
+
+/*!
\return pointer to the current model-view matrix.
*/
const QMatrix4x4 *QSGRenderNode::matrix() const
diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.h b/src/quick/scenegraph/coreapi/qsgrendernode.h
index 6eb425c03b..f6bc40d3ee 100644
--- a/src/quick/scenegraph/coreapi/qsgrendernode.h
+++ b/src/quick/scenegraph/coreapi/qsgrendernode.h
@@ -61,6 +61,13 @@ public:
};
Q_DECLARE_FLAGS(StateFlags, StateFlag)
+ enum RenderingFlag {
+ BoundedRectRendering = 0x01,
+ DepthAwareRendering = 0x02,
+ OpaqueRendering = 0x04
+ };
+ Q_DECLARE_FLAGS(RenderingFlags, RenderingFlag)
+
struct Q_QUICK_EXPORT RenderState {
virtual ~RenderState();
virtual const QMatrix4x4 *projectionMatrix() const = 0;
@@ -78,6 +85,8 @@ public:
virtual StateFlags changedStates() const;
virtual void render(const RenderState *state) = 0;
virtual void releaseResources();
+ virtual RenderingFlags flags() const;
+ virtual QRectF rect() const;
const QMatrix4x4 *matrix() const;
const QSGClipNode *clipList() const;
@@ -89,6 +98,7 @@ private:
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QSGRenderNode::StateFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSGRenderNode::RenderingFlags)
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 3ff32b360d..6b9c67b2bd 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -600,7 +600,7 @@ void QSGRenderThread::syncAndRender()
#endif
Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
- if (!syncResultedInChanges && !repaintRequested) {
+ if (!syncResultedInChanges && !repaintRequested && sgrc->isValid()) {
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- no changes, render aborted";
int waitTime = vsyncDelta - (int) waitTimer.elapsed();
if (waitTime > 0)
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index 098a4a666b..40c3293c7b 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -158,13 +158,13 @@ Atlas::Atlas(const QSize &size)
wrongfullyReportsBgra8888Support = false;
const char *ext = (const char *) QOpenGLContext::currentContext()->functions()->glGetString(GL_EXTENSIONS);
- if (!wrongfullyReportsBgra8888Support
+ if (ext && !wrongfullyReportsBgra8888Support
&& (strstr(ext, "GL_EXT_bgra")
|| strstr(ext, "GL_EXT_texture_format_BGRA8888")
|| strstr(ext, "GL_IMG_texture_format_BGRA8888"))) {
m_internalFormat = m_externalFormat = GL_BGRA;
#if defined(Q_OS_DARWIN) && !defined(Q_OS_OSX)
- } else if (strstr(ext, "GL_APPLE_texture_format_BGRA8888")) {
+ } else if (ext && strstr(ext, "GL_APPLE_texture_format_BGRA8888")) {
m_internalFormat = GL_RGBA;
m_externalFormat = GL_BGRA;
#endif // IOS || TVOS
diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp
index 741a583803..d782f9309f 100644
--- a/src/quick/util/qquickanimation.cpp
+++ b/src/quick/util/qquickanimation.cpp
@@ -1202,7 +1202,7 @@ QAbstractAnimationJob* QQuickPropertyAction::transition(QQuickStateActions &acti
{
for (int ii = 0; ii < actions.count(); ++ii) {
const QQuickStateAction &action = actions.at(ii);
- QQmlPropertyPrivate::write(action.property, action.toValue, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
+ QQmlPropertyPrivate::write(action.property, action.toValue, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
}
}
virtual void debugAction(QDebug d, int indentLevel) const {
@@ -2535,7 +2535,7 @@ void QQuickAnimationPropertyUpdater::setValue(qreal v)
QQuickStateAction &action = actions[ii];
if (v == 1.) {
- QQmlPropertyPrivate::write(action.property, action.toValue, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
+ QQmlPropertyPrivate::write(action.property, action.toValue, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
} else {
if (!fromSourced && !fromDefined) {
action.fromValue = action.property.read();
@@ -2551,7 +2551,7 @@ void QQuickAnimationPropertyUpdater::setValue(qreal v)
}
}
if (interpolator)
- QQmlPropertyPrivate::write(action.property, interpolator(action.fromValue.constData(), action.toValue.constData(), v), QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
+ QQmlPropertyPrivate::write(action.property, interpolator(action.fromValue.constData(), action.toValue.constData(), v), QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
}
if (deleted)
return;
diff --git a/src/quick/util/qquickbehavior.cpp b/src/quick/util/qquickbehavior.cpp
index 147380037d..1d3ee2c4be 100644
--- a/src/quick/util/qquickbehavior.cpp
+++ b/src/quick/util/qquickbehavior.cpp
@@ -180,7 +180,7 @@ void QQuickBehavior::write(const QVariant &value)
if (!d->animation || bypass) {
if (d->animationInstance)
d->animationInstance->stop();
- QQmlPropertyPrivate::write(d->property, value, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
+ QQmlPropertyPrivate::write(d->property, value, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
d->targetValue = value;
return;
}
@@ -206,7 +206,7 @@ void QQuickBehavior::write(const QVariant &value)
// is needed (value has not changed). If the Behavior was already
// running, let it continue as normal to ensure correct behavior and state.
if (!behaviorActive && d->targetValue == currentValue) {
- QQmlPropertyPrivate::write(d->property, value, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
+ QQmlPropertyPrivate::write(d->property, value, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
return;
}
@@ -234,7 +234,7 @@ void QQuickBehavior::write(const QVariant &value)
d->blockRunningChanged = false;
}
if (!after.contains(d->property))
- QQmlPropertyPrivate::write(d->property, value, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
+ QQmlPropertyPrivate::write(d->property, value, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
}
void QQuickBehavior::setTarget(const QQmlProperty &property)
diff --git a/src/quick/util/qquickprofiler.cpp b/src/quick/util/qquickprofiler.cpp
index 659ffe1d84..841a1c9bcf 100644
--- a/src/quick/util/qquickprofiler.cpp
+++ b/src/quick/util/qquickprofiler.cpp
@@ -70,7 +70,7 @@ void QQuickProfiler::registerAnimationCallback()
class CallbackRegistrationHelper : public QObject {
Q_OBJECT
-public slots:
+public:
void registerAnimationTimerCallback()
{
QQuickProfiler::registerAnimationCallback();
@@ -86,7 +86,12 @@ QQuickProfiler::QQuickProfiler(QObject *parent) : QObject(parent)
m_timer.start();
CallbackRegistrationHelper *helper = new CallbackRegistrationHelper; // will delete itself
helper->moveToThread(QCoreApplication::instance()->thread());
- QMetaObject::invokeMethod(helper, "registerAnimationTimerCallback", Qt::QueuedConnection);
+
+ // Queue the signal to have the animation timer registration run in the right thread;
+ QObject signalSource;
+ connect(&signalSource, &QObject::destroyed,
+ helper, &CallbackRegistrationHelper::registerAnimationTimerCallback,
+ Qt::QueuedConnection);
}
QQuickProfiler::~QQuickProfiler()
diff --git a/src/quick/util/qquickprofiler_p.h b/src/quick/util/qquickprofiler_p.h
index f1af87f4e6..66ed212722 100644
--- a/src/quick/util/qquickprofiler_p.h
+++ b/src/quick/util/qquickprofiler_p.h
@@ -62,52 +62,22 @@
QT_BEGIN_NAMESPACE
+#ifdef QT_NO_QML_DEBUGGER
+
+#define Q_QUICK_PROFILE_IF_ENABLED(feature, Code)
+
+struct QQuickProfiler {
+ static void registerAnimationCallback() {}
+};
+
+#else
+
#define Q_QUICK_PROFILE_IF_ENABLED(feature, Code)\
if (QQuickProfiler::featuresEnabled & (1 << feature)) {\
Code;\
} else\
(void)0
-#define Q_QUICK_PROFILE(feature, Method)\
- Q_QUICK_PROFILE_IF_ENABLED(feature, QQuickProfiler::Method)
-
-#define Q_QUICK_SG_PROFILE_START(Type)\
- Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
- (QQuickProfiler::startSceneGraphFrame<Type>()))
-
-#define Q_QUICK_SG_PROFILE_RECORD(Type)\
- Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
- (QQuickProfiler::recordSceneGraphTimestamp<Type>()))
-
-#define Q_QUICK_SG_PROFILE_SKIP(Type, Skip)\
- Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
- (QQuickProfiler::skipSceneGraphTimestamps<Type, Skip>()))
-
-#define Q_QUICK_SG_PROFILE_START_SYNCHRONIZED(Type1, Type2)\
- Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
- (QQuickProfiler::startSceneGraphFrame<Type1, Type2>()))
-
-#define Q_QUICK_SG_PROFILE_SWITCH(Type1, Type2) \
- Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
- (QQuickProfiler::reportSceneGraphFrame<Type1, true, Type2>()))
-
-#define Q_QUICK_SG_PROFILE_REPORT(Type)\
- Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
- (QQuickProfiler::reportSceneGraphFrame<Type, false>()))
-
-#define Q_QUICK_SG_PROFILE_END(Type)\
- Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
- (QQuickProfiler::reportSceneGraphFrame<Type, true>()))
-
-#define Q_QUICK_SG_PROFILE_END_WITH_PAYLOAD(Type, Payload)\
- Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
- (QQuickProfiler::reportSceneGraphFrame<Type, true>(Payload)))
-
-
-#define Q_QUICK_INPUT_PROFILE(Type, DetailType, A, B)\
- Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileInputEvents,\
- (QQuickProfiler::inputEvent<Type, DetailType>(A, B)))
-
// This struct is somewhat dangerous to use:
// You can save values either with 32 or 64 bit precision. toByteArrays will
// guess the precision from messageType. If you state the wrong messageType
@@ -319,17 +289,15 @@ public:
qint64 timestamp() { return m_timer.nsecsElapsed(); }
-
static quint64 featuresEnabled;
- static bool profilingSceneGraph()
- {
- return featuresEnabled & (1 << QQuickProfiler::ProfileSceneGraph);
- }
static void initialize(QObject *parent);
virtual ~QQuickProfiler();
+signals:
+ void dataReady(const QVector<QQuickProfilerData> &data);
+
protected:
friend class QQuickProfilerAdapter;
@@ -347,16 +315,54 @@ protected:
m_data.append(message);
}
-signals:
- void dataReady(const QVector<QQuickProfilerData> &data);
-
-protected slots:
void startProfilingImpl(quint64 features);
void stopProfilingImpl();
void reportDataImpl(bool trackLocations);
void setTimer(const QElapsedTimer &t);
};
+#endif // QT_NO_QML_DEBUGGER
+
+#define Q_QUICK_PROFILE(feature, Method)\
+ Q_QUICK_PROFILE_IF_ENABLED(feature, QQuickProfiler::Method)
+
+#define Q_QUICK_SG_PROFILE_START(Type)\
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::startSceneGraphFrame<Type>()))
+
+#define Q_QUICK_SG_PROFILE_RECORD(Type)\
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::recordSceneGraphTimestamp<Type>()))
+
+#define Q_QUICK_SG_PROFILE_SKIP(Type, Skip)\
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::skipSceneGraphTimestamps<Type, Skip>()))
+
+#define Q_QUICK_SG_PROFILE_START_SYNCHRONIZED(Type1, Type2)\
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::startSceneGraphFrame<Type1, Type2>()))
+
+#define Q_QUICK_SG_PROFILE_SWITCH(Type1, Type2) \
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::reportSceneGraphFrame<Type1, true, Type2>()))
+
+#define Q_QUICK_SG_PROFILE_REPORT(Type)\
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::reportSceneGraphFrame<Type, false>()))
+
+#define Q_QUICK_SG_PROFILE_END(Type)\
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::reportSceneGraphFrame<Type, true>()))
+
+#define Q_QUICK_SG_PROFILE_END_WITH_PAYLOAD(Type, Payload)\
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::reportSceneGraphFrame<Type, true>(Payload)))
+
+
+#define Q_QUICK_INPUT_PROFILE(Type, DetailType, A, B)\
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileInputEvents,\
+ (QQuickProfiler::inputEvent<Type, DetailType>(A, B)))
+
QT_END_NAMESPACE
#endif
diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp
index a42ec31058..c4be68cd31 100644
--- a/src/quick/util/qquickpropertychanges.cpp
+++ b/src/quick/util/qquickpropertychanges.cpp
@@ -597,7 +597,7 @@ void QQuickPropertyChanges::changeValue(const QString &name, const QVariant &val
state()->addEntryToRevertList(action);
QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(action.property);
if (oldBinding)
- oldBinding->setEnabled(false, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
+ oldBinding->setEnabled(false, QQmlPropertyData::DontRemoveBinding | QQmlPropertyData::BypassInterceptor);
d->property(name).write(value);
}
}
@@ -631,7 +631,7 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString
&QQmlPropertyPrivate::get(prop)->core, expression, object(),
qmlContext(this));
newBinding->setTarget(prop);
- QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
+ QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyData::DontRemoveBinding | QQmlPropertyData::BypassInterceptor);
}
return;
}
@@ -644,7 +644,7 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString
if (hadValue) {
QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(d->property(name));
if (oldBinding) {
- oldBinding->setEnabled(false, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
+ oldBinding->setEnabled(false, QQmlPropertyData::DontRemoveBinding | QQmlPropertyData::BypassInterceptor);
state()->changeBindingInRevertList(object(), name, oldBinding);
}
@@ -653,7 +653,7 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString
&QQmlPropertyPrivate::get(prop)->core, expression, object(),
qmlContext(this));
newBinding->setTarget(prop);
- QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
+ QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyData::DontRemoveBinding | QQmlPropertyData::BypassInterceptor);
} else {
QQuickStateAction action;
action.restore = restoreEntryValues();
@@ -679,9 +679,9 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString
state()->addEntryToRevertList(action);
QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(action.property);
if (oldBinding)
- oldBinding->setEnabled(false, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
+ oldBinding->setEnabled(false, QQmlPropertyData::DontRemoveBinding | QQmlPropertyData::BypassInterceptor);
- QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
+ QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyData::DontRemoveBinding | QQmlPropertyData::BypassInterceptor);
}
}
}
diff --git a/src/quick/util/qquicksmoothedanimation.cpp b/src/quick/util/qquicksmoothedanimation.cpp
index 569cb37c95..a992589040 100644
--- a/src/quick/util/qquicksmoothedanimation.cpp
+++ b/src/quick/util/qquicksmoothedanimation.cpp
@@ -254,8 +254,8 @@ void QSmoothedAnimation::updateCurrentTime(int t)
qreal value = easeFollow(time_seconds);
value *= (invert? -1.0: 1.0);
QQmlPropertyPrivate::write(target, initialValue + value,
- QQmlPropertyPrivate::BypassInterceptor
- | QQmlPropertyPrivate::DontRemoveBinding);
+ QQmlPropertyData::BypassInterceptor
+ | QQmlPropertyData::DontRemoveBinding);
}
void QSmoothedAnimation::init()
@@ -287,8 +287,8 @@ void QSmoothedAnimation::init()
break;
case QQuickSmoothedAnimation::Sync:
QQmlPropertyPrivate::write(target, to,
- QQmlPropertyPrivate::BypassInterceptor
- | QQmlPropertyPrivate::DontRemoveBinding);
+ QQmlPropertyData::BypassInterceptor
+ | QQmlPropertyData::DontRemoveBinding);
trackVelocity = 0;
stop();
return;
@@ -304,8 +304,8 @@ void QSmoothedAnimation::init()
if (!recalc()) {
QQmlPropertyPrivate::write(target, to,
- QQmlPropertyPrivate::BypassInterceptor
- | QQmlPropertyPrivate::DontRemoveBinding);
+ QQmlPropertyData::BypassInterceptor
+ | QQmlPropertyData::DontRemoveBinding);
stop();
return;
}
diff --git a/src/quick/util/qquickspringanimation.cpp b/src/quick/util/qquickspringanimation.cpp
index d2bc3b4ece..294122150a 100644
--- a/src/quick/util/qquickspringanimation.cpp
+++ b/src/quick/util/qquickspringanimation.cpp
@@ -301,8 +301,8 @@ void QSpringAnimation::updateCurrentTime(int time)
qreal old_to = to;
QQmlPropertyPrivate::write(target, currentValue,
- QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::DontRemoveBinding);
+ QQmlPropertyData::BypassInterceptor |
+ QQmlPropertyData::DontRemoveBinding);
if (stopped && old_to == to) { // do not stop if we got restarted
if (animationTemplate)
diff --git a/src/quick/util/qquicktransitionmanager.cpp b/src/quick/util/qquicktransitionmanager.cpp
index 55abb0a207..60f710549b 100644
--- a/src/quick/util/qquicktransitionmanager.cpp
+++ b/src/quick/util/qquicktransitionmanager.cpp
@@ -159,9 +159,9 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
for (int ii = 0; ii < applyList.size(); ++ii) {
const QQuickStateAction &action = applyList.at(ii);
if (action.toBinding) {
- QQmlPropertyPrivate::setBinding(action.toBinding.data(), QQmlPropertyPrivate::None, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
+ QQmlPropertyPrivate::setBinding(action.toBinding.data(), QQmlPropertyPrivate::None, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
} else if (!action.event) {
- QQmlPropertyPrivate::write(action.property, action.toValue, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
+ QQmlPropertyPrivate::write(action.property, action.toValue, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
} else if (action.event->isReversable()) {
if (action.reverseEvent)
action.event->reverse();
@@ -197,7 +197,7 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
if (action.toBinding)
QQmlPropertyPrivate::removeBinding(action.property); // Make sure this is disabled during the transition
- QQmlPropertyPrivate::write(action.property, action.fromValue, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding);
+ QQmlPropertyPrivate::write(action.property, action.fromValue, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
}
}
diff --git a/src/quick/util/qquickvaluetypes.cpp b/src/quick/util/qquickvaluetypes.cpp
index 7b9b6068bd..e673df0451 100644
--- a/src/quick/util/qquickvaluetypes.cpp
+++ b/src/quick/util/qquickvaluetypes.cpp
@@ -80,6 +80,36 @@ qreal QQuickColorValueType::a() const
return v.alphaF();
}
+qreal QQuickColorValueType::hsvHue() const
+{
+ return v.hsvHueF();
+}
+
+qreal QQuickColorValueType::hsvSaturation() const
+{
+ return v.hsvSaturationF();
+}
+
+qreal QQuickColorValueType::hsvValue() const
+{
+ return v.valueF();
+}
+
+qreal QQuickColorValueType::hslHue() const
+{
+ return v.hslHueF();
+}
+
+qreal QQuickColorValueType::hslSaturation() const
+{
+ return v.hslSaturationF();
+}
+
+qreal QQuickColorValueType::hslLightness() const
+{
+ return v.lightnessF();
+}
+
void QQuickColorValueType::setR(qreal r)
{
v.setRedF(r);
@@ -100,6 +130,48 @@ void QQuickColorValueType::setA(qreal a)
v.setAlphaF(a);
}
+void QQuickColorValueType::setHsvHue(qreal hsvHue)
+{
+ qreal hue, saturation, value, alpha;
+ v.getHsvF(&hue, &saturation, &value, &alpha);
+ v.setHsvF(hsvHue, saturation, value, alpha);
+}
+
+void QQuickColorValueType::setHsvSaturation(qreal hsvSaturation)
+{
+ qreal hue, saturation, value, alpha;
+ v.getHsvF(&hue, &saturation, &value, &alpha);
+ v.setHsvF(hue, hsvSaturation, value, alpha);
+}
+
+void QQuickColorValueType::setHsvValue(qreal hsvValue)
+{
+ qreal hue, saturation, value, alpha;
+ v.getHsvF(&hue, &saturation, &value, &alpha);
+ v.setHsvF(hue, saturation, hsvValue, alpha);
+}
+
+void QQuickColorValueType::setHslHue(qreal hslHue)
+{
+ qreal hue, saturation, lightness, alpha;
+ v.getHslF(&hue, &saturation, &lightness, &alpha);
+ v.setHslF(hslHue, saturation, lightness, alpha);
+}
+
+void QQuickColorValueType::setHslSaturation(qreal hslSaturation)
+{
+ qreal hue, saturation, lightness, alpha;
+ v.getHslF(&hue, &saturation, &lightness, &alpha);
+ v.setHslF(hue, hslSaturation, lightness, alpha);
+}
+
+void QQuickColorValueType::setHslLightness(qreal hslLightness)
+{
+ qreal hue, saturation, lightness, alpha;
+ v.getHslF(&hue, &saturation, &lightness, &alpha);
+ v.setHslF(hue, saturation, hslLightness, alpha);
+}
+
QString QQuickVector2DValueType::toString() const
{
return QString(QLatin1String("QVector2D(%1, %2)")).arg(v.x()).arg(v.y());
diff --git a/src/quick/util/qquickvaluetypes_p.h b/src/quick/util/qquickvaluetypes_p.h
index 05e954f915..4a1598ec5c 100644
--- a/src/quick/util/qquickvaluetypes_p.h
+++ b/src/quick/util/qquickvaluetypes_p.h
@@ -78,6 +78,12 @@ class QQuickColorValueType
Q_PROPERTY(qreal g READ g WRITE setG FINAL)
Q_PROPERTY(qreal b READ b WRITE setB FINAL)
Q_PROPERTY(qreal a READ a WRITE setA FINAL)
+ Q_PROPERTY(qreal hsvHue READ hsvHue WRITE setHsvHue FINAL)
+ Q_PROPERTY(qreal hsvSaturation READ hsvSaturation WRITE setHsvSaturation FINAL)
+ Q_PROPERTY(qreal hsvValue READ hsvValue WRITE setHsvValue FINAL)
+ Q_PROPERTY(qreal hslHue READ hslHue WRITE setHslHue FINAL)
+ Q_PROPERTY(qreal hslSaturation READ hslSaturation WRITE setHslSaturation FINAL)
+ Q_PROPERTY(qreal hslLightness READ hslLightness WRITE setHslLightness FINAL)
Q_GADGET
public:
Q_INVOKABLE QString toString() const;
@@ -86,10 +92,22 @@ public:
qreal g() const;
qreal b() const;
qreal a() const;
+ qreal hsvHue() const;
+ qreal hsvSaturation() const;
+ qreal hsvValue() const;
+ qreal hslHue() const;
+ qreal hslSaturation() const;
+ qreal hslLightness() const;
void setR(qreal);
void setG(qreal);
void setB(qreal);
void setA(qreal);
+ void setHsvHue(qreal);
+ void setHsvSaturation(qreal);
+ void setHsvValue(qreal);
+ void setHslHue(qreal);
+ void setHslSaturation(qreal);
+ void setHslLightness(qreal);
};
class QQuickVector2DValueType
diff --git a/src/quick/util/util.pri b/src/quick/util/util.pri
index ffb31ae75e..66792536d7 100644
--- a/src/quick/util/util.pri
+++ b/src/quick/util/util.pri
@@ -26,12 +26,13 @@ SOURCES += \
$$PWD/qquickanimator.cpp \
$$PWD/qquickanimatorjob.cpp \
$$PWD/qquickanimatorcontroller.cpp \
- $$PWD/qquickprofiler.cpp \
$$PWD/qquickfontmetrics.cpp \
$$PWD/qquicktextmetrics.cpp \
$$PWD/qquickshortcut.cpp \
$$PWD/qquickvalidator.cpp
+!contains(QT_CONFIG, no-qml-debug): SOURCES += $$PWD/qquickprofiler.cpp
+
HEADERS += \
$$PWD/qquickapplication_p.h\
$$PWD/qquickutilmodule_p.h\
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
index 4568d25dc1..40e19d375d 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
@@ -1223,16 +1223,15 @@ void tst_QQmlEngineDebugService::queryObjectTree()
int main(int argc, char *argv[])
{
int _argc = argc + 1;
- char **_argv = new char*[_argc];
+ QScopedArrayPointer<char *>_argv(new char*[_argc]);
for (int i = 0; i < argc; ++i)
_argv[i] = argv[i];
char arg[] = "-qmljsdebugger=port:3768,services:QmlDebugger";
_argv[_argc - 1] = arg;
- QGuiApplication app(_argc, _argv);
+ QGuiApplication app(_argc, _argv.data());
tst_QQmlEngineDebugService tc;
- return QTest::qExec(&tc, _argc, _argv);
- delete _argv;
+ return QTest::qExec(&tc, _argc, _argv.data());
}
#include "tst_qqmlenginedebugservice.moc"
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
index 52c9953970..c4b17aa60a 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
@@ -609,12 +609,11 @@ void tst_QQmlProfilerService::scenegraphData()
checkTraceReceived();
checkJsHeap();
-
- // check that at least one frame was rendered
- // there should be a SGPolishAndSync + SGRendererFrame + SGRenderLoopFrame sequence
- // (though we can't be sure to get the SGRenderLoopFrame in the threaded renderer)
+ // Check that at least one frame was rendered.
+ // There should be a SGContextFrame + SGRendererFrame + SGRenderLoopFrame sequence,
+ // but we can't be sure to get the SGRenderLoopFrame in the threaded renderer.
//
- // since the rendering happens in a different thread, there could be other unrelated events
+ // Since the rendering happens in a different thread, there could be other unrelated events
// interleaved. Also, events could carry the same time stamps and be sorted in an unexpected way
// if the clocks are acting up.
qint64 contextFrameTime = -1;
@@ -643,8 +642,13 @@ void tst_QQmlProfilerService::scenegraphData()
foreach (const QQmlProfilerData &msg, m_client->asynchronousMessages) {
if (msg.detailType == QQmlProfilerDefinitions::SceneGraphRenderLoopFrame) {
- QVERIFY(msg.time >= renderFrameTime);
- break;
+ if (msg.time >= contextFrameTime) {
+ // Make sure SceneGraphRenderLoopFrame is not between SceneGraphContextFrame and
+ // SceneGraphRendererFrame. A SceneGraphRenderLoopFrame before everything else is
+ // OK as the scene graph might decide to do an initial rendering.
+ QVERIFY(msg.time >= renderFrameTime);
+ break;
+ }
}
}
}
diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
index 3f89913f3b..a23b7e37eb 100644
--- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
+++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
@@ -326,7 +326,7 @@ private slots:
private:
QV4Debugger *debugger() const
{
- return static_cast<QV4Debugger *>(m_v4->debugger);
+ return static_cast<QV4Debugger *>(m_v4->debugger());
}
void evaluateJavaScript(const QString &script, const QString &fileName, int lineNumber = 1)
{
@@ -444,7 +444,7 @@ void tst_qv4debugger::addBreakPointWhilePaused()
static QV4::ReturnedValue someCall(QV4::CallContext *ctx)
{
- static_cast<QV4Debugger *>(ctx->d()->engine->debugger)
+ static_cast<QV4Debugger *>(ctx->d()->engine->debugger())
->removeBreakPoint("removeBreakPointForNextInstruction", 2);
return QV4::Encode::undefined();
}
diff --git a/tests/auto/qml/debugger/shared/debugutil_p.h b/tests/auto/qml/debugger/shared/debugutil_p.h
index 6fe5d897e0..1ec0a6513d 100644
--- a/tests/auto/qml/debugger/shared/debugutil_p.h
+++ b/tests/auto/qml/debugger/shared/debugutil_p.h
@@ -135,8 +135,6 @@ public:
int lastResponseId;
bool lastResult;
-public slots:
-
void recordResponse(int requestId, bool result)
{
lastResponseId = requestId;
diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
index bb78f2856f..1fe63bb99a 100644
--- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
+++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
@@ -29,6 +29,11 @@
#include <qtest.h>
#include <private/qv4compileddata_p.h>
+#include <private/qv4compiler_p.h>
+#include <private/qv4jsir_p.h>
+#include <private/qv4isel_p.h>
+#include <private/qv8engine_p.h>
+#include <private/qv4engine_p.h>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QThread>
@@ -42,6 +47,7 @@ private slots:
void regenerateAfterChange();
void registerImportForImplicitComponent();
+ void basicVersionChecks();
};
struct TestCompiler
@@ -58,11 +64,8 @@ struct TestCompiler
bool compile(const QByteArray &contents)
{
- if (currentMapping) {
- mappedFile.unmap(currentMapping);
- currentMapping = nullptr;
- }
- mappedFile.close();
+ closeMapping();
+ engine->clearComponentCache();
// Qt API limits the precision of QFileInfo::modificationTime() to seconds, so to ensure that
// the newly written file has a modification date newer than an existing cache file, we must
@@ -106,6 +109,44 @@ struct TestCompiler
return unitPtr;
}
+ typedef void (*HeaderTweakFunction)(QV4::CompiledData::Unit *header);
+ bool tweakHeader(HeaderTweakFunction function)
+ {
+ closeMapping();
+
+ QFile f(cacheFilePath);
+ if (!f.open(QIODevice::ReadWrite))
+ return false;
+ QV4::CompiledData::Unit header;
+ if (f.read(reinterpret_cast<char *>(&header), sizeof(header)) != sizeof(header))
+ return false;
+ function(&header);
+ f.seek(0);
+ return f.write(reinterpret_cast<const char *>(&header), sizeof(header)) == sizeof(header);
+ }
+
+ bool verify()
+ {
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = v4->iselFactory->createUnitForLoading();
+ return unit->loadFromDisk(QUrl::fromLocalFile(testFilePath), v4->iselFactory.data(), &lastErrorString);
+ }
+
+ void closeMapping()
+ {
+ if (currentMapping) {
+ mappedFile.unmap(currentMapping);
+ currentMapping = nullptr;
+ }
+ mappedFile.close();
+ }
+
+ void clearCache()
+ {
+ closeMapping();
+ QFile::remove(cacheFilePath);
+ }
+
QQmlEngine *engine;
const QTemporaryDir tempDir;
const QString testFilePath;
@@ -151,8 +192,6 @@ void tst_qmldiskcache::regenerateAfterChange()
QVERIFY(bindingFunction->codeOffset > testUnit->unitSize);
}
- engine.clearComponentCache();
-
{
const QByteArray newContents = QByteArrayLiteral("import QtQml 2.0\n"
"QtObject {\n"
@@ -214,6 +253,74 @@ void tst_qmldiskcache::registerImportForImplicitComponent()
}
}
+void tst_qmldiskcache::basicVersionChecks()
+{
+ QQmlEngine engine;
+
+ TestCompiler testCompiler(&engine);
+ QVERIFY(testCompiler.tempDir.isValid());
+
+ const QByteArray contents = QByteArrayLiteral("import QtQml 2.0\n"
+ "QtObject {\n"
+ " property string blah: Qt.platform;\n"
+ "}");
+
+ {
+ testCompiler.clearCache();
+ QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
+ QVERIFY2(testCompiler.verify(), qPrintable(testCompiler.lastErrorString));
+ }
+
+ {
+ testCompiler.clearCache();
+ QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
+
+ testCompiler.tweakHeader([](QV4::CompiledData::Unit *header) {
+ header->qtVersion = 0;
+ });
+
+ QVERIFY(!testCompiler.verify());
+ QCOMPARE(testCompiler.lastErrorString, QString::fromUtf8("Qt version mismatch. Found 0 expected %1").arg(QT_VERSION, 0, 16));
+ testCompiler.clearCache();
+ }
+
+ {
+ testCompiler.clearCache();
+ QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
+
+ testCompiler.tweakHeader([](QV4::CompiledData::Unit *header) {
+ header->version = 0;
+ });
+
+ QVERIFY(!testCompiler.verify());
+ QCOMPARE(testCompiler.lastErrorString, QString::fromUtf8("V4 data structure version mismatch. Found 0 expected %1").arg(QV4_DATA_STRUCTURE_VERSION, 0, 16));
+ }
+
+ {
+ testCompiler.clearCache();
+ QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
+
+ testCompiler.tweakHeader([](QV4::CompiledData::Unit *header) {
+ header->architectureIndex = 0;
+ });
+
+ QVERIFY(!testCompiler.verify());
+ QCOMPARE(testCompiler.lastErrorString, QString::fromUtf8("Architecture mismatch. Found expected %1").arg(QSysInfo::buildAbi()));
+ }
+
+ {
+ testCompiler.clearCache();
+ QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
+
+ testCompiler.tweakHeader([](QV4::CompiledData::Unit *header) {
+ header->codeGeneratorIndex = 0;
+ });
+
+ QVERIFY(!testCompiler.verify());
+ QCOMPARE(testCompiler.lastErrorString, QString::fromUtf8("Code generator mismatch. Found code generated by but expected %1").arg(QV8Engine::getV4(&engine)->iselFactory->codeGeneratorName));
+ }
+}
+
QTEST_MAIN(tst_qmldiskcache)
#include "tst_qmldiskcache.moc"
diff --git a/tests/auto/qml/qqmlecmascript/data/qtbug_54589.qml b/tests/auto/qml/qqmlecmascript/data/qtbug_54589.qml
new file mode 100644
index 0000000000..8f7d5f2a70
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/qtbug_54589.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+
+QtObject {
+ function checkPropertyDeletion() {
+ var o = {
+ x: 1,
+ y: 2
+ };
+ o.z = 3
+ delete o.y;
+
+ return (o.x === 1 && o.y === undefined && o.z === 3)
+ }
+
+ property bool result: checkPropertyDeletion()
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 07b5e55384..de3ead917f 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -324,6 +324,8 @@ private slots:
void switchExpression();
void qtbug_46022();
void qtbug_52340();
+ void qtbug_54589();
+ void qtbug_54687();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -7965,6 +7967,22 @@ void tst_qqmlecmascript::qtbug_52340()
QVERIFY(returnValue.toBool());
}
+void tst_qqmlecmascript::qtbug_54589()
+{
+ QQmlComponent component(&engine, testFileUrl("qtbug_54589.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->property("result").toBool(), true);
+}
+
+void tst_qqmlecmascript::qtbug_54687()
+{
+ QJSEngine e;
+ // it's simple: this shouldn't crash.
+ engine.evaluate("12\n----12");
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"
diff --git a/tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml b/tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml
index c91cf581b3..52027232db 100644
--- a/tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml
+++ b/tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml
@@ -26,7 +26,9 @@ MyTypeObject {
boolProperty: true
variantProperty: "Hello World!"
vectorProperty: "10,1,2.2"
+ vector2Property: "2, 3"
vector4Property: "10,1,2.2,2.3"
+ quaternionProperty: "4,5,6,7"
urlProperty: "main.qml?with%3cencoded%3edata"
objectProperty: MyTypeObject { intProperty: 8 }
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index f41f13c561..af7dc155d0 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -33,8 +33,10 @@
#include <QtCore/qdatetime.h>
#include <QtGui/qmatrix.h>
#include <QtGui/qcolor.h>
+#include <QtGui/qvector2d.h>
#include <QtGui/qvector3d.h>
#include <QtGui/qvector4d.h>
+#include <QtGui/qquaternion.h>
#include <QtQml/qqml.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlparserstatus.h>
@@ -241,8 +243,10 @@ class MyTypeObject : public QObject
Q_PROPERTY(QRectF rectFProperty READ rectFProperty WRITE setRectFProperty NOTIFY rectFPropertyChanged)
Q_PROPERTY(bool boolProperty READ boolProperty WRITE setBoolProperty NOTIFY boolPropertyChanged)
Q_PROPERTY(QVariant variantProperty READ variantProperty WRITE setVariantProperty NOTIFY variantPropertyChanged)
+ Q_PROPERTY(QVector2D vector2Property READ vector2Property WRITE setVector2Property NOTIFY vector2PropertyChanged)
Q_PROPERTY(QVector3D vectorProperty READ vectorProperty WRITE setVectorProperty NOTIFY vectorPropertyChanged)
Q_PROPERTY(QVector4D vector4Property READ vector4Property WRITE setVector4Property NOTIFY vector4PropertyChanged)
+ Q_PROPERTY(QQuaternion quaternionProperty READ quaternionProperty WRITE setQuaternionProperty NOTIFY quaternionPropertyChanged)
Q_PROPERTY(QUrl urlProperty READ urlProperty WRITE setUrlProperty NOTIFY urlPropertyChanged)
Q_PROPERTY(QQmlScriptString scriptProperty READ scriptProperty WRITE setScriptProperty)
@@ -523,6 +527,15 @@ public:
emit vectorPropertyChanged();
}
+ QVector2D vector2PropertyValue;
+ QVector2D vector2Property() const {
+ return vector2PropertyValue;
+ }
+ void setVector2Property(const QVector2D &v) {
+ vector2PropertyValue = v;
+ emit vector2PropertyChanged();
+ }
+
QVector4D vector4PropertyValue;
QVector4D vector4Property() const {
return vector4PropertyValue;
@@ -532,6 +545,15 @@ public:
emit vector4PropertyChanged();
}
+ QQuaternion quaternionPropertyValue;
+ QQuaternion quaternionProperty() const {
+ return quaternionPropertyValue;
+ }
+ void setQuaternionProperty(const QQuaternion &v) {
+ quaternionPropertyValue = v;
+ emit quaternionPropertyChanged();
+ }
+
QUrl urlPropertyValue;
QUrl urlProperty() const {
return urlPropertyValue;
@@ -585,7 +607,9 @@ signals:
void boolPropertyChanged();
void variantPropertyChanged();
void vectorPropertyChanged();
+ void vector2PropertyChanged();
void vector4PropertyChanged();
+ void quaternionPropertyChanged();
void urlPropertyChanged();
};
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 1df7c4157e..1a035be5e0 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -682,6 +682,7 @@ void tst_qqmllanguage::assignBasicTypes()
QCOMPARE(object->boolProperty(), true);
QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2f));
+ QCOMPARE(object->vector2Property(), QVector2D(2, 3));
QCOMPARE(object->vector4Property(), QVector4D(10, 1, 2.2f, 2.3f));
const QUrl encoded = QUrl::fromEncoded("main.qml?with%3cencoded%3edata", QUrl::TolerantMode);
QCOMPARE(object->urlProperty(), component.url().resolved(encoded));
diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
index 7e00147963..63d7f1c12b 100644
--- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
+++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
@@ -2078,15 +2078,15 @@ void tst_qqmlproperty::floatToStringPrecision()
QFETCH(QString, qtString);
QFETCH(QString, jsString);
- const char *name = propertyName.toLatin1().constData();
+ QByteArray name = propertyName.toLatin1();
QCOMPARE(obj->property(name).toDouble(), number);
QCOMPARE(obj->property(name).toString(), qtString);
- const char *name1 = (propertyName + QLatin1Char('1')).toLatin1().constData();
+ QByteArray name1 = (propertyName + QLatin1Char('1')).toLatin1();
QCOMPARE(obj->property(name1).toDouble(), number);
QCOMPARE(obj->property(name1).toString(), qtString);
- const char *name2 = (propertyName + QLatin1Char('2')).toLatin1().constData();
+ QByteArray name2 = (propertyName + QLatin1Char('2')).toLatin1();
QCOMPARE(obj->property(name2).toDouble(), number);
QCOMPARE(obj->property(name2).toString(), jsString);
diff --git a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
index 5f15afff85..2916d8455c 100644
--- a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
+++ b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
@@ -30,6 +30,8 @@
#include <private/qqmlpropertycache_p.h>
#include <QtQml/qqmlengine.h>
#include <private/qv8engine_p.h>
+#include <private/qmetaobjectbuilder_p.h>
+#include <QCryptographicHash>
#include "../../shared/util.h"
class tst_qqmlpropertycache : public QObject
@@ -45,6 +47,9 @@ private slots:
void methodsDerived();
void signalHandlers();
void signalHandlersDerived();
+ void metaObjectSize_data();
+ void metaObjectSize();
+ void metaObjectChecksum();
private:
QQmlEngine engine;
@@ -105,16 +110,16 @@ void tst_qqmlpropertycache::properties()
QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(v4, metaObject));
QQmlPropertyData *data;
- QVERIFY(data = cacheProperty(cache, "propertyA"));
+ QVERIFY((data = cacheProperty(cache, "propertyA")));
QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyA"));
- QVERIFY(data = cacheProperty(cache, "propertyB"));
+ QVERIFY((data = cacheProperty(cache, "propertyB")));
QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyB"));
- QVERIFY(data = cacheProperty(cache, "propertyC"));
+ QVERIFY((data = cacheProperty(cache, "propertyC")));
QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyC"));
- QVERIFY(data = cacheProperty(cache, "propertyD"));
+ QVERIFY((data = cacheProperty(cache, "propertyD")));
QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyD"));
}
@@ -129,16 +134,16 @@ void tst_qqmlpropertycache::propertiesDerived()
QQmlRefPointer<QQmlPropertyCache> cache(parentCache->copyAndAppend(object.metaObject()));
QQmlPropertyData *data;
- QVERIFY(data = cacheProperty(cache, "propertyA"));
+ QVERIFY((data = cacheProperty(cache, "propertyA")));
QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyA"));
- QVERIFY(data = cacheProperty(cache, "propertyB"));
+ QVERIFY((data = cacheProperty(cache, "propertyB")));
QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyB"));
- QVERIFY(data = cacheProperty(cache, "propertyC"));
+ QVERIFY((data = cacheProperty(cache, "propertyC")));
QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyC"));
- QVERIFY(data = cacheProperty(cache, "propertyD"));
+ QVERIFY((data = cacheProperty(cache, "propertyD")));
QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyD"));
}
@@ -152,28 +157,28 @@ void tst_qqmlpropertycache::methods()
QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(v4, metaObject));
QQmlPropertyData *data;
- QVERIFY(data = cacheProperty(cache, "slotA"));
+ QVERIFY((data = cacheProperty(cache, "slotA")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("slotA()"));
- QVERIFY(data = cacheProperty(cache, "slotB"));
+ QVERIFY((data = cacheProperty(cache, "slotB")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("slotB()"));
- QVERIFY(data = cacheProperty(cache, "signalA"));
+ QVERIFY((data = cacheProperty(cache, "signalA")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalA()"));
- QVERIFY(data = cacheProperty(cache, "signalB"));
+ QVERIFY((data = cacheProperty(cache, "signalB")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalB()"));
- QVERIFY(data = cacheProperty(cache, "propertyAChanged"));
+ QVERIFY((data = cacheProperty(cache, "propertyAChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyAChanged()"));
- QVERIFY(data = cacheProperty(cache, "propertyBChanged"));
+ QVERIFY((data = cacheProperty(cache, "propertyBChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyBChanged()"));
- QVERIFY(data = cacheProperty(cache, "propertyCChanged"));
+ QVERIFY((data = cacheProperty(cache, "propertyCChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyCChanged()"));
- QVERIFY(data = cacheProperty(cache, "propertyDChanged"));
+ QVERIFY((data = cacheProperty(cache, "propertyDChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyDChanged()"));
}
@@ -188,28 +193,28 @@ void tst_qqmlpropertycache::methodsDerived()
QQmlRefPointer<QQmlPropertyCache> cache(parentCache->copyAndAppend(object.metaObject()));
QQmlPropertyData *data;
- QVERIFY(data = cacheProperty(cache, "slotA"));
+ QVERIFY((data = cacheProperty(cache, "slotA")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("slotA()"));
- QVERIFY(data = cacheProperty(cache, "slotB"));
+ QVERIFY((data = cacheProperty(cache, "slotB")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("slotB()"));
- QVERIFY(data = cacheProperty(cache, "signalA"));
+ QVERIFY((data = cacheProperty(cache, "signalA")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalA()"));
- QVERIFY(data = cacheProperty(cache, "signalB"));
+ QVERIFY((data = cacheProperty(cache, "signalB")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalB()"));
- QVERIFY(data = cacheProperty(cache, "propertyAChanged"));
+ QVERIFY((data = cacheProperty(cache, "propertyAChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyAChanged()"));
- QVERIFY(data = cacheProperty(cache, "propertyBChanged"));
+ QVERIFY((data = cacheProperty(cache, "propertyBChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyBChanged()"));
- QVERIFY(data = cacheProperty(cache, "propertyCChanged"));
+ QVERIFY((data = cacheProperty(cache, "propertyCChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyCChanged()"));
- QVERIFY(data = cacheProperty(cache, "propertyDChanged"));
+ QVERIFY((data = cacheProperty(cache, "propertyDChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyDChanged()"));
}
@@ -223,22 +228,22 @@ void tst_qqmlpropertycache::signalHandlers()
QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(v4, metaObject));
QQmlPropertyData *data;
- QVERIFY(data = cacheProperty(cache, "onSignalA"));
+ QVERIFY((data = cacheProperty(cache, "onSignalA")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalA()"));
- QVERIFY(data = cacheProperty(cache, "onSignalB"));
+ QVERIFY((data = cacheProperty(cache, "onSignalB")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalB()"));
- QVERIFY(data = cacheProperty(cache, "onPropertyAChanged"));
+ QVERIFY((data = cacheProperty(cache, "onPropertyAChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyAChanged()"));
- QVERIFY(data = cacheProperty(cache, "onPropertyBChanged"));
+ QVERIFY((data = cacheProperty(cache, "onPropertyBChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyBChanged()"));
- QVERIFY(data = cacheProperty(cache, "onPropertyCChanged"));
+ QVERIFY((data = cacheProperty(cache, "onPropertyCChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyCChanged()"));
- QVERIFY(data = cacheProperty(cache, "onPropertyDChanged"));
+ QVERIFY((data = cacheProperty(cache, "onPropertyDChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyDChanged()"));
}
@@ -253,25 +258,145 @@ void tst_qqmlpropertycache::signalHandlersDerived()
QQmlRefPointer<QQmlPropertyCache> cache(parentCache->copyAndAppend(object.metaObject()));
QQmlPropertyData *data;
- QVERIFY(data = cacheProperty(cache, "onSignalA"));
+ QVERIFY((data = cacheProperty(cache, "onSignalA")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalA()"));
- QVERIFY(data = cacheProperty(cache, "onSignalB"));
+ QVERIFY((data = cacheProperty(cache, "onSignalB")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalB()"));
- QVERIFY(data = cacheProperty(cache, "onPropertyAChanged"));
+ QVERIFY((data = cacheProperty(cache, "onPropertyAChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyAChanged()"));
- QVERIFY(data = cacheProperty(cache, "onPropertyBChanged"));
+ QVERIFY((data = cacheProperty(cache, "onPropertyBChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyBChanged()"));
- QVERIFY(data = cacheProperty(cache, "onPropertyCChanged"));
+ QVERIFY((data = cacheProperty(cache, "onPropertyCChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyCChanged()"));
- QVERIFY(data = cacheProperty(cache, "onPropertyDChanged"));
+ QVERIFY((data = cacheProperty(cache, "onPropertyDChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyDChanged()"));
}
-QTEST_MAIN(tst_qqmlpropertycache)
+class TestClass : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int prop READ prop WRITE setProp NOTIFY propChanged)
+ int m_prop;
+
+public:
+ enum MyEnum {
+ First, Second
+ };
+ Q_ENUM(MyEnum)
+
+ Q_CLASSINFO("Foo", "Bar")
+
+ TestClass() {}
+
+ int prop() const
+ {
+ return m_prop;
+ }
+
+public slots:
+ void setProp(int prop)
+ {
+ if (m_prop == prop)
+ return;
+
+ m_prop = prop;
+ emit propChanged(prop);
+ }
+signals:
+ void propChanged(int prop);
+};
+
+class TestClassWithParameters : public QObject
+{
+ Q_OBJECT
+
+public:
+ Q_INVOKABLE void slotWithArguments(int firstArg) {
+ Q_UNUSED(firstArg);
+ }
+};
+
+class TestClassWithClassInfo : public QObject
+{
+ Q_OBJECT
+ Q_CLASSINFO("Key", "Value")
+};
#include "tst_qqmlpropertycache.moc"
+
+#define ARRAY_SIZE(arr) \
+ int(sizeof(arr) / sizeof(arr[0]))
+
+#define TEST_CLASS(Class) \
+ QTest::newRow(#Class) << &Class::staticMetaObject << ARRAY_SIZE(qt_meta_data_##Class) << ARRAY_SIZE(qt_meta_stringdata_##Class.data)
+
+Q_DECLARE_METATYPE(const QMetaObject*);
+
+void tst_qqmlpropertycache::metaObjectSize_data()
+{
+ QTest::addColumn<const QMetaObject*>("metaObject");
+ QTest::addColumn<int>("expectedFieldCount");
+ QTest::addColumn<int>("expectedStringCount");
+
+ TEST_CLASS(TestClass);
+ TEST_CLASS(TestClassWithParameters);
+ TEST_CLASS(TestClassWithClassInfo);
+}
+
+void tst_qqmlpropertycache::metaObjectSize()
+{
+ QFETCH(const QMetaObject *, metaObject);
+ QFETCH(int, expectedFieldCount);
+ QFETCH(int, expectedStringCount);
+
+ int size = 0;
+ int stringDataSize = 0;
+ bool valid = QQmlPropertyCache::determineMetaObjectSizes(*metaObject, &size, &stringDataSize);
+ QVERIFY(valid);
+
+ QCOMPARE(size, expectedFieldCount - 1); // Remove trailing zero field until fixed in moc.
+ QCOMPARE(stringDataSize, expectedStringCount);
+}
+
+void tst_qqmlpropertycache::metaObjectChecksum()
+{
+ QMetaObjectBuilder builder;
+ builder.setClassName("Test");
+ builder.addClassInfo("foo", "bar");
+
+ QCryptographicHash hash(QCryptographicHash::Md5);
+
+ QScopedPointer<QMetaObject, QScopedPointerPodDeleter> mo(builder.toMetaObject());
+ QVERIFY(!mo.isNull());
+
+ QVERIFY(QQmlPropertyCache::addToHash(hash, *mo.data()));
+ QByteArray initialHash = hash.result();
+ QVERIFY(!initialHash.isEmpty());
+ hash.reset();
+
+ {
+ QVERIFY(QQmlPropertyCache::addToHash(hash, *mo.data()));
+ QByteArray nextHash = hash.result();
+ QVERIFY(!nextHash.isEmpty());
+ hash.reset();
+ QCOMPARE(initialHash, nextHash);
+ }
+
+ builder.addProperty("testProperty", "int", -1);
+
+ mo.reset(builder.toMetaObject());
+ {
+ QVERIFY(QQmlPropertyCache::addToHash(hash, *mo.data()));
+ QByteArray nextHash = hash.result();
+ QVERIFY(!nextHash.isEmpty());
+ hash.reset();
+ QVERIFY(initialHash != nextHash);
+ }
+}
+
+QTEST_MAIN(tst_qqmlpropertycache)
diff --git a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
index e0c2324dc6..b8ea98df2b 100644
--- a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
+++ b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
@@ -60,6 +60,7 @@ private slots:
void QTBUG_35233();
void disallowExtending();
void QTBUG_35906();
+ void QTBUG_48136();
};
class LazyPropertyMap : public QQmlPropertyMap, public QQmlParserStatus
@@ -462,6 +463,40 @@ void tst_QQmlPropertyMap::QTBUG_35906()
QCOMPARE(value.toInt(), 42);
}
+void tst_QQmlPropertyMap::QTBUG_48136()
+{
+ static const char key[] = "mykey";
+ QQmlPropertyMap map;
+
+ //
+ // Test that the notify signal is emitted correctly
+ //
+
+ const int propIndex = map.metaObject()->indexOfProperty(key);
+ const QMetaProperty prop = map.metaObject()->property(propIndex);
+ QSignalSpy notifySpy(&map, QByteArray::number(QSIGNAL_CODE) + prop.notifySignal().methodSignature());
+
+ map.insert(key, 42);
+ QCOMPARE(notifySpy.count(), 1);
+ map.insert(key, 43);
+ QCOMPARE(notifySpy.count(), 2);
+ map.insert(key, 43);
+ QCOMPARE(notifySpy.count(), 2);
+ map.insert(key, 44);
+ QCOMPARE(notifySpy.count(), 3);
+
+ //
+ // Test that the valueChanged signal is emitted correctly
+ //
+ QSignalSpy valueChangedSpy(&map, &QQmlPropertyMap::valueChanged);
+ map.setProperty(key, 44);
+ QCOMPARE(valueChangedSpy.count(), 0);
+ map.setProperty(key, 45);
+ QCOMPARE(valueChangedSpy.count(), 1);
+ map.setProperty(key, 45);
+ QCOMPARE(valueChangedSpy.count(), 1);
+}
+
QTEST_MAIN(tst_QQmlPropertyMap)
#include "tst_qqmlpropertymap.moc"
diff --git a/tests/auto/qml/qqmlvaluetypes/data/color_read.qml b/tests/auto/qml/qqmlvaluetypes/data/color_read.qml
index bc92b1e5f9..73d2b921a7 100644
--- a/tests/auto/qml/qqmlvaluetypes/data/color_read.qml
+++ b/tests/auto/qml/qqmlvaluetypes/data/color_read.qml
@@ -5,5 +5,11 @@ MyTypeObject {
property real v_g: color.g
property real v_b: color.b
property real v_a: color.a
+ property real hsv_h: color.hsvHue
+ property real hsv_s: color.hsvSaturation
+ property real hsv_v: color.hsvValue
+ property real hsl_h: color.hslHue
+ property real hsl_s: color.hslSaturation
+ property real hsl_l: color.hslLightness
property variant copy: color
}
diff --git a/tests/auto/qml/qqmlvaluetypes/data/color_write_HSL.qml b/tests/auto/qml/qqmlvaluetypes/data/color_write_HSL.qml
new file mode 100644
index 0000000000..0034163bbe
--- /dev/null
+++ b/tests/auto/qml/qqmlvaluetypes/data/color_write_HSL.qml
@@ -0,0 +1,8 @@
+import Test 1.0
+
+MyTypeObject {
+ color.hslHue: if (true) 0.43
+ color.hslSaturation: if (true) 0.74
+ color.hslLightness: if (true) 0.54
+ color.a: if (true) 0.7
+}
diff --git a/tests/auto/qml/qqmlvaluetypes/data/color_write_HSV.qml b/tests/auto/qml/qqmlvaluetypes/data/color_write_HSV.qml
new file mode 100644
index 0000000000..1fc47d460e
--- /dev/null
+++ b/tests/auto/qml/qqmlvaluetypes/data/color_write_HSV.qml
@@ -0,0 +1,8 @@
+import Test 1.0
+
+MyTypeObject {
+ color.hsvHue: if (true) 0.43
+ color.hsvSaturation: if (true) 0.77
+ color.hsvValue: if (true) 0.88
+ color.a: if (true) 0.7
+}
diff --git a/tests/auto/qml/qqmlvaluetypes/testtypes.h b/tests/auto/qml/qqmlvaluetypes/testtypes.h
index 77d723fbd4..bcfe4028c6 100644
--- a/tests/auto/qml/qqmlvaluetypes/testtypes.h
+++ b/tests/auto/qml/qqmlvaluetypes/testtypes.h
@@ -194,7 +194,7 @@ class MyOffsetValueInterceptor : public QObject, public QQmlPropertyValueInterce
Q_INTERFACES(QQmlPropertyValueInterceptor)
public:
virtual void setTarget(const QQmlProperty &p) { prop = p; }
- virtual void write(const QVariant &value) { QQmlPropertyPrivate::write(prop, value.toInt() + 13, QQmlPropertyPrivate::BypassInterceptor); }
+ virtual void write(const QVariant &value) { QQmlPropertyPrivate::write(prop, value.toInt() + 13, QQmlPropertyData::BypassInterceptor); }
private:
QQmlProperty prop;
@@ -215,7 +215,7 @@ public:
c.getRgb(&r, &g, &b, &a);
c.setRgb(a, b, g, r);
- QQmlPropertyPrivate::write(prop, c, QQmlPropertyPrivate::BypassInterceptor);
+ QQmlPropertyPrivate::write(prop, c, QQmlPropertyData::BypassInterceptor);
}
private:
@@ -230,7 +230,7 @@ public:
virtual void setTarget(const QQmlProperty &p) { prop = p; }
virtual void write(const QVariant &)
{
- QQmlPropertyPrivate::write(prop, 0.0f, QQmlPropertyPrivate::BypassInterceptor);
+ QQmlPropertyPrivate::write(prop, 0.0f, QQmlPropertyData::BypassInterceptor);
}
private:
diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
index f506d0f53a..803bad197a 100644
--- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
@@ -907,6 +907,15 @@ void tst_qqmlvaluetypes::color()
QCOMPARE((float)object->property("v_g").toDouble(), (float)0.88);
QCOMPARE((float)object->property("v_b").toDouble(), (float)0.6);
QCOMPARE((float)object->property("v_a").toDouble(), (float)0.34);
+
+ QCOMPARE(qRound(object->property("hsv_h").toDouble() * 100), 43);
+ QCOMPARE(qRound(object->property("hsv_s").toDouble() * 100), 77);
+ QCOMPARE(qRound(object->property("hsv_v").toDouble() * 100), 88);
+
+ QCOMPARE(qRound(object->property("hsl_h").toDouble() * 100), 43);
+ QCOMPARE(qRound(object->property("hsl_s").toDouble() * 100), 74);
+ QCOMPARE(qRound(object->property("hsl_l").toDouble() * 100), 54);
+
QColor comparison;
comparison.setRedF(0.2);
comparison.setGreenF(0.88);
@@ -933,6 +942,30 @@ void tst_qqmlvaluetypes::color()
}
{
+ QQmlComponent component(&engine, testFileUrl("color_write_HSV.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QColor newColor;
+ newColor.setHsvF(0.43, 0.77, 0.88, 0.7);
+ QCOMPARE(object->color(), newColor);
+
+ delete object;
+ }
+
+ {
+ QQmlComponent component(&engine, testFileUrl("color_write_HSL.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QColor newColor;
+ newColor.setHslF(0.43, 0.74, 0.54, 0.7);
+ QCOMPARE(object->color(), newColor);
+
+ delete object;
+ }
+
+ {
QQmlComponent component(&engine, testFileUrl("color_compare.qml"));
MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
QVERIFY(object != 0);
diff --git a/tests/auto/quick/qquickflickable/data/ratios_smallContent.qml b/tests/auto/quick/qquickflickable/data/ratios_smallContent.qml
new file mode 100644
index 0000000000..07bad683ee
--- /dev/null
+++ b/tests/auto/quick/qquickflickable/data/ratios_smallContent.qml
@@ -0,0 +1,19 @@
+import QtQuick 2.0
+
+Flickable {
+ property double heightRatioIs: visibleArea.heightRatio
+ property double widthRatioIs: visibleArea.widthRatio
+
+ width: 200
+ height: 200
+ contentWidth: item.width
+ contentHeight: item.height
+ topMargin: 20
+ leftMargin: 40
+
+ Item {
+ id: item
+ width: 100
+ height: 100
+ }
+}
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index 2742f5c1e2..e1678b9acd 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -90,6 +90,7 @@ private slots:
void movementFromProgrammaticFlick();
void cleanup();
void contentSize();
+ void ratios_smallContent();
private:
void flickWithTouch(QQuickWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to);
@@ -1814,6 +1815,33 @@ void tst_qquickflickable::contentSize()
QCOMPARE(chspy.count(), 1);
}
+// QTBUG-53726
+void tst_qquickflickable::ratios_smallContent()
+{
+ QScopedPointer<QQuickView> window(new QQuickView);
+ window->setSource(testFileUrl("ratios_smallContent.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickViewTestUtil::centerOnScreen(window.data());
+ QQuickViewTestUtil::moveMouseAway(window.data());
+ window->setTitle(QTest::currentTestFunction());
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QQuickItem *root = window->rootObject();
+ QVERIFY(root);
+ QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(root);
+ QVERIFY(obj != 0);
+
+ //doublecheck the item, as specified by contentWidth/Height, fits in the view
+ //use tryCompare to allow a bit of stabilization in component's properties
+ QTRY_COMPARE(obj->leftMargin() + obj->contentWidth() + obj->rightMargin() <= obj->width(), true);
+ QTRY_COMPARE(obj->topMargin() + obj->contentHeight() + obj->bottomMargin() <= obj->height(), true);
+
+ //the whole item fits in the flickable, heightRatio should be 1
+ QCOMPARE(obj->property("heightRatioIs").toDouble(), 1.);
+ QCOMPARE(obj->property("widthRatioIs").toDouble(), 1.);
+}
+
+
QTEST_MAIN(tst_qquickflickable)
#include "tst_qquickflickable.moc"
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
index 4b2c86697e..9fedfb21ab 100644
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
@@ -169,6 +169,8 @@ private slots:
void childAt();
+ void ignoreButtonPressNotInAcceptedMouseButtons();
+
private:
enum PaintOrderOp {
@@ -2009,6 +2011,28 @@ void tst_qquickitem::childAt()
QVERIFY(!root->childAt(19,19));
}
+void tst_qquickitem::ignoreButtonPressNotInAcceptedMouseButtons()
+{
+ // Verify the fix for QTBUG-31861
+ TestItem item;
+ QCOMPARE(item.acceptedMouseButtons(), Qt::MouseButtons(Qt::NoButton));
+
+ QQuickWindow window;
+ item.setSize(QSizeF(200,100));
+ item.setParentItem(window.contentItem());
+
+ item.setAcceptedMouseButtons(Qt::LeftButton);
+ QCOMPARE(item.acceptedMouseButtons(), Qt::MouseButtons(Qt::LeftButton));
+
+ QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(50, 50));
+ QTest::mousePress(&window, Qt::RightButton, 0, QPoint(50, 50)); // ignored because it's not LeftButton
+ QTest::mouseRelease(&window, Qt::RightButton, 0, QPoint(50, 50)); // ignored because it didn't grab the RightButton press
+ QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(50, 50));
+
+ QCOMPARE(item.pressCount, 1);
+ QCOMPARE(item.releaseCount, 1);
+}
+
QTEST_MAIN(tst_qquickitem)
#include "tst_qquickitem.moc"
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index b83edec996..bf9df7850d 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -653,11 +653,9 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v
#endif
QList<FxViewItem *> visibleItems = QQuickItemViewPrivate::get(listview)->visibleItems;
- for (QList<FxViewItem *>::const_iterator itemIt = visibleItems.begin(); itemIt != visibleItems.end(); ++itemIt)
- {
+ for (QList<FxViewItem *>::const_iterator itemIt = visibleItems.begin(); itemIt != visibleItems.end(); ++itemIt) {
FxViewItem *item = *itemIt;
- if (item->item->position().y() >= 0 && item->item->position().y() < listview->height())
- {
+ if (item->item->position().y() >= 0 && item->item->position().y() < listview->height()) {
QVERIFY(!QQuickItemPrivate::get(item->item)->culled);
}
}
diff --git a/tests/auto/quick/qquickshadereffect/data/MyIcon.qml b/tests/auto/quick/qquickshadereffect/data/MyIcon.qml
new file mode 100644
index 0000000000..b83da321f2
--- /dev/null
+++ b/tests/auto/quick/qquickshadereffect/data/MyIcon.qml
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.4
+
+Item {
+ id: root
+
+ property alias source: image.source
+ property bool shaderActive: false
+
+ implicitWidth: image.width
+
+ Image {
+ id: image
+ objectName: "image"
+ anchors { top: parent.top; bottom: parent.bottom }
+ sourceSize.height: height
+
+ visible: !shaderActive
+ }
+
+ ShaderEffect {
+ id: colorizedImage
+
+ anchors.fill: parent
+ visible: shaderActive && image.status == Image.Ready
+ supportsAtlasTextures: true
+
+ property Image source: visible ? image : null
+
+ fragmentShader: "
+ varying highp vec2 qt_TexCoord0;
+ uniform sampler2D source;
+ void main() {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ }"
+ }
+}
diff --git a/tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml b/tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml
new file mode 100644
index 0000000000..d1292f74b8
--- /dev/null
+++ b/tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.4
+
+Item {
+ width: 400
+ height: 700
+
+ MyIcon {
+ id: icon
+
+ height: 24
+ source: "star.png"
+ shaderActive: true
+ }
+
+ MyIcon {
+ anchors.top: icon.bottom
+
+ height: 24
+ source: "star.png"
+ }
+}
diff --git a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
index 54b64fdee9..fe33dbd4d8 100644
--- a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
+++ b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
@@ -77,6 +77,7 @@ private slots:
void deleteSourceItem();
void deleteShaderEffectSource();
+ void twoImagesOneShaderEffect();
private:
enum PresenceFlags {
@@ -306,6 +307,19 @@ void tst_qquickshadereffect::deleteShaderEffectSource()
delete view;
}
+void tst_qquickshadereffect::twoImagesOneShaderEffect()
+{
+ // purely to ensure that deleting the sourceItem of a shader doesn't cause a crash
+ QQuickView *view = new QQuickView(0);
+ view->setSource(QUrl::fromLocalFile(testFile("twoImagesOneShaderEffect.qml")));
+ view->show();
+ QVERIFY(QTest::qWaitForWindowExposed(view));
+ QVERIFY(view);
+ QObject *obj = view->rootObject();
+ QVERIFY(obj);
+ delete view;
+}
+
QTEST_MAIN(tst_qquickshadereffect)
#include "tst_qquickshadereffect.moc"
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index a9953b944c..acccac8eca 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -365,6 +365,7 @@ private slots:
void testRenderJob();
void testHoverChildMouseEventFilter();
+ void testHoverTimestamp();
void pointerEventTypeAndPointCount();
@@ -2398,6 +2399,90 @@ void tst_qquickwindow::testHoverChildMouseEventFilter()
QCOMPARE(middleItem->eventCount(QEvent::HoverEnter), 0);
}
+class HoverTimestampConsumer : public QQuickItem
+{
+ Q_OBJECT
+public:
+ HoverTimestampConsumer(QQuickItem *parent = 0)
+ : QQuickItem(parent)
+ {
+ setAcceptHoverEvents(true);
+ }
+
+ void hoverEnterEvent(QHoverEvent *event) { hoverTimestamps << event->timestamp(); }
+ void hoverLeaveEvent(QHoverEvent *event) { hoverTimestamps << event->timestamp(); }
+ void hoverMoveEvent(QHoverEvent *event) { hoverTimestamps << event->timestamp(); }
+
+ QList<ulong> hoverTimestamps;
+};
+
+// Checks that a QHoverEvent carries the timestamp of the QMouseEvent that caused it.
+// QTBUG-54600
+void tst_qquickwindow::testHoverTimestamp()
+{
+ QQuickWindow window;
+
+ window.resize(200, 200);
+ window.setPosition(100, 100);
+ window.setTitle(QTest::currentTestFunction());
+ window.show();
+ QVERIFY(QTest::qWaitForWindowActive(&window));
+
+ HoverTimestampConsumer *hoverConsumer = new HoverTimestampConsumer(window.contentItem());
+ hoverConsumer->setWidth(100);
+ hoverConsumer->setHeight(100);
+ hoverConsumer->setX(50);
+ hoverConsumer->setY(50);
+
+ // First position, outside
+ {
+ QMouseEvent mouseEvent(QEvent::MouseMove, QPointF(40, 40), QPointF(40, 40), QPointF(140, 140),
+ Qt::NoButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventNotSynthesized);
+ mouseEvent.setTimestamp(10);
+ QVERIFY(QCoreApplication::sendEvent(&window, &mouseEvent));
+ }
+
+ // Enter
+ {
+ QMouseEvent mouseEvent(QEvent::MouseMove, QPointF(50, 50), QPointF(50, 50), QPointF(150, 150),
+ Qt::NoButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventNotSynthesized);
+ mouseEvent.setTimestamp(20);
+ QVERIFY(QCoreApplication::sendEvent(&window, &mouseEvent));
+ }
+ QCOMPARE(hoverConsumer->hoverTimestamps.size(), 1);
+ QCOMPARE(hoverConsumer->hoverTimestamps.last(), 20UL);
+
+ // Move
+ {
+ QMouseEvent mouseEvent(QEvent::MouseMove, QPointF(60, 60), QPointF(60, 60), QPointF(160, 160),
+ Qt::NoButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventNotSynthesized);
+ mouseEvent.setTimestamp(30);
+ QVERIFY(QCoreApplication::sendEvent(&window, &mouseEvent));
+ }
+ QCOMPARE(hoverConsumer->hoverTimestamps.size(), 2);
+ QCOMPARE(hoverConsumer->hoverTimestamps.last(), 30UL);
+
+ // Move
+ {
+ QMouseEvent mouseEvent(QEvent::MouseMove, QPointF(100, 100), QPointF(100, 100), QPointF(200, 200),
+ Qt::NoButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventNotSynthesized);
+ mouseEvent.setTimestamp(40);
+ QVERIFY(QCoreApplication::sendEvent(&window, &mouseEvent));
+ }
+ QCOMPARE(hoverConsumer->hoverTimestamps.size(), 3);
+ QCOMPARE(hoverConsumer->hoverTimestamps.last(), 40UL);
+
+ // Leave
+ {
+ QMouseEvent mouseEvent(QEvent::MouseMove, QPointF(160, 160), QPointF(160, 160), QPointF(260, 260),
+ Qt::NoButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventNotSynthesized);
+ mouseEvent.setTimestamp(5);
+ QVERIFY(QCoreApplication::sendEvent(&window, &mouseEvent));
+ }
+ QCOMPARE(hoverConsumer->hoverTimestamps.size(), 4);
+ QCOMPARE(hoverConsumer->hoverTimestamps.last(), 5UL);
+}
+
void tst_qquickwindow::pointerEventTypeAndPointCount()
{
QPointF localPosition(33, 66);
diff --git a/tests/benchmarks/qml/qml.pro b/tests/benchmarks/qml/qml.pro
index d3ce69c713..5d48ec0067 100644
--- a/tests/benchmarks/qml/qml.pro
+++ b/tests/benchmarks/qml/qml.pro
@@ -5,6 +5,7 @@ SUBDIRS += \
compilation \
javascript \
holistic \
+ qqmlchangeset \
qqmlcomponent \
qqmlimage \
qqmlmetaproperty \
diff --git a/tests/benchmarks/qml/qqmlchangeset/qqmlchangeset.pro b/tests/benchmarks/qml/qqmlchangeset/qqmlchangeset.pro
new file mode 100644
index 0000000000..fc0ccdf8ed
--- /dev/null
+++ b/tests/benchmarks/qml/qqmlchangeset/qqmlchangeset.pro
@@ -0,0 +1,10 @@
+CONFIG += benchmark
+TEMPLATE = app
+TARGET = tst_qqmlchangeset
+QT += qml quick-private testlib
+osx:CONFIG -= app_bundle
+
+SOURCES += tst_qqmlchangeset.cpp
+
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+
diff --git a/tests/benchmarks/qml/qqmlchangeset/tst_qqmlchangeset.cpp b/tests/benchmarks/qml/qqmlchangeset/tst_qqmlchangeset.cpp
new file mode 100644
index 0000000000..bbfb52343c
--- /dev/null
+++ b/tests/benchmarks/qml/qqmlchangeset/tst_qqmlchangeset.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite 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 <qtest.h>
+
+#include <QDebug>
+
+#include <private/qqmlchangeset_p.h>
+
+class tst_qqmlchangeset : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void move();
+};
+
+void tst_qqmlchangeset::move()
+{
+ QBENCHMARK {
+ QQmlChangeSet set;
+ const int MAX_ROWS = 30000;
+ for (int i = 0; i < MAX_ROWS; ++i) {
+ set.move(i, MAX_ROWS - 1 - i, 1, i);
+ }
+ }
+}
+
+QTEST_MAIN(tst_qqmlchangeset)
+#include "tst_qqmlchangeset.moc"
diff --git a/tests/manual/scenegraph_lancelot/scenegrabber/main.cpp b/tests/manual/scenegraph_lancelot/scenegrabber/main.cpp
index a4b1a1be70..5098d51134 100644
--- a/tests/manual/scenegraph_lancelot/scenegrabber/main.cpp
+++ b/tests/manual/scenegraph_lancelot/scenegrabber/main.cpp
@@ -134,7 +134,7 @@ private:
};
-extern uint qt_qhash_seed;
+Q_CORE_EXPORT extern QBasicAtomicInt qt_qhash_seed;
int main(int argc, char *argv[])
{
diff --git a/tests/manual/v4/test262 b/tests/manual/v4/test262
-Subproject 0b5af3dcec772bb06b4d685a20b2859cda59d18
+Subproject 9741ac4655808ac46c127e3d1d8ba3d27ada618
diff --git a/tools/qml/qml.pro b/tools/qml/qml.pro
index fe90916980..5f05054d04 100644
--- a/tools/qml/qml.pro
+++ b/tools/qml/qml.pro
@@ -12,6 +12,6 @@ mac {
ICON = qml.icns
}
-DEFINES += QT_QML_DEBUG_NO_WARNING
+!contains(QT_CONFIG, no-qml-debug): DEFINES += QT_QML_DEBUG_NO_WARNING
load(qt_tool)
diff --git a/tools/qmlplugindump/qmlplugindump.pro b/tools/qmlplugindump/qmlplugindump.pro
index e45a7fad83..b38eea2554 100644
--- a/tools/qmlplugindump/qmlplugindump.pro
+++ b/tools/qmlplugindump/qmlplugindump.pro
@@ -17,7 +17,7 @@ macx {
# Prevent qmlplugindump from popping up in the dock when launched.
# We embed the Info.plist file, so the application doesn't need to
# be a bundle.
- QMAKE_LFLAGS += -sectcreate __TEXT __info_plist $$shell_quote($$PWD/Info.plist)
+ QMAKE_LFLAGS += -Wl,-sectcreate,__TEXT,__info_plist,$$shell_quote($$PWD/Info.plist)
CONFIG -= app_bundle
}
diff --git a/tools/qmlprofiler/commandlistener.h b/tools/qmlprofiler/commandlistener.h
index c10b199daa..2a994bf449 100644
--- a/tools/qmlprofiler/commandlistener.h
+++ b/tools/qmlprofiler/commandlistener.h
@@ -33,7 +33,7 @@
class CommandListener : public QObject {
Q_OBJECT
-public slots:
+public:
void readCommand();
signals:
diff --git a/tools/qmlprofiler/main.cpp b/tools/qmlprofiler/main.cpp
index d3e2beb83f..c7cb979ff8 100644
--- a/tools/qmlprofiler/main.cpp
+++ b/tools/qmlprofiler/main.cpp
@@ -39,8 +39,10 @@ int main(int argc, char *argv[])
QThread listenerThread;
CommandListener listener;
listener.moveToThread(&listenerThread);
- QObject::connect(&listener, SIGNAL(command(QString)), &app, SLOT(userCommand(QString)));
- QObject::connect(&app, SIGNAL(readyForCommand()), &listener, SLOT(readCommand()));
+ QObject::connect(&listener, &CommandListener::command,
+ &app, &QmlProfilerApplication::userCommand);
+ QObject::connect(&app, &QmlProfilerApplication::readyForCommand,
+ &listener, &CommandListener::readCommand);
listenerThread.start();
int exitValue = app.exec();
listenerThread.quit();
diff --git a/tools/qmlprofiler/qmlprofilerapplication.cpp b/tools/qmlprofiler/qmlprofilerapplication.cpp
index b04ff7e558..063e5e2961 100644
--- a/tools/qmlprofiler/qmlprofilerapplication.cpp
+++ b/tools/qmlprofiler/qmlprofilerapplication.cpp
@@ -87,17 +87,21 @@ QmlProfilerApplication::QmlProfilerApplication(int &argc, char **argv) :
m_connectionAttempts(0)
{
m_connectTimer.setInterval(1000);
- connect(&m_connectTimer, SIGNAL(timeout()), this, SLOT(tryToConnect()));
+ connect(&m_connectTimer, &QTimer::timeout, this, &QmlProfilerApplication::tryToConnect);
- connect(&m_connection, SIGNAL(connected()), this, SLOT(connected()));
+ connect(&m_connection, &QQmlDebugConnection::connected,
+ this, &QmlProfilerApplication::connected);
- connect(&m_qmlProfilerClient, SIGNAL(enabledChanged(bool)),
- this, SLOT(traceClientEnabledChanged(bool)));
- connect(&m_qmlProfilerClient, SIGNAL(recordingStarted()), this, SLOT(notifyTraceStarted()));
- connect(&m_qmlProfilerClient, SIGNAL(error(QString)), this, SLOT(logError(QString)));
+ connect(&m_qmlProfilerClient, &QmlProfilerClient::enabledChanged,
+ this, &QmlProfilerApplication::traceClientEnabledChanged);
+ connect(&m_qmlProfilerClient, &QmlProfilerClient::recordingStarted,
+ this, &QmlProfilerApplication::notifyTraceStarted);
+ connect(&m_qmlProfilerClient, &QmlProfilerClient::error,
+ this, &QmlProfilerApplication::logError);
- connect(&m_profilerData, SIGNAL(error(QString)), this, SLOT(logError(QString)));
- connect(&m_profilerData, SIGNAL(dataReady()), this, SLOT(traceFinished()));
+ connect(&m_profilerData, &QmlProfilerData::error, this, &QmlProfilerApplication::logError);
+ connect(&m_profilerData, &QmlProfilerData::dataReady,
+ this, &QmlProfilerApplication::traceFinished);
}
@@ -257,7 +261,7 @@ void QmlProfilerApplication::parseArguments()
int QmlProfilerApplication::exec()
{
- QTimer::singleShot(0, this, SLOT(run()));
+ QTimer::singleShot(0, this, &QmlProfilerApplication::run);
return QCoreApplication::exec();
}
@@ -460,9 +464,9 @@ void QmlProfilerApplication::run()
arguments << m_programArguments;
m_process->setProcessChannelMode(QProcess::MergedChannels);
- connect(m_process, SIGNAL(readyRead()), this, SLOT(processHasOutput()));
- connect(m_process, SIGNAL(finished(int,QProcess::ExitStatus)), this,
- SLOT(processFinished()));
+ connect(m_process, &QIODevice::readyRead, this, &QmlProfilerApplication::processHasOutput);
+ connect(m_process, static_cast<void(QProcess::*)(int)>(&QProcess::finished),
+ this, [this](int){ processFinished(); });
logStatus(QString("Starting '%1 %2' ...").arg(m_programPath,
arguments.join(QLatin1Char(' '))));
m_process->start(m_programPath, arguments);
diff --git a/tools/qmlprofiler/qmlprofilerapplication.h b/tools/qmlprofiler/qmlprofilerapplication.h
index 04f9d43c87..13f0f041f0 100644
--- a/tools/qmlprofiler/qmlprofilerapplication.h
+++ b/tools/qmlprofiler/qmlprofilerapplication.h
@@ -58,16 +58,14 @@ public:
void parseArguments();
int exec();
bool isInteractive() const;
-
-signals:
- void readyForCommand();
-
-public slots:
void userCommand(const QString &command);
void notifyTraceStarted();
void outputData();
-private slots:
+signals:
+ void readyForCommand();
+
+private:
void run();
void tryToConnect();
void connected();
@@ -81,7 +79,6 @@ private slots:
void logError(const QString &error);
void logStatus(const QString &status);
-private:
quint64 parseFeatures(const QStringList &featureList, const QString &values, bool exclude);
bool checkOutputFile(PendingRequest pending);
void flush();
diff --git a/tools/qmlprofiler/qmlprofilerdata.h b/tools/qmlprofiler/qmlprofilerdata.h
index 2570513d93..00ef037071 100644
--- a/tools/qmlprofiler/qmlprofilerdata.h
+++ b/tools/qmlprofiler/qmlprofilerdata.h
@@ -58,12 +58,6 @@ public:
bool isEmpty() const;
-signals:
- void error(QString);
- void stateChanged();
- void dataReady();
-
-public slots:
void clear();
void setTraceEndTime(qint64 time);
void setTraceStartTime(qint64 time);
@@ -83,6 +77,11 @@ public slots:
void complete();
bool save(const QString &filename);
+signals:
+ void error(QString);
+ void stateChanged();
+ void dataReady();
+
private:
void sortStartTimes();
void computeQmlTime();
diff --git a/tools/qmlscene/qmlscene.pro b/tools/qmlscene/qmlscene.pro
index 0411fd8e31..b1267612c5 100644
--- a/tools/qmlscene/qmlscene.pro
+++ b/tools/qmlscene/qmlscene.pro
@@ -4,6 +4,7 @@ CONFIG += no_import_scan
SOURCES += main.cpp
-DEFINES += QML_RUNTIME_TESTING QT_QML_DEBUG_NO_WARNING
+DEFINES += QML_RUNTIME_TESTING
+!contains(QT_CONFIG, no-qml-debug): DEFINES += QT_QML_DEBUG_NO_WARNING
load(qt_tool)