aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2015-04-22 15:04:42 +0200
committerLiang Qi <liang.qi@theqtcompany.com>2015-04-22 15:32:19 +0200
commit07782f48f4318a7261f1b0ddcd686b19ec812e36 (patch)
tree3fa2aa3a1170ad7ebaf5b1641cdce19a941ca480
parent50fcdfd705c2ad9560641986bf4152b017ee8bb6 (diff)
parentf15a90e5d10465e66698209a5d88f1e63ae336fa (diff)
Merge remote-tracking branch 'origin/5.5' into dev
Conflicts: src/qml/qml/qqmlbinding.cpp src/qml/jsruntime/qv4arraybuffer.cpp src/qml/jsruntime/qv4functionobject.cpp Change-Id: Ic752e9dfd69b282093651c9234c110a49762f06d
-rw-r--r--examples/quick/rendercontrol/cuberenderer.cpp4
-rw-r--r--examples/quick/rendercontrol/window_multithreaded.cpp10
-rw-r--r--examples/quick/shared/Slider.qml3
-rw-r--r--examples/quick/shared/quick_shared.qrc3
-rw-r--r--src/3rdparty/masm/assembler/MacroAssemblerMIPS.h6
-rw-r--r--src/3rdparty/masm/masm.pri15
-rw-r--r--src/imports/models/plugins.qmltypes540
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro2
-rw-r--r--src/plugins/qmltooling/shared/qpacketprotocol.cpp16
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp67
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h17
-rw-r--r--src/qml/compiler/qv4compileddata.cpp10
-rw-r--r--src/qml/compiler/qv4compileddata_p.h20
-rw-r--r--src/qml/debugger/qqmldebugservice.cpp2
-rw-r--r--src/qml/debugger/qqmlenginedebugservice.cpp4
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h8
-rw-r--r--src/qml/doc/snippets/code/src_script_qjsengine.cpp5
-rw-r--r--src/qml/jit/qv4assembler_p.h8
-rw-r--r--src/qml/jit/qv4binop.cpp4
-rw-r--r--src/qml/jit/qv4isel_masm.cpp15
-rw-r--r--src/qml/jsapi/qjsengine.cpp28
-rw-r--r--src/qml/jsapi/qjsvalue.cpp2
-rw-r--r--src/qml/jsruntime/qv4arraybuffer.cpp26
-rw-r--r--src/qml/jsruntime/qv4arraybuffer_p.h13
-rw-r--r--src/qml/jsruntime/qv4context.cpp2
-rw-r--r--src/qml/jsruntime/qv4engine.cpp14
-rw-r--r--src/qml/jsruntime/qv4engine_p.h1
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp1
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp37
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h8
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp2
-rw-r--r--src/qml/jsruntime/qv4value_p.h6
-rw-r--r--src/qml/qml/qqmlbinding.cpp29
-rw-r--r--src/qml/qml/qqmlcontext.cpp79
-rw-r--r--src/qml/qml/qqmlcontext_p.h22
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp12
-rw-r--r--src/qml/qml/qqmlcustomparser_p.h2
-rw-r--r--src/qml/qml/qqmlengine.cpp11
-rw-r--r--src/qml/qml/qqmlexpression.cpp4
-rw-r--r--src/qml/qml/qqmlimport.cpp2
-rw-r--r--src/qml/qml/qqmlinfo.cpp2
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp9
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h4
-rw-r--r--src/qml/qml/qqmlmetatype.cpp88
-rw-r--r--src/qml/qml/qqmlmetatype_p.h4
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp164
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h14
-rw-r--r--src/qml/qml/qqmlproperty.cpp6
-rw-r--r--src/qml/qml/qqmltypeloader.cpp4
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp3
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp12
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h5
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp101
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h10
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp13
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp2
-rw-r--r--src/quick/items/qquickdrag.cpp6
-rw-r--r--src/quick/items/qquickwindowmodule.cpp4
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp6
-rw-r--r--src/quick/scenegraph/qsgwindowsrenderloop.cpp8
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp4
-rw-r--r--src/quick/util/qquickpropertychanges.cpp4
-rw-r--r--src/quickwidgets/qquickwidget.cpp47
-rw-r--r--src/quickwidgets/qquickwidget_p.h3
-rw-r--r--tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro2
-rw-r--r--tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro2
-rw-r--r--tests/auto/qml/debugger/qqmldebugclient/qqmldebugclient.pro2
-rw-r--r--tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler.pro2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro2
-rw-r--r--tests/auto/qml/debugger/qqmldebugservice/qqmldebugservice.pro2
-rw-r--r--tests/auto/qml/debugger/qqmlenginecontrol/qqmlenginecontrol.pro2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/qqmlenginedebuginspectorintegrationtest.pro2
-rw-r--r--tests/auto/qml/debugger/qqmlinspector/qqmlinspector.pro2
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro2
-rw-r--r--tests/auto/quick/qquickapplication/tst_qquickapplication.cpp15
-rw-r--r--tests/manual/shortcuts/shortcuts.qml (renamed from tests/manual/shorcuts/shortcuts.qml)0
-rw-r--r--tests/manual/touch/flicktext.qml378
-rw-r--r--tests/manual/touch/main.cpp51
-rw-r--r--tests/manual/touch/main.qml57
-rw-r--r--tests/manual/touch/mpta-crosshairs.qml108
-rw-r--r--tests/manual/touch/qml.qrc7
-rw-r--r--tests/manual/touch/touch.pro7
-rw-r--r--tools/qmlplugindump/main.cpp241
-rw-r--r--tools/qmlprofiler/qpacketprotocol.cpp16
-rw-r--r--tools/qmlscene/main.cpp1
85 files changed, 2041 insertions, 443 deletions
diff --git a/examples/quick/rendercontrol/cuberenderer.cpp b/examples/quick/rendercontrol/cuberenderer.cpp
index be503e3d8f..1b2d7dec8f 100644
--- a/examples/quick/rendercontrol/cuberenderer.cpp
+++ b/examples/quick/rendercontrol/cuberenderer.cpp
@@ -52,7 +52,9 @@ CubeRenderer::CubeRenderer(QOffscreenSurface *offscreenSurface)
: m_offscreenSurface(offscreenSurface),
m_context(0),
m_program(0),
- m_vbo(0)
+ m_vbo(0),
+ m_vao(0),
+ m_matrixLoc(0)
{
}
diff --git a/examples/quick/rendercontrol/window_multithreaded.cpp b/examples/quick/rendercontrol/window_multithreaded.cpp
index 6c0de93a19..9b6020a347 100644
--- a/examples/quick/rendercontrol/window_multithreaded.cpp
+++ b/examples/quick/rendercontrol/window_multithreaded.cpp
@@ -77,7 +77,12 @@ static const QEvent::Type STOP = QEvent::Type(QEvent::User + 4);
static const QEvent::Type UPDATE = QEvent::Type(QEvent::User + 5);
QuickRenderer::QuickRenderer()
- : m_fbo(0),
+ : m_context(0),
+ m_surface(0),
+ m_fbo(0),
+ m_window(0),
+ m_quickWindow(0),
+ m_renderControl(0),
m_cubeRenderer(0),
m_quit(false)
{
@@ -209,7 +214,8 @@ void QuickRenderer::aboutToQuit()
}
WindowMultiThreaded::WindowMultiThreaded()
- : m_rootItem(0),
+ : m_qmlComponent(Q_NULLPTR),
+ m_rootItem(0),
m_quickInitialized(false),
m_psrRequested(false)
{
diff --git a/examples/quick/shared/Slider.qml b/examples/quick/shared/Slider.qml
index b3b2c98271..1728024715 100644
--- a/examples/quick/shared/Slider.qml
+++ b/examples/quick/shared/Slider.qml
@@ -44,6 +44,7 @@ Item {
property real init: min+(max-min)/2
property string name: "Slider"
property color color: "#0066cc"
+ property real minLabelWidth: 44
Component.onCompleted: setValue(init)
function setValue(v) {
@@ -57,7 +58,7 @@ Item {
anchors.left: parent.left
anchors.leftMargin: 16
height: childrenRect.height
- width: Math.max(44, childrenRect.width)
+ width: Math.max(minLabelWidth, childrenRect.width)
anchors.verticalCenter: parent.verticalCenter
Text {
text: slider.name + ":"
diff --git a/examples/quick/shared/quick_shared.qrc b/examples/quick/shared/quick_shared.qrc
index 015a1f99d5..ea7e0fdd89 100644
--- a/examples/quick/shared/quick_shared.qrc
+++ b/examples/quick/shared/quick_shared.qrc
@@ -7,5 +7,8 @@
<file>TextField.qml</file>
<file>images/back.png</file>
<file>images/next.png</file>
+ <file>images/checkmark.png</file>
+ <file>Slider.qml</file>
+ <file>images/slider_handle.png</file>
</qresource>
</RCC>
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h b/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h
index 55a3c7bf9b..03f8e2d71a 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h
@@ -395,8 +395,10 @@ public:
void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
{
- if (!imm.m_value && !m_fixedWidth)
+ if (!imm.m_value && !m_fixedWidth) {
+ move(src, dest);
return;
+ }
if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth) {
m_assembler.ori(dest, src, imm.m_value);
@@ -2647,7 +2649,7 @@ public:
{
m_assembler.truncwd(fpTempRegister, src);
m_assembler.mfc1(dest, fpTempRegister);
- return branch32(branchType == BranchIfTruncateFailed ? Equal : NotEqual, dest, TrustedImm32(0));
+ return branch32(branchType == BranchIfTruncateFailed ? Equal : NotEqual, dest, TrustedImm32(0x7fffffff));
}
// Result is undefined if the value is outside of the integer range.
diff --git a/src/3rdparty/masm/masm.pri b/src/3rdparty/masm/masm.pri
index 3655af36b6..3497650f0c 100644
--- a/src/3rdparty/masm/masm.pri
+++ b/src/3rdparty/masm/masm.pri
@@ -63,7 +63,20 @@ HEADERS += $$PWD/disassembler/ARMv7/ARMv7DOpcode.h
SOURCES += $$PWD/yarr/*.cpp
HEADERS += $$PWD/yarr/*.h
-retgen.output = RegExpJitTables.h
+#
+# Generate RegExpJitTables.h
+#
+GENERATEDDIR = .generated
+debug_and_release {
+ CONFIG(debug, debug|release) {
+ GENERATEDDIR = $$GENERATEDDIR/debug
+ } else {
+ GENERATEDDIR = $$GENERATEDDIR/release
+ }
+}
+INCLUDEPATH += $$GENERATEDDIR
+
+retgen.output = $$GENERATEDDIR/RegExpJitTables.h
retgen.script = $$PWD/create_regex_tables
retgen.input = retgen.script
retgen.CONFIG += no_link
diff --git a/src/imports/models/plugins.qmltypes b/src/imports/models/plugins.qmltypes
new file mode 100644
index 0000000000..e81a971e79
--- /dev/null
+++ b/src/imports/models/plugins.qmltypes
@@ -0,0 +1,540 @@
+import QtQuick.tooling 1.1
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable QtQml.Models 2.2'
+
+Module {
+ Component {
+ name: "QAbstractItemModel"
+ prototype: "QObject"
+ Enum {
+ name: "LayoutChangeHint"
+ values: {
+ "NoLayoutChangeHint": 0,
+ "VerticalSortHint": 1,
+ "HorizontalSortHint": 2
+ }
+ }
+ Signal {
+ name: "dataChanged"
+ Parameter { name: "topLeft"; type: "QModelIndex" }
+ Parameter { name: "bottomRight"; type: "QModelIndex" }
+ Parameter { name: "roles"; type: "QVector<int>" }
+ }
+ Signal {
+ name: "dataChanged"
+ Parameter { name: "topLeft"; type: "QModelIndex" }
+ Parameter { name: "bottomRight"; type: "QModelIndex" }
+ }
+ Signal {
+ name: "headerDataChanged"
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "layoutChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ Parameter { name: "hint"; type: "QAbstractItemModel::LayoutChangeHint" }
+ }
+ Signal {
+ name: "layoutChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ }
+ Signal { name: "layoutChanged" }
+ Signal {
+ name: "layoutAboutToBeChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ Parameter { name: "hint"; type: "QAbstractItemModel::LayoutChangeHint" }
+ }
+ Signal {
+ name: "layoutAboutToBeChanged"
+ Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" }
+ }
+ Signal { name: "layoutAboutToBeChanged" }
+ Signal {
+ name: "rowsAboutToBeInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsAboutToBeRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "rowsRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsInserted"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal {
+ name: "columnsRemoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "first"; type: "int" }
+ Parameter { name: "last"; type: "int" }
+ }
+ Signal { name: "modelAboutToBeReset" }
+ Signal { name: "modelReset" }
+ Signal {
+ name: "rowsAboutToBeMoved"
+ Parameter { name: "sourceParent"; type: "QModelIndex" }
+ Parameter { name: "sourceStart"; type: "int" }
+ Parameter { name: "sourceEnd"; type: "int" }
+ Parameter { name: "destinationParent"; type: "QModelIndex" }
+ Parameter { name: "destinationRow"; type: "int" }
+ }
+ Signal {
+ name: "rowsMoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "start"; type: "int" }
+ Parameter { name: "end"; type: "int" }
+ Parameter { name: "destination"; type: "QModelIndex" }
+ Parameter { name: "row"; type: "int" }
+ }
+ Signal {
+ name: "columnsAboutToBeMoved"
+ Parameter { name: "sourceParent"; type: "QModelIndex" }
+ Parameter { name: "sourceStart"; type: "int" }
+ Parameter { name: "sourceEnd"; type: "int" }
+ Parameter { name: "destinationParent"; type: "QModelIndex" }
+ Parameter { name: "destinationColumn"; type: "int" }
+ }
+ Signal {
+ name: "columnsMoved"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ Parameter { name: "start"; type: "int" }
+ Parameter { name: "end"; type: "int" }
+ Parameter { name: "destination"; type: "QModelIndex" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method { name: "submit"; type: "bool" }
+ Method { name: "revert" }
+ Method {
+ name: "hasIndex"
+ type: "bool"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "hasIndex"
+ type: "bool"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method {
+ name: "index"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "index"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ }
+ Method {
+ name: "parent"
+ type: "QModelIndex"
+ Parameter { name: "child"; type: "QModelIndex" }
+ }
+ Method {
+ name: "sibling"
+ type: "QModelIndex"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "idx"; type: "QModelIndex" }
+ }
+ Method {
+ name: "rowCount"
+ type: "int"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "rowCount"; type: "int" }
+ Method {
+ name: "columnCount"
+ type: "int"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "columnCount"; type: "int" }
+ Method {
+ name: "hasChildren"
+ type: "bool"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method { name: "hasChildren"; type: "bool" }
+ Method {
+ name: "data"
+ type: "QVariant"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "data"
+ type: "QVariant"
+ Parameter { name: "index"; type: "QModelIndex" }
+ }
+ Method {
+ name: "setData"
+ type: "bool"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "setData"
+ type: "bool"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "value"; type: "QVariant" }
+ }
+ Method {
+ name: "headerData"
+ type: "QVariant"
+ Parameter { name: "section"; type: "int" }
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ Parameter { name: "role"; type: "int" }
+ }
+ Method {
+ name: "headerData"
+ type: "QVariant"
+ Parameter { name: "section"; type: "int" }
+ Parameter { name: "orientation"; type: "Qt::Orientation" }
+ }
+ Method {
+ name: "fetchMore"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "canFetchMore"
+ type: "bool"
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "flags"
+ type: "Qt::ItemFlags"
+ Parameter { name: "index"; type: "QModelIndex" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "hits"; type: "int" }
+ Parameter { name: "flags"; type: "Qt::MatchFlags" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ Parameter { name: "hits"; type: "int" }
+ }
+ Method {
+ name: "match"
+ type: "QModelIndexList"
+ Parameter { name: "start"; type: "QModelIndex" }
+ Parameter { name: "role"; type: "int" }
+ Parameter { name: "value"; type: "QVariant" }
+ }
+ }
+ Component { name: "QAbstractListModel"; prototype: "QAbstractItemModel" }
+ Component {
+ name: "QItemSelectionModel"
+ prototype: "QObject"
+ exports: ["QtQml.Models/ItemSelectionModel 2.2"]
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "SelectionFlags"
+ values: {
+ "NoUpdate": 0,
+ "Clear": 1,
+ "Select": 2,
+ "Deselect": 4,
+ "Toggle": 8,
+ "Current": 16,
+ "Rows": 32,
+ "Columns": 64,
+ "SelectCurrent": 18,
+ "ToggleCurrent": 24,
+ "ClearAndSelect": 3
+ }
+ }
+ Property { name: "model"; type: "QAbstractItemModel"; isPointer: true }
+ Property { name: "hasSelection"; type: "bool"; isReadonly: true }
+ Property { name: "currentIndex"; type: "QModelIndex"; isReadonly: true }
+ Property { name: "selection"; type: "QItemSelection"; isReadonly: true }
+ Property { name: "selectedIndexes"; type: "QModelIndexList"; isReadonly: true }
+ Signal {
+ name: "selectionChanged"
+ Parameter { name: "selected"; type: "QItemSelection" }
+ Parameter { name: "deselected"; type: "QItemSelection" }
+ }
+ Signal {
+ name: "currentChanged"
+ Parameter { name: "current"; type: "QModelIndex" }
+ Parameter { name: "previous"; type: "QModelIndex" }
+ }
+ Signal {
+ name: "currentRowChanged"
+ Parameter { name: "current"; type: "QModelIndex" }
+ Parameter { name: "previous"; type: "QModelIndex" }
+ }
+ Signal {
+ name: "currentColumnChanged"
+ Parameter { name: "current"; type: "QModelIndex" }
+ Parameter { name: "previous"; type: "QModelIndex" }
+ }
+ Signal {
+ name: "modelChanged"
+ Parameter { name: "model"; type: "QAbstractItemModel"; isPointer: true }
+ }
+ Method {
+ name: "setCurrentIndex"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "command"; type: "QItemSelectionModel::SelectionFlags" }
+ }
+ Method {
+ name: "select"
+ Parameter { name: "index"; type: "QModelIndex" }
+ Parameter { name: "command"; type: "QItemSelectionModel::SelectionFlags" }
+ }
+ Method {
+ name: "select"
+ Parameter { name: "selection"; type: "QItemSelection" }
+ Parameter { name: "command"; type: "QItemSelectionModel::SelectionFlags" }
+ }
+ Method { name: "clear" }
+ Method { name: "reset" }
+ Method { name: "clearSelection" }
+ Method { name: "clearCurrentIndex" }
+ Method {
+ name: "isSelected"
+ type: "bool"
+ Parameter { name: "index"; type: "QModelIndex" }
+ }
+ Method {
+ name: "isRowSelected"
+ type: "bool"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "isColumnSelected"
+ type: "bool"
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "rowIntersectsSelection"
+ type: "bool"
+ Parameter { name: "row"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "columnIntersectsSelection"
+ type: "bool"
+ Parameter { name: "column"; type: "int" }
+ Parameter { name: "parent"; type: "QModelIndex" }
+ }
+ Method {
+ name: "selectedRows"
+ type: "QModelIndexList"
+ Parameter { name: "column"; type: "int" }
+ }
+ Method { name: "selectedRows"; type: "QModelIndexList" }
+ Method {
+ name: "selectedColumns"
+ type: "QModelIndexList"
+ Parameter { name: "row"; type: "int" }
+ }
+ Method { name: "selectedColumns"; type: "QModelIndexList" }
+ }
+ Component {
+ name: "QQmlDelegateModel"
+ defaultProperty: "delegate"
+ prototype: "QQmlInstanceModel"
+ exports: ["QtQml.Models/DelegateModel 2.1"]
+ exportMetaObjectRevisions: [0]
+ attachedType: "QQmlDelegateModelAttached"
+ Property { name: "model"; type: "QVariant" }
+ Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
+ Property { name: "filterOnGroup"; type: "string" }
+ Property { name: "items"; type: "QQmlDelegateModelGroup"; isReadonly: true; isPointer: true }
+ Property {
+ name: "persistedItems"
+ type: "QQmlDelegateModelGroup"
+ isReadonly: true
+ isPointer: true
+ }
+ Property { name: "groups"; type: "QQmlDelegateModelGroup"; isList: true; isReadonly: true }
+ Property { name: "parts"; type: "QObject"; isReadonly: true; isPointer: true }
+ Property { name: "rootIndex"; type: "QVariant" }
+ Signal { name: "filterGroupChanged" }
+ Signal { name: "defaultGroupsChanged" }
+ Method {
+ name: "modelIndex"
+ type: "QVariant"
+ Parameter { name: "idx"; type: "int" }
+ }
+ Method { name: "parentModelIndex"; type: "QVariant" }
+ }
+ Component {
+ name: "QQmlDelegateModelAttached"
+ prototype: "QObject"
+ Property { name: "model"; type: "QQmlDelegateModel"; isReadonly: true; isPointer: true }
+ Property { name: "groups"; type: "QStringList" }
+ Property { name: "isUnresolved"; type: "bool"; isReadonly: true }
+ Signal { name: "unresolvedChanged" }
+ }
+ Component {
+ name: "QQmlDelegateModelGroup"
+ prototype: "QObject"
+ exports: ["QtQml.Models/DelegateModelGroup 2.1"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "count"; type: "int"; isReadonly: true }
+ Property { name: "name"; type: "string" }
+ Property { name: "includeByDefault"; type: "bool" }
+ Signal { name: "defaultIncludeChanged" }
+ Signal {
+ name: "changed"
+ Parameter { name: "removed"; type: "QQmlV4Handle" }
+ Parameter { name: "inserted"; type: "QQmlV4Handle" }
+ }
+ Method {
+ name: "insert"
+ Parameter { type: "QQmlV4Function"; isPointer: true }
+ }
+ Method {
+ name: "create"
+ Parameter { type: "QQmlV4Function"; isPointer: true }
+ }
+ Method {
+ name: "resolve"
+ Parameter { type: "QQmlV4Function"; isPointer: true }
+ }
+ Method {
+ name: "remove"
+ Parameter { type: "QQmlV4Function"; isPointer: true }
+ }
+ Method {
+ name: "addGroups"
+ Parameter { type: "QQmlV4Function"; isPointer: true }
+ }
+ Method {
+ name: "removeGroups"
+ Parameter { type: "QQmlV4Function"; isPointer: true }
+ }
+ Method {
+ name: "setGroups"
+ Parameter { type: "QQmlV4Function"; isPointer: true }
+ }
+ Method {
+ name: "move"
+ Parameter { type: "QQmlV4Function"; isPointer: true }
+ }
+ Method {
+ name: "get"
+ type: "QQmlV4Handle"
+ Parameter { name: "index"; type: "int" }
+ }
+ }
+ Component { name: "QQmlDelegateModelParts"; prototype: "QObject" }
+ Component {
+ name: "QQmlListElement"
+ prototype: "QObject"
+ exports: ["QtQml.Models/ListElement 2.1"]
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
+ name: "QQmlListModel"
+ prototype: "QAbstractListModel"
+ exports: ["QtQml.Models/ListModel 2.1"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "count"; type: "int"; isReadonly: true }
+ Property { name: "dynamicRoles"; type: "bool" }
+ Method { name: "clear" }
+ Method {
+ name: "remove"
+ Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true }
+ }
+ Method {
+ name: "append"
+ Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true }
+ }
+ Method {
+ name: "insert"
+ Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true }
+ }
+ Method {
+ name: "get"
+ type: "QQmlV4Handle"
+ Parameter { name: "index"; type: "int" }
+ }
+ Method {
+ name: "set"
+ Parameter { name: "index"; type: "int" }
+ Parameter { type: "QQmlV4Handle" }
+ }
+ Method {
+ name: "setProperty"
+ Parameter { name: "index"; type: "int" }
+ Parameter { name: "property"; type: "string" }
+ Parameter { name: "value"; type: "QVariant" }
+ }
+ Method {
+ name: "move"
+ Parameter { name: "from"; type: "int" }
+ Parameter { name: "to"; type: "int" }
+ Parameter { name: "count"; type: "int" }
+ }
+ Method { name: "sync" }
+ }
+ Component {
+ name: "QQmlObjectModel"
+ defaultProperty: "children"
+ prototype: "QQmlInstanceModel"
+ exports: ["QtQml.Models/ObjectModel 2.1"]
+ exportMetaObjectRevisions: [0]
+ attachedType: "QQmlObjectModelAttached"
+ Property { name: "children"; type: "QObject"; isList: true; isReadonly: true }
+ }
+ Component {
+ name: "QQmlObjectModelAttached"
+ prototype: "QObject"
+ Property { name: "index"; type: "int"; isReadonly: true }
+ }
+}
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
index e9dba5fdaf..e1284b7233 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
+++ b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
@@ -1,5 +1,5 @@
TARGET = qmldbg_tcp
-QT = qml-private
+QT = qml-private core-private
PLUGIN_TYPE = qmltooling
PLUGIN_CLASS_NAME = QTcpServerConnection
diff --git a/src/plugins/qmltooling/shared/qpacketprotocol.cpp b/src/plugins/qmltooling/shared/qpacketprotocol.cpp
index b680cec7e3..9a58f803c1 100644
--- a/src/plugins/qmltooling/shared/qpacketprotocol.cpp
+++ b/src/plugins/qmltooling/shared/qpacketprotocol.cpp
@@ -35,6 +35,7 @@
#include <QtCore/QBuffer>
#include <QtCore/QElapsedTimer>
+#include <private/qiodevice_p.h>
QT_BEGIN_NAMESPACE
@@ -318,19 +319,6 @@ QPacket QPacketProtocol::read()
return rv;
}
-/*
- Returns the difference between msecs and elapsed. If msecs is -1,
- however, -1 is returned.
-*/
-static int qt_timeout_value(int msecs, int elapsed)
-{
- if (msecs == -1)
- return -1;
-
- int timeout = msecs - elapsed;
- return timeout < 0 ? 0 : timeout;
-}
-
/*!
This function locks until a new packet is available for reading and the
\l{QIODevice::}{readyRead()} signal has been emitted. The function
@@ -356,7 +344,7 @@ bool QPacketProtocol::waitForReadyRead(int msecs)
return false;
if (!d->waitingForPacket)
return true;
- msecs = qt_timeout_value(msecs, stopWatch.elapsed());
+ msecs = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
} while (true);
}
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index ec8e6ac33c..4bdfe444f5 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -392,6 +392,11 @@ void QQmlTypeCompiler::setDeferredBindingsPerObject(const QHash<int, QBitArray>
compiledData->deferredBindingsPerObject = deferredBindingsPerObject;
}
+void QQmlTypeCompiler::setBindingPropertyDataPerObject(const QVector<QV4::CompiledData::BindingPropertyData> &propertyData)
+{
+ compiledData->compilationUnit->bindingPropertyDataPerObject = propertyData;
+}
+
QString QQmlTypeCompiler::bindingAsString(const QmlIR::Object *object, int scriptIndex) const
{
return object->bindingAsString(document, scriptIndex);
@@ -402,7 +407,7 @@ QQmlCompilePass::QQmlCompilePass(QQmlTypeCompiler *typeCompiler)
{
}
-void QQmlCompilePass::recordError(const QV4::CompiledData::Location &location, const QString &description)
+void QQmlCompilePass::recordError(const QV4::CompiledData::Location &location, const QString &description) const
{
QQmlError error;
error.setLine(location.line);
@@ -1712,9 +1717,11 @@ QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler)
bool QQmlPropertyValidator::validate()
{
+ _bindingPropertyDataPerObject.resize(qmlUnit->nObjects);
if (!validateObject(qmlUnit->indexOfRootObject, /*instantiatingBinding*/0))
return false;
- compiler->setDeferredBindingsPerObject(deferredBindingsPerObject);
+ compiler->setDeferredBindingsPerObject(_deferredBindingsPerObject);
+ compiler->setBindingPropertyDataPerObject(_bindingPropertyDataPerObject);
return true;
}
@@ -1752,7 +1759,7 @@ struct BindingFinder
}
};
-bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty)
+bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty) const
{
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
if (obj->idIndex != 0)
@@ -1818,6 +1825,8 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
defaultProperty = propertyCache->defaultProperty();
}
+ QV4::CompiledData::BindingPropertyData collectedBindingPropertyData(obj->nBindings);
+
binding = obj->bindingTable();
for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
QString name = stringAt(binding->propertyNameIndex);
@@ -1837,22 +1846,6 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
}
}
- // Signal handlers were resolved and checked earlier in the signal handler conversion pass.
- if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
- || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
- continue;
-
- if (name.constData()->isUpper() && !binding->isAttachedProperty()) {
- QQmlType *type = 0;
- QQmlImportNamespace *typeNamespace = 0;
- compiler->imports()->resolveType(stringAt(binding->propertyNameIndex), &type, 0, 0, &typeNamespace);
- if (typeNamespace)
- recordError(binding->location, tr("Invalid use of namespace"));
- else
- recordError(binding->location, tr("Invalid attached object assignment"));
- return false;
- }
-
bool bindingToDefaultProperty = false;
bool notInRevision = false;
@@ -1882,9 +1875,23 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
bindingToDefaultProperty = true;
}
+ if (pd)
+ collectedBindingPropertyData[i] = pd;
+
+ if (name.constData()->isUpper() && !binding->isAttachedProperty()) {
+ QQmlType *type = 0;
+ QQmlImportNamespace *typeNamespace = 0;
+ compiler->imports()->resolveType(stringAt(binding->propertyNameIndex), &type, 0, 0, &typeNamespace);
+ if (typeNamespace)
+ recordError(binding->location, tr("Invalid use of namespace"));
+ else
+ recordError(binding->location, tr("Invalid attached object assignment"));
+ return false;
+ }
+
bool seenSubObjectWithId = false;
- if (binding->type >= QV4::CompiledData::Binding::Type_Object && !customParser) {
+ if (binding->type >= QV4::CompiledData::Binding::Type_Object && (!customParser || binding->type == QV4::CompiledData::Binding::Type_AttachedProperty)) {
qSwap(_seenObjectWithId, seenSubObjectWithId);
const bool subObjectValid = validateObject(binding->value.objectIndex, binding, pd && QQmlValueTypeFactory::metaObjectForMetaType(pd->propType));
qSwap(_seenObjectWithId, seenSubObjectWithId);
@@ -1902,6 +1909,11 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
deferredBindings.setBit(i);
}
+ // Signal handlers were resolved and checked earlier in the signal handler conversion pass.
+ if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
+ || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
+ continue;
+
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
if (instantiatingBinding && (instantiatingBinding->isAttachedProperty() || instantiatingBinding->isGroupProperty())) {
recordError(binding->location, tr("Attached properties cannot be used here"));
@@ -1990,6 +2002,11 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
}
}
+ if (obj->idIndex) {
+ bool notInRevision = false;
+ collectedBindingPropertyData << propertyResolver.property(QStringLiteral("id"), &notInRevision);
+ }
+
if (customParser && !customBindings.isEmpty()) {
customParser->clearErrors();
customParser->compiler = this;
@@ -2007,12 +2024,14 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
}
if (!deferredBindings.isEmpty())
- deferredBindingsPerObject.insert(objectIndex, deferredBindings);
+ _deferredBindingsPerObject.insert(objectIndex, deferredBindings);
+
+ _bindingPropertyDataPerObject[objectIndex] = collectedBindingPropertyData;
return true;
}
-bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
+bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) const
{
if (property->isQList()) {
recordError(binding->valueLocation, tr("Cannot assign primitives to lists"));
@@ -2288,7 +2307,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa
Returns true if from can be assigned to a (QObject) property of type
to.
*/
-bool QQmlPropertyValidator::canCoerce(int to, QQmlPropertyCache *fromMo)
+bool QQmlPropertyValidator::canCoerce(int to, QQmlPropertyCache *fromMo) const
{
QQmlPropertyCache *toMo = enginePrivate->rawPropertyCacheForType(to);
@@ -2300,7 +2319,7 @@ bool QQmlPropertyValidator::canCoerce(int to, QQmlPropertyCache *fromMo)
return false;
}
-bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding)
+bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding) const
{
if (binding->flags & QV4::CompiledData::Binding::IsOnAssignment) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Object);
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index 025718dd96..75987af656 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -93,6 +93,7 @@ public:
QStringRef newStringRef(const QString &string);
const QV4::Compiler::StringTableGenerator *stringPool() const;
void setDeferredBindingsPerObject(const QHash<int, QBitArray> &deferredBindingsPerObject);
+ void setBindingPropertyDataPerObject(const QVector<QV4::CompiledData::BindingPropertyData> &propertyData);
const QHash<int, QQmlCustomParser*> &customParserCache() const { return customParsers; }
@@ -116,7 +117,7 @@ struct QQmlCompilePass
QString stringAt(int idx) const { return compiler->stringAt(idx); }
protected:
- void recordError(const QV4::CompiledData::Location &location, const QString &description);
+ void recordError(const QV4::CompiledData::Location &location, const QString &description) const;
QQmlTypeCompiler *compiler;
};
@@ -276,13 +277,13 @@ public:
virtual QString bindingAsString(int objectIndex, const QV4::CompiledData::Binding *binding) const;
private:
- bool validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty = false);
- bool validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
- bool validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding);
+ bool validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty = false) const;
+ bool validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) const;
+ bool validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding) const;
bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); }
- bool canCoerce(int to, QQmlPropertyCache *fromMo);
+ bool canCoerce(int to, QQmlPropertyCache *fromMo) const;
QQmlEnginePrivate *enginePrivate;
const QV4::CompiledData::Unit *qmlUnit;
@@ -291,9 +292,11 @@ private:
const QVector<QQmlPropertyCache *> &propertyCaches;
const QHash<int, QHash<int, int> > objectIndexToIdPerComponent;
QHash<int, QBitArray> *customParserBindingsPerObject;
- QHash<int, QBitArray> deferredBindingsPerObject;
- bool _seenObjectWithId;
+ // collected state variables, essentially write-only
+ mutable QHash<int, QBitArray> _deferredBindingsPerObject;
+ mutable bool _seenObjectWithId;
+ mutable QVector<QV4::CompiledData::BindingPropertyData> _bindingPropertyDataPerObject;
};
// ### merge with QtQml::JSCodeGen and operate directly on object->functionsAndExpressions once old compiler is gone.
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 653416783e..5d954eb4fc 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -40,6 +40,7 @@
#include <private/qv4objectproto_p.h>
#include <private/qv4lookup_p.h>
#include <private/qv4regexpobject_p.h>
+#include <private/qqmlpropertycache_p.h>
#endif
#include <private/qqmlirbuilder_p.h>
#include <QCoreApplication>
@@ -53,6 +54,15 @@ namespace QV4 {
namespace CompiledData {
#ifndef V4_BOOTSTRAP
+CompilationUnit::CompilationUnit()
+ : data(0)
+ , engine(0)
+ , runtimeStrings(0)
+ , runtimeLookups(0)
+ , runtimeRegularExpressions(0)
+ , runtimeClasses(0)
+{}
+
CompilationUnit::~CompilationUnit()
{
unlink();
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 7b40fa849a..f46e27fe98 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -46,6 +46,9 @@
QT_BEGIN_NAMESPACE
+class QQmlPropertyCache;
+class QQmlPropertyData;
+
namespace QmlIR {
struct Document;
}
@@ -556,6 +559,9 @@ struct TypeReferenceMap : QHash<int, TypeReference>
}
};
+// index is per-object binding index
+typedef QVector<QQmlPropertyData*> BindingPropertyData;
+
// This is how this hooks into the existing structures:
//VM::Function
@@ -570,14 +576,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
{}
virtual ~CompilationUnit() {}
#else
- CompilationUnit()
- : data(0)
- , engine(0)
- , runtimeStrings(0)
- , runtimeLookups(0)
- , runtimeRegularExpressions(0)
- , runtimeClasses(0)
- {}
+ CompilationUnit();
virtual ~CompilationUnit();
#endif
@@ -598,6 +597,11 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
QVector<QV4::Function *> runtimeFunctions;
mutable QQmlNullableValue<QUrl> m_url;
+ // index is object index. This allows fast access to the
+ // property data when initializing bindings, avoiding expensive
+ // lookups by string (property name).
+ QVector<BindingPropertyData> bindingPropertyDataPerObject;
+
QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
void unlink();
diff --git a/src/qml/debugger/qqmldebugservice.cpp b/src/qml/debugger/qqmldebugservice.cpp
index f3ba20538d..b37a7335a0 100644
--- a/src/qml/debugger/qqmldebugservice.cpp
+++ b/src/qml/debugger/qqmldebugservice.cpp
@@ -215,7 +215,7 @@ QList<QObject*> QQmlDebugService::objectForLocationInfo(const QString &filename,
} else {
QQmlData *ddata = QQmlData::get(iter.value());
if (ddata && ddata->outerContext) {
- if (QFileInfo(ddata->outerContext->urlString).fileName() == filename &&
+ if (QFileInfo(ddata->outerContext->urlString()).fileName() == filename &&
ddata->lineNumber == lineNumber &&
ddata->columnNumber >= columnNumber) {
objects << *iter;
diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp
index b0c0995a44..da01d00f17 100644
--- a/src/qml/debugger/qqmlenginedebugservice.cpp
+++ b/src/qml/debugger/qqmlenginedebugservice.cpp
@@ -391,7 +391,7 @@ QQmlEngineDebugService::objectData(QObject *object)
QQmlData *ddata = QQmlData::get(object);
QQmlObjectData rv;
if (ddata && ddata->outerContext) {
- rv.url = ddata->outerContext->url;
+ rv.url = ddata->outerContext->url();
rv.lineNumber = ddata->lineNumber;
rv.columnNumber = ddata->columnNumber;
} else {
@@ -762,7 +762,7 @@ bool QQmlEngineDebugService::setMethodBody(int objectId, const QString &method,
int lineNumber = vmeMetaObject->vmeMethodLineNumber(prop->coreIndex);
QV4::ExecutionEngine *v4 = QV8Engine::getV4(qmlEngine(object)->handle());
QV4::Scope scope(v4);
- QV4::ScopedValue v(scope, QQmlExpressionPrivate::evalFunction(contextData, object, jsfunction, contextData->url.toString(), lineNumber));
+ QV4::ScopedValue v(scope, QQmlExpressionPrivate::evalFunction(contextData, object, jsfunction, contextData->urlString(), lineNumber));
vmeMetaObject->setVmeMethod(prop->coreIndex, v);
return true;
}
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
index ba85a76277..5c994b112f 100644
--- a/src/qml/debugger/qqmlprofiler_p.h
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -112,11 +112,11 @@ Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
class QQmlProfiler : public QObject, public QQmlProfilerDefinitions {
Q_OBJECT
public:
- void startBinding(const QString &fileName, int line, int column)
+ void startBinding(const QQmlSourceLocation &location)
{
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
(1 << RangeStart | 1 << RangeLocation), 1 << Binding,
- fileName, line, column));
+ location.sourceFile, qmlSourceCoordinate(location.line), qmlSourceCoordinate(location.column)));
}
// Have toByteArrays() construct another RangeData event from the same QString later.
@@ -201,11 +201,11 @@ struct QQmlProfilerHelper : public QQmlProfilerDefinitions {
};
struct QQmlBindingProfiler : public QQmlProfilerHelper {
- QQmlBindingProfiler(QQmlProfiler *profiler, const QString &url, int line, int column) :
+ QQmlBindingProfiler(QQmlProfiler *profiler, const QV4::FunctionObject *function) :
QQmlProfilerHelper(profiler)
{
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileBinding, profiler,
- startBinding(url, line, column));
+ startBinding(function->sourceLocation()));
}
~QQmlBindingProfiler()
diff --git a/src/qml/doc/snippets/code/src_script_qjsengine.cpp b/src/qml/doc/snippets/code/src_script_qjsengine.cpp
index 315df2c23f..c9bd7dfcd9 100644
--- a/src/qml/doc/snippets/code/src_script_qjsengine.cpp
+++ b/src/qml/doc/snippets/code/src_script_qjsengine.cpp
@@ -74,7 +74,10 @@ QJSValue myNumberPlusOne = myEngine.evaluate("myNumber + 1");
//! [4]
QJSValue result = myEngine.evaluate(...);
if (result.isError())
- qDebug() << "uncaught exception:" << result.toString();
+ qDebug()
+ << "Uncaught exception at line"
+ << result.property("lineNumber").toInt()
+ << ":" << result.toString();
//! [4]
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index 6b38ffe53f..3b65acb26c 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -916,25 +916,25 @@ public:
template <typename ArgRet, typename Callable, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
void generateFunctionCallImp(ArgRet r, const char* functionName, Callable function, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
{
- generateFunctionCallImp(r, functionName, function, arg1, arg2, arg3, arg4, VoidType());
+ generateFunctionCallImp(r, functionName, function, arg1, arg2, arg3, arg4, VoidType(), VoidType());
}
template <typename ArgRet, typename Callable, typename Arg1, typename Arg2, typename Arg3>
void generateFunctionCallImp(ArgRet r, const char* functionName, Callable function, Arg1 arg1, Arg2 arg2, Arg3 arg3)
{
- generateFunctionCallImp(r, functionName, function, arg1, arg2, arg3, VoidType(), VoidType());
+ generateFunctionCallImp(r, functionName, function, arg1, arg2, arg3, VoidType(), VoidType(), VoidType());
}
template <typename ArgRet, typename Callable, typename Arg1, typename Arg2>
void generateFunctionCallImp(ArgRet r, const char* functionName, Callable function, Arg1 arg1, Arg2 arg2)
{
- generateFunctionCallImp(r, functionName, function, arg1, arg2, VoidType(), VoidType(), VoidType());
+ generateFunctionCallImp(r, functionName, function, arg1, arg2, VoidType(), VoidType(), VoidType(), VoidType());
}
template <typename ArgRet, typename Callable, typename Arg1>
void generateFunctionCallImp(ArgRet r, const char* functionName, Callable function, Arg1 arg1)
{
- generateFunctionCallImp(r, functionName, function, arg1, VoidType(), VoidType(), VoidType(), VoidType());
+ generateFunctionCallImp(r, functionName, function, arg1, VoidType(), VoidType(), VoidType(), VoidType(), VoidType());
}
Pointer toAddress(RegisterID tmpReg, IR::Expr *e, int offset)
diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp
index a055dffcac..c6c8023cd7 100644
--- a/src/qml/jit/qv4binop.cpp
+++ b/src/qml/jit/qv4binop.cpp
@@ -430,13 +430,13 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
as->lshift32(l, Assembler::ScratchRegister, targetReg);
break;
- case IR::OpLShift:
+ case IR::OpRShift:
as->move(r, Assembler::ScratchRegister);
as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister);
as->rshift32(l, Assembler::ScratchRegister, targetReg);
break;
- case IR::OpLShift:
+ case IR::OpURShift:
as->move(r, Assembler::ScratchRegister);
as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister);
as->storeUInt32(targetReg, target); // IMPORTANT: do NOT do a break here! The stored type of an urshift is different from the other binary operations!
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index 05d3876466..da511cd1eb 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -1485,7 +1485,7 @@ void InstructionSelection::visitRet(IR::Ret *s)
Q_UNUSED(s);
}
- _as->exceptionReturnLabel = _as->label();
+ Assembler::Label leaveStackFrame = _as->label();
const int locals = _as->stackLayout().calculateJSStackFrameSize();
_as->subPtr(Assembler::TrustedImm32(sizeof(QV4::Value)*locals), Assembler::LocalsRegister);
@@ -1495,6 +1495,19 @@ void InstructionSelection::visitRet(IR::Ret *s)
_as->leaveStandardStackFrame(regularRegistersToSave, fpRegistersToSave);
_as->ret();
+
+ _as->exceptionReturnLabel = _as->label();
+ QV4::Primitive retVal = Primitive::undefinedValue();
+#if CPU(X86)
+ _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::X86Registers::eax);
+ _as->move(Assembler::TrustedImm32(retVal.tag), JSC::X86Registers::edx);
+#elif CPU(ARM)
+ _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::ARMRegisters::r0);
+ _as->move(Assembler::TrustedImm32(retVal.tag), JSC::ARMRegisters::r1);
+#else
+ _as->move(Assembler::TrustedImm64(retVal.val), Assembler::ReturnValueRegister);
+#endif
+ _as->jump(leaveStackFrame);
}
int InstructionSelection::prepareVariableArguments(IR::ExprList* args)
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index ceeaef1789..4db73c49f6 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -103,8 +103,8 @@ Q_DECLARE_METATYPE(QList<int>)
Here we pass the name of the file as the second argument to
evaluate(). This does not affect evaluation in any way; the second
- argument is a general-purpose string that is used to identify the
- script for debugging purposes.
+ argument is a general-purpose string that is stored in the \c Error
+ object for debugging purposes.
\section1 Engine Configuration
@@ -125,11 +125,21 @@ Q_DECLARE_METATYPE(QList<int>)
\section1 Script Exceptions
evaluate() can throw a script exception (e.g. due to a syntax
- error); in that case, the return value is the value that was thrown
- (typically an \c{Error} object). You can check whether the
- evaluation caused an exception by calling isError() on the return
- value. If isError() returns true, you can call toString() on the
- error object to obtain an error message.
+ error). If it does, then evaluate() returns the value that was thrown
+ (typically an \c{Error} object). Use \l QJSValue::isError() to check
+ for exceptions.
+
+ For detailed information about the error, use \l QJSValue::toString() to
+ obtain an error message, and use \l QJSValue::property() to query the
+ properties of the \c Error object. The following properties are available:
+
+ \list
+ \li \c name
+ \li \c message
+ \li \c fileName
+ \li \c lineNumber
+ \li \c stack
+ \endlist
\snippet code/src_script_qjsengine.cpp 4
@@ -282,7 +292,7 @@ void QJSEngine::installTranslatorFunctions(const QJSValue &object)
The script code will be evaluated in the context of the global object.
- The evaluation of \a program can cause an exception in the
+ The evaluation of \a program can cause an \l{Script Exceptions}{exception} in the
engine; in this case the return value will be the exception
that was thrown (typically an \c{Error} object; see
QJSValue::isError()).
@@ -372,7 +382,7 @@ QJSValue QJSEngine::newArray(uint length)
If the given \a object is deleted outside of the engine's control, any
attempt to access the deleted QObject's members through the JavaScript
wrapper object (either by script code or C++) will result in a
- script exception.
+ \l{Script Exceptions}{script exception}.
\sa QJSValue::toQObject()
*/
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index f6031d4268..466ac26eb6 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -310,6 +310,8 @@ bool QJSValue::isUndefined() const
/*!
Returns true if this QJSValue is an object of the Error class;
otherwise returns false.
+
+ \sa {QJSEngine#Script Exceptions}{QJSEngine - Script Exceptions}
*/
bool QJSValue::isError() const
{
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp
index 432d70f151..145e400c20 100644
--- a/src/qml/jsruntime/qv4arraybuffer.cpp
+++ b/src/qml/jsruntime/qv4arraybuffer.cpp
@@ -95,6 +95,13 @@ Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, size_t length)
memset(data->data(), 0, length + 1);
}
+Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, const QByteArray& array)
+ : Heap::Object(e->emptyClass, e->arrayBufferPrototype.as<QV4::Object>())
+ , data(const_cast<QByteArray&>(array).data_ptr())
+{
+ data->ref.ref();
+}
+
Heap::ArrayBuffer::~ArrayBuffer()
{
if (!data->ref.deref())
@@ -108,6 +115,25 @@ QByteArray ArrayBuffer::asByteArray() const
return QByteArray(ba);
}
+void ArrayBuffer::detach() {
+ if (!d()->data->ref.isShared())
+ return;
+
+ QTypedArrayData<char> *oldData = d()->data;
+
+ d()->data = QTypedArrayData<char>::allocate(oldData->size + 1);
+ if (!d()->data) {
+ engine()->throwRangeError(QStringLiteral("ArrayBuffer: out of memory"));
+ return;
+ }
+
+ memcpy(d()->data->data(), oldData->data(), oldData->size + 1);
+
+ if (!oldData->ref.deref())
+ QTypedArrayData<char>::deallocate(oldData);
+}
+
+
void ArrayBufferPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h
index cbcde18793..a7f9e92c80 100644
--- a/src/qml/jsruntime/qv4arraybuffer_p.h
+++ b/src/qml/jsruntime/qv4arraybuffer_p.h
@@ -48,6 +48,7 @@ struct ArrayBufferCtor : FunctionObject {
struct Q_QML_PRIVATE_EXPORT ArrayBuffer : Object {
ArrayBuffer(ExecutionEngine *e, size_t length);
+ ArrayBuffer(ExecutionEngine *e, const QByteArray& array);
~ArrayBuffer();
QTypedArrayData<char> *data;
@@ -74,15 +75,11 @@ struct Q_QML_PRIVATE_EXPORT ArrayBuffer : Object
QByteArray asByteArray() const;
uint byteLength() const { return d()->byteLength(); }
- char *data() {
- // ### detach if refcount > 1
- return d()->data->data();
- }
- const char *constData() {
- // ### detach if refcount > 1
- return d()->data->data();
- }
+ char *data() { detach(); return d()->data ? d()->data->data() : 0; }
+ const char *constData() { detach(); return d()->data ? d()->data->data() : 0; }
+private:
+ void detach();
};
struct ArrayBufferPrototype: Object
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 6d3ba2c516..0ef7d56c4d 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -167,7 +167,7 @@ Heap::CallContext::CallContext(ExecutionEngine *engine, QV4::Object *qml, QV4::F
callData->argc = 0;
callData->thisObject = Primitive::undefinedValue();
- strictMode = true;
+ strictMode = false;
outer = function->scope();
activation = qml->d();
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 9b9a2349a9..8859f73bd7 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -308,6 +308,10 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
functionPrototype = memoryManager->alloc<FunctionPrototype>(functionProtoClass, objectPrototype.as<Object>());
functionClass = emptyClass->addMember(id_prototype, Attr_NotEnumerable|Attr_NotConfigurable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_Prototype);
+ simpleScriptFunctionClass = functionClass->addMember(id_name, Attr_ReadOnly, &index);
+ Q_ASSERT(index == Heap::SimpleScriptFunction::Index_Name);
+ simpleScriptFunctionClass = simpleScriptFunctionClass->addMember(id_length, Attr_ReadOnly, &index);
+ Q_ASSERT(index == Heap::SimpleScriptFunction::Index_Length);
protoClass = emptyClass->addMember(id_constructor, Attr_NotEnumerable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_ProtoConstructor);
@@ -585,10 +589,7 @@ Heap::ArrayObject *ExecutionEngine::newArrayObject(InternalClass *ic, Object *pr
Heap::ArrayBuffer *ExecutionEngine::newArrayBuffer(const QByteArray &array)
{
Scope scope(this);
- Scoped<ArrayBuffer> object(scope, memoryManager->alloc<ArrayBuffer>(this, array.size()));
- if (!hasException) {
- memcpy(object->d()->data->data(), array.data(), array.size());
- }
+ Scoped<ArrayBuffer> object(scope, memoryManager->alloc<ArrayBuffer>(this, array));
return object->d();
}
@@ -1741,9 +1742,8 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
{
QV4::Scoped<QV4::QQmlValueTypeWrapper> vtw(scope, value);
- if (vtw && vtw->d()->metaType == type) {
- vtw->toGadget(data);
- return true;
+ if (vtw && vtw->typeId() == type) {
+ return vtw->toGadget(data);
}
}
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index e59e96f534..33dce48737 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -171,6 +171,7 @@ public:
InternalClass *arrayClass;
InternalClass *functionClass;
+ InternalClass *simpleScriptFunctionClass;
InternalClass *protoClass;
InternalClass *regExpExecArrayClass;
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index d9d8ed6d20..2c5795e8b3 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -62,6 +62,7 @@ using namespace QV4;
Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype)
: Heap::Object(ic, prototype)
+ , stack(Q_NULLPTR)
{
Scope scope(ic->engine);
Scoped<QV4::ErrorObject> e(scope, this);
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index f5db520348..5a68cf6b79 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -65,6 +65,7 @@ DEFINE_OBJECT_VTABLE(FunctionObject);
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *name, bool createProto)
: Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.objectValue())
, scope(scope->d())
+ , function(Q_NULLPTR)
{
Scope s(scope->engine());
ScopedFunctionObject f(s, this);
@@ -74,6 +75,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *function, bool createProto)
: Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.objectValue())
, scope(scope->d())
+ , function(Q_NULLPTR)
{
Scope s(scope->engine());
ScopedString name(s, function->name());
@@ -84,6 +86,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *fun
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString &name, bool createProto)
: Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.objectValue())
, scope(scope->d())
+ , function(Q_NULLPTR)
{
Scope s(scope->engine());
ScopedFunctionObject f(s, this);
@@ -94,6 +97,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString
Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto)
: Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype.objectValue())
, scope(scope)
+ , function(Q_NULLPTR)
{
Scope s(scope->engine);
ScopedFunctionObject f(s, this);
@@ -104,6 +108,7 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &nam
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name)
: Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.objectValue())
, scope(scope->d())
+ , function(Q_NULLPTR)
{
Scope s(scope);
ScopedFunctionObject f(s, this);
@@ -114,6 +119,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const Returne
Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValue name)
: Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype.objectValue())
, scope(scope)
+ , function(Q_NULLPTR)
{
Scope s(scope->engine);
ScopedFunctionObject f(s, this);
@@ -124,6 +130,7 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValu
Heap::FunctionObject::FunctionObject(InternalClass *ic, QV4::Object *prototype)
: Heap::Object(ic, prototype)
, scope(ic->engine->rootContext())
+ , function(Q_NULLPTR)
{
Scope scope(ic->engine);
ScopedObject o(scope, this);
@@ -209,6 +216,18 @@ bool FunctionObject::isBoundFunction() const
return d()->vtable == BoundFunction::staticVTable();
}
+QQmlSourceLocation FunctionObject::sourceLocation() const
+{
+ if (isBinding()) {
+ Q_ASSERT(as<const QV4::QQmlBindingFunction>());
+ return static_cast<QV4::Heap::QQmlBindingFunction *>(d())->bindingLocation;
+ }
+ QV4::Function *function = d()->function;
+ Q_ASSERT(function);
+
+ return QQmlSourceLocation(function->sourceFile(), function->compiledFunction->location.line, function->compiledFunction->location.column);
+}
+
DEFINE_OBJECT_VTABLE(FunctionCtor);
Heap::FunctionCtor::FunctionCtor(QV4::ExecutionContext *scope)
@@ -446,21 +465,27 @@ ReturnedValue ScriptFunction::call(const Managed *that, CallData *callData)
DEFINE_OBJECT_VTABLE(SimpleScriptFunction);
Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto)
- : Heap::FunctionObject(scope, function, createProto)
+ : Heap::FunctionObject(function->compilationUnit->engine->simpleScriptFunctionClass, function->compilationUnit->engine->functionPrototype.as<QV4::Object>())
{
+ this->scope = scope->d();
+
this->function = function;
function->compilationUnit->addref();
Q_ASSERT(function);
Q_ASSERT(function->code);
- // global function
- if (!scope)
- return;
-
Scope s(scope);
ScopedFunctionObject f(s, this);
- f->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(f->formalParameterCount()));
+ if (createProto) {
+ ScopedString name(s, function->name());
+ f->init(name, createProto);
+ f->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(f->formalParameterCount()));
+ } else {
+ f->ensureMemberIndex(s.engine, Index_Length);
+ memberData->data[Index_Name] = function->name();
+ memberData->data[Index_Length] = Primitive::fromInt32(f->formalParameterCount());
+ }
if (scope->d()->strictMode) {
ScopedProperty pd(s);
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index d13ecb98fb..2aa5d95831 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -40,6 +40,8 @@
QT_BEGIN_NAMESPACE
+struct QQmlSourceLocation;
+
namespace QV4 {
namespace Heap {
@@ -87,6 +89,10 @@ struct IndexedBuiltinFunction : FunctionObject {
};
struct SimpleScriptFunction : FunctionObject {
+ enum {
+ Index_Name = FunctionObject::Index_Prototype + 1,
+ Index_Length
+ };
SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto);
};
@@ -136,6 +142,8 @@ struct Q_QML_EXPORT FunctionObject: Object {
bool isBinding() const;
bool isBoundFunction() const;
+ QQmlSourceLocation sourceLocation() const;
+
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 34414cd220..a7810563c9 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1836,7 +1836,7 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData) const
if (!wrapper)
return Encode::undefined();
- object = QQmlObjectOrGadget(d()->propertyCache.data(), wrapper->d()->gadget());
+ object = QQmlObjectOrGadget(d()->propertyCache.data(), wrapper->d()->gadgetPtr);
}
QQmlPropertyData method;
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index ae1e8fbd32..7deb2098ac 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -54,8 +54,8 @@ struct Q_QML_PRIVATE_EXPORT Value
/*
We use two different ways of encoding JS values. One for 32bit and one for 64bit systems.
- In both cases, we 8 bytes for a value and different variant of NaN boxing. A Double NaN (actually -qNaN)
- is indicated by a number that has the top 13 bits set. THe other values are usually set to 0 by the
+ In both cases, we use 8 bytes for a value and a different variant of NaN boxing. A Double NaN (actually -qNaN)
+ is indicated by a number that has the top 13 bits set. The other values are usually set to 0 by the
processor, and are thus free for us to store other data. We keep pointers in there for managed objects,
and encode the other types using the free space given to use by the unused bits for NaN values. This also
works for pointers on 64 bit systems, as they all currently only have 48 bits of addressable memory.
@@ -63,7 +63,7 @@ struct Q_QML_PRIVATE_EXPORT Value
On 32bit, we store doubles as doubles. All other values, have the high 32bits set to a value that
will make the number a NaN. The Masks below are used for encoding the other types.
- On 64 bit, we xor Doubles with (0xffff8000 << 32). Thas has the effect that no doubles will get encoded
+ On 64 bit, we xor Doubles with (0xffff8000 << 32). That has the effect that no doubles will get encoded
with the 13 highest bits all 0. We are now using special values for bits 14-17 to encode our values. These
can be used, as the highest valid pointer on a 64 bit system is 2^48-1.
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 44bbe14d43..455c94f138 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -93,8 +93,8 @@ QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlConte
QQmlContextData *ctxtdata = QQmlContextData::get(scriptPrivate->context);
QQmlEnginePrivate *engine = QQmlEnginePrivate::get(scriptPrivate->context->engine());
- if (engine && ctxtdata && !ctxtdata->url.isEmpty() && ctxtdata->typeCompilationUnit) {
- url = ctxtdata->url.toString();
+ if (engine && ctxtdata && !ctxtdata->urlString().isEmpty() && ctxtdata->typeCompilationUnit) {
+ url = ctxtdata->urlString();
if (scriptPrivate->bindingId != QQmlBinding::Invalid)
runtimeFunction = ctxtdata->typeCompilationUnit->runtimeFunctions.at(scriptPrivate->bindingId);
}
@@ -165,34 +165,13 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
if (QQmlData::wasDeleted(object()))
return;
- QString url;
- quint16 lineNumber;
- quint16 columnNumber;
-
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
QV4::Scope scope(ep->v4engine());
QV4::ScopedFunctionObject f(scope, v4function.value());
Q_ASSERT(f);
- if (f->isBinding()) {
- Q_ASSERT(f->as<QV4::QQmlBindingFunction>());
- QQmlSourceLocation loc = static_cast<QV4::Heap::QQmlBindingFunction *>(f->d())->bindingLocation;
- url = loc.sourceFile;
- lineNumber = loc.line;
- columnNumber = loc.column;
- } else {
- QV4::Function *function = f->as<QV4::FunctionObject>()->function();
- Q_ASSERT(function);
-
- url = function->sourceFile();
- lineNumber = function->compiledFunction->location.line;
- columnNumber = function->compiledFunction->location.column;
- }
-
- int lineNo = qmlSourceCoordinate(lineNumber);
- int columnNo = qmlSourceCoordinate(columnNumber);
if (!updatingFlag()) {
- QQmlBindingProfiler prof(ep->profiler, url, lineNo, columnNo);
+ QQmlBindingProfiler prof(ep->profiler, f);
setUpdatingFlag(true);
QQmlAbstractExpression::DeleteWatcher watcher(this);
@@ -222,7 +201,7 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
if (!watcher.wasDeleted()) {
if (needsErrorLocationData)
- delayedError()->setErrorLocation(QUrl(url), lineNumber, columnNumber);
+ delayedError()->setErrorLocation(f->sourceLocation());
if (hasError()) {
if (!delayedError()->addError(ep)) ep->warning(this->error(context()->engine));
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index 1005d097d2..f08f650913 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -305,12 +305,10 @@ void QQmlContext::setContextProperty(const QString &name, const QVariant &value)
}
}
- if (data->propertyNames.isEmpty())
- data->propertyNames = QV4::IdentifierHash<int>(QV8Engine::getV4(engine()->handle()));
-
- int idx = data->propertyNames.value(name);
+ QV4::IdentifierHash<int> &properties = data->propertyNames();
+ int idx = properties.value(name);
if (idx == -1) {
- data->propertyNames.add(name, data->idValueCount + d->propertyValues.count());
+ properties.add(name, data->idValueCount + d->propertyValues.count());
d->propertyValues.append(value);
data->refreshExpressions();
@@ -343,12 +341,11 @@ void QQmlContext::setContextProperty(const QString &name, QObject *value)
return;
}
- if (data->propertyNames.isEmpty())
- data->propertyNames = QV4::IdentifierHash<int>(QV8Engine::getV4(engine()->handle()));
- int idx = data->propertyNames.value(name);
+ QV4::IdentifierHash<int> &properties = data->propertyNames();
+ int idx = properties.value(name);
if (idx == -1) {
- data->propertyNames.add(name, data->idValueCount + d->propertyValues.count());
+ properties.add(name, data->idValueCount + d->propertyValues.count());
d->propertyValues.append(QVariant::fromValue(value));
data->refreshExpressions();
@@ -370,8 +367,9 @@ QVariant QQmlContext::contextProperty(const QString &name) const
QQmlContextData *data = d->data;
- if (data->propertyNames.count())
- idx = data->propertyNames.value(name);
+ const QV4::IdentifierHash<int> &properties = data->propertyNames();
+ if (properties.count())
+ idx = properties.value(name);
if (idx == -1) {
if (data->contextObject) {
@@ -428,14 +426,14 @@ QUrl QQmlContextData::resolvedUrl(const QUrl &src)
if (src.isRelative() && !src.isEmpty()) {
if (ctxt) {
while(ctxt) {
- if(ctxt->url.isValid())
+ if (ctxt->url().isValid())
break;
else
ctxt = ctxt->parent;
}
if (ctxt)
- resolved = ctxt->url.resolved(src);
+ resolved = ctxt->url().resolved(src);
else if (engine)
resolved = engine->baseUrl().resolved(src);
}
@@ -464,8 +462,8 @@ void QQmlContext::setBaseUrl(const QUrl &baseUrl)
{
Q_D(QQmlContext);
- d->data->url = baseUrl;
- d->data->urlString = baseUrl.toString();
+ d->data->baseUrl = baseUrl;
+ d->data->baseUrlString = baseUrl.toString();
}
/*!
@@ -476,11 +474,11 @@ QUrl QQmlContext::baseUrl() const
{
Q_D(const QQmlContext);
const QQmlContextData* data = d->data;
- while (data && data->url.isEmpty())
+ while (data && data->url().isEmpty())
data = data->parent;
if (data)
- return data->url;
+ return data->url();
else
return QUrl();
}
@@ -762,33 +760,31 @@ void QQmlContextData::setIdProperty(int idx, QObject *obj)
idValues[idx].context = this;
}
-void QQmlContextData::setIdPropertyData(const QVector<ObjectIdMapping> &data)
+void QQmlContextData::setIdPropertyData(const QHash<int, int> &data)
{
- Q_ASSERT(propertyNames.isEmpty());
- propertyNames = QV4::IdentifierHash<int>(QV8Engine::getV4(engine->handle()));
- for (QVector<ObjectIdMapping>::ConstIterator it = data.begin(), end = data.end();
- it != end; ++it)
- propertyNames.add(it->name, it->id);
-
+ Q_ASSERT(objectIndexToId.isEmpty());
+ objectIndexToId = data;
+ Q_ASSERT(propertyNameCache.isEmpty());
idValueCount = data.count();
idValues = new ContextGuard[idValueCount];
}
QString QQmlContextData::findObjectId(const QObject *obj) const
{
- if (propertyNames.isEmpty())
+ const QV4::IdentifierHash<int> &properties = propertyNames();
+ if (propertyNameCache.isEmpty())
return QString();
for (int ii = 0; ii < idValueCount; ii++) {
if (idValues[ii] == obj)
- return propertyNames.findId(ii);
+ return properties.findId(ii);
}
if (publicContext) {
QQmlContextPrivate *p = QQmlContextPrivate::get(publicContext);
for (int ii = 0; ii < p->propertyValues.count(); ++ii)
if (p->propertyValues.at(ii) == QVariant::fromValue((QObject *)obj))
- return propertyNames.findId(ii);
+ return properties.findId(ii);
}
if (linkedContext)
@@ -808,4 +804,33 @@ QQmlContextPrivate *QQmlContextData::asQQmlContextPrivate()
return QQmlContextPrivate::get(asQQmlContext());
}
+QV4::IdentifierHash<int> &QQmlContextData::propertyNames() const
+{
+ if (propertyNameCache.isEmpty()) {
+ propertyNameCache = QV4::IdentifierHash<int>(QV8Engine::getV4(engine->handle()));
+ for (QHash<int, int>::ConstIterator it = objectIndexToId.begin(), end = objectIndexToId.end();
+ it != end; ++it) {
+ const QV4::CompiledData::Object *obj = typeCompilationUnit->data->objectAt(it.key());
+ const QString name = typeCompilationUnit->data->stringAt(obj->idIndex);
+ propertyNameCache.add(name, it.value());
+ }
+ objectIndexToId.clear();
+ }
+ return propertyNameCache;
+}
+
+QUrl QQmlContextData::url() const
+{
+ if (typeCompilationUnit)
+ return typeCompilationUnit->url();
+ return baseUrl;
+}
+
+QString QQmlContextData::urlString() const
+{
+ if (typeCompilationUnit)
+ return typeCompilationUnit->fileName();
+ return baseUrlString;
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h
index f0e0ab26c6..f5fd7d0a5c 100644
--- a/src/qml/qml/qqmlcontext_p.h
+++ b/src/qml/qml/qqmlcontext_p.h
@@ -144,8 +144,9 @@ public:
// Compilation unit for contexts that belong to a compiled type.
QQmlRefPointer<QV4::CompiledData::CompilationUnit> typeCompilationUnit;
- // Property name cache
- QV4::IdentifierHash<int> propertyNames;
+ mutable QHash<int, int> objectIndexToId;
+ mutable QV4::IdentifierHash<int> propertyNameCache;
+ QV4::IdentifierHash<int> &propertyNames() const;
// Context object
QObject *contextObject;
@@ -153,9 +154,11 @@ public:
// Any script blocks that exist on this context
QV4::PersistentValue importedScripts; // This is a JS Array
- // Context base url
- QUrl url;
- QString urlString;
+ QUrl baseUrl;
+ QString baseUrlString;
+
+ QUrl url() const;
+ QString urlString() const;
// List of imports that apply to this context
QQmlTypeNameCache *imports;
@@ -188,17 +191,10 @@ public:
QFlagPointer<QQmlContextData> context;
QQmlNotifier bindings;
};
- struct ObjectIdMapping {
- ObjectIdMapping() : id(-1) {}
- ObjectIdMapping(const QString &name, int id)
- : name(name), id(id) {}
- QString name;
- int id;
- };
ContextGuard *idValues;
int idValueCount;
void setIdProperty(int, QObject *);
- void setIdPropertyData(const QVector<ObjectIdMapping> &);
+ void setIdPropertyData(const QHash<int, int> &);
// Linked contexts. this owns linkedContext.
QQmlContextData *linkedContext;
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index 64ff6c390e..69071cd6c2 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -60,6 +60,7 @@ Heap::QmlContextWrapper::QmlContextWrapper(QV4::ExecutionEngine *engine, QQmlCon
, isNullWrapper(false)
, context(context)
, scopeObject(scopeObject)
+ , idObjectsWrapper(Q_NULLPTR)
{
}
@@ -82,7 +83,8 @@ ReturnedValue QmlContextWrapper::urlScope(ExecutionEngine *v4, const QUrl &url)
Scope scope(v4);
QQmlContextData *context = new QQmlContextData;
- context->url = url;
+ context->baseUrl = url;
+ context->baseUrlString = url.toString();
context->isInternal = true;
context->isJSContext = true;
@@ -199,8 +201,9 @@ ReturnedValue QmlContextWrapper::get(const Managed *m, String *name, bool *hasPr
while (context) {
// Search context properties
- if (context->propertyNames.count()) {
- int propertyIdx = context->propertyNames.value(name);
+ const QV4::IdentifierHash<int> &properties = context->propertyNames();
+ if (properties.count()) {
+ int propertyIdx = properties.value(name);
if (propertyIdx != -1) {
@@ -308,8 +311,9 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value)
QObject *scopeObject = wrapper->getScopeObject();
while (context) {
+ const QV4::IdentifierHash<int> &properties = context->propertyNames();
// Search context properties
- if (context->propertyNames.count() && -1 != context->propertyNames.value(name))
+ if (properties.count() && properties.value(name) != -1)
return;
// Search scope object
diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h
index 15ca126365..88282b1bbc 100644
--- a/src/qml/qml/qqmlcustomparser_p.h
+++ b/src/qml/qml/qqmlcustomparser_p.h
@@ -100,7 +100,7 @@ protected:
private:
QList<QQmlError> exceptions;
- QQmlCustomParserCompilerBackend *compiler;
+ const QQmlCustomParserCompilerBackend *compiler;
Flags m_flags;
QBiPointer<const QQmlImports, QQmlTypeNameCache> imports;
friend class QQmlPropertyValidator;
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 96fb2f1cdb..5bf8479e55 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -621,8 +621,14 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
for (TypePropertyCacheIt iter = typePropertyCache.begin(), end = typePropertyCache.end(); iter != end; ++iter)
(*iter)->release();
- for (CompositeTypesIt iter = m_compositeTypes.begin(), end = m_compositeTypes.end(); iter != end; ++iter)
+ for (CompositeTypesIt iter = m_compositeTypes.begin(), end = m_compositeTypes.end(); iter != end; ++iter) {
iter.value()->isRegisteredWithEngine = false;
+
+ // since unregisterInternalCompositeType() will not be called in this
+ // case, we have to clean up the type registration manually
+ QMetaType::unregisterType(iter.value()->metaTypeId);
+ QMetaType::unregisterType(iter.value()->listMetaTypeId);
+ }
delete profiler;
}
@@ -2337,6 +2343,9 @@ void QQmlEnginePrivate::unregisterInternalCompositeType(QQmlCompiledData *data)
Locker locker(this);
m_qmlLists.remove(lst_type);
m_compositeTypes.remove(ptr_type);
+
+ QMetaType::unregisterType(ptr_type);
+ QMetaType::unregisterType(lst_type);
}
bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index 18f882e1e0..35e0bc8c64 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -149,8 +149,8 @@ QQmlExpression::QQmlExpression(const QQmlScriptString &script, QQmlContext *ctxt
if (scriptPrivate->context) {
QQmlContextData *ctxtdata = QQmlContextData::get(scriptPrivate->context);
QQmlEnginePrivate *engine = QQmlEnginePrivate::get(scriptPrivate->context->engine());
- if (engine && ctxtdata && !ctxtdata->url.isEmpty() && ctxtdata->typeCompilationUnit) {
- d->url = ctxtdata->url.toString();
+ if (engine && ctxtdata && !ctxtdata->urlString().isEmpty() && ctxtdata->typeCompilationUnit) {
+ d->url = ctxtdata->urlString();
d->line = scriptPrivate->lineNumber;
d->column = scriptPrivate->columnNumber;
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 6a5cab02fd..906e073cab 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -1829,7 +1829,7 @@ bool QQmlImportDatabase::registerPluginTypes(QObject *instance, const QString &b
{
// Create a scope for QWriteLocker to keep it as narrow as possible, and
// to ensure that we release it before the call to initalizeEngine below
- QWriteLocker lock(QQmlMetaType::typeRegistrationLock());
+ QMutexLocker lock(QQmlMetaType::typeRegistrationLock());
if (!typeNamespace.isEmpty()) {
// This is an 'identified' module
diff --git a/src/qml/qml/qqmlinfo.cpp b/src/qml/qml/qqmlinfo.cpp
index 85979b8dc0..b9f96a724c 100644
--- a/src/qml/qml/qqmlinfo.cpp
+++ b/src/qml/qml/qqmlinfo.cpp
@@ -140,7 +140,7 @@ QQmlInfo::~QQmlInfo()
QQmlData *ddata = QQmlData::get(object, false);
if (ddata && ddata->outerContext) {
- error.setUrl(ddata->outerContext->url);
+ error.setUrl(ddata->outerContext->url());
error.setLine(ddata->lineNumber);
error.setColumn(ddata->columnNumber);
}
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 6411b569ee..6919042e0f 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -40,6 +40,7 @@
#include <private/qv4script_p.h>
#include <private/qv4errorobject_p.h>
#include <private/qv4scopedvalue_p.h>
+#include <private/qqmlglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -59,11 +60,11 @@ bool QQmlDelayedError::addError(QQmlEnginePrivate *e)
return true;
}
-void QQmlDelayedError::setErrorLocation(const QUrl &url, quint16 line, quint16 column)
+void QQmlDelayedError::setErrorLocation(const QQmlSourceLocation &sourceLocation)
{
- m_error.setUrl(url);
- m_error.setLine(line);
- m_error.setColumn(column);
+ m_error.setUrl(QUrl(sourceLocation.sourceFile));
+ m_error.setLine(sourceLocation.line);
+ m_error.setColumn(sourceLocation.column);
}
void QQmlDelayedError::setErrorDescription(const QString &description)
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index 3f1a8c173d..989d5a0b0d 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -52,6 +52,8 @@
QT_BEGIN_NAMESPACE
+struct QQmlSourceLocation;
+
class QQmlDelayedError
{
public:
@@ -72,7 +74,7 @@ public:
inline const QQmlError &error() const { return m_error; }
inline void clearError() { m_error = QQmlError(); }
- void setErrorLocation(const QUrl &url, quint16 line, quint16 column);
+ void setErrorLocation(const QQmlSourceLocation &sourceLocation);
void setErrorDescription(const QString &description);
void setErrorObject(QObject *object);
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 9779773b05..2f7834fa41 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -127,7 +127,7 @@ public:
};
Q_GLOBAL_STATIC(QQmlMetaTypeData, metaTypeData)
-Q_GLOBAL_STATIC_WITH_ARGS(QReadWriteLock, metaTypeDataLock, (QReadWriteLock::Recursive))
+Q_GLOBAL_STATIC_WITH_ARGS(QMutex, metaTypeDataLock, (QMutex::Recursive))
static uint qHash(const QQmlMetaTypeData::VersionedUri &v)
{
@@ -565,7 +565,7 @@ void QQmlTypePrivate::init() const
if (isSetup)
return;
- QWriteLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
if (isSetup)
return;
@@ -646,7 +646,7 @@ void QQmlTypePrivate::initEnums() const
init();
- QWriteLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
if (isEnumSetup) return;
if (baseMetaObject) // could be singleton type without metaobject
@@ -1000,7 +1000,7 @@ void QQmlTypeModulePrivate::add(QQmlType *type)
QQmlType *QQmlTypeModule::type(const QHashedStringRef &name, int minor)
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QList<QQmlType *> *types = d->typeHash.value(name);
if (!types) return 0;
@@ -1014,7 +1014,7 @@ QQmlType *QQmlTypeModule::type(const QHashedStringRef &name, int minor)
QQmlType *QQmlTypeModule::type(const QV4::String *name, int minor)
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QList<QQmlType *> *types = d->typeHash.value(name);
if (!types) return 0;
@@ -1028,7 +1028,7 @@ QQmlType *QQmlTypeModule::type(const QV4::String *name, int minor)
QList<QQmlType*> QQmlTypeModule::singletonTypes(int minor) const
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QList<QQmlType *> retn;
for (int ii = 0; ii < d->types.count(); ++ii) {
@@ -1089,7 +1089,7 @@ QQmlType *QQmlTypeModuleVersion::type(const QV4::String *name) const
void qmlClearTypeRegistrations() // Declared in qqml.h
{
//Only cleans global static, assumed no running engine
- QWriteLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
for (int i = 0; i < data->types.count(); ++i)
@@ -1112,7 +1112,7 @@ void qmlClearTypeRegistrations() // Declared in qqml.h
int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent)
{
- QWriteLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
data->parentFunctions.append(autoparent.function);
@@ -1125,7 +1125,7 @@ int registerInterface(const QQmlPrivate::RegisterInterface &interface)
if (interface.version > 0)
qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
- QWriteLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
int index = data->types.count();
@@ -1163,7 +1163,7 @@ QString registrationTypeString(QQmlType::RegistrationType typeType)
return typeStr;
}
-// NOTE: caller must hold a QWriteLocker on "data"
+// NOTE: caller must hold a QMutexLocker on "data"
bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *data, const char *uri, const QString &typeName, int majorVersion = -1)
{
if (!typeName.isEmpty()) {
@@ -1214,7 +1214,7 @@ bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *da
return true;
}
-// NOTE: caller must hold a QWriteLocker on "data"
+// NOTE: caller must hold a QMutexLocker on "data"
void addTypeToData(QQmlType* type, QQmlMetaTypeData *data)
{
if (!type->elementName().isEmpty())
@@ -1253,7 +1253,7 @@ void addTypeToData(QQmlType* type, QQmlMetaTypeData *data)
int registerType(const QQmlPrivate::RegisterType &type)
{
- QWriteLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QString elementName = QString::fromUtf8(type.elementName);
if (!checkRegistration(QQmlType::CppType, data, type.uri, elementName, type.versionMajor))
@@ -1273,7 +1273,7 @@ int registerType(const QQmlPrivate::RegisterType &type)
int registerSingletonType(const QQmlPrivate::RegisterSingletonType &type)
{
- QWriteLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QString typeName = QString::fromUtf8(type.typeName);
if (!checkRegistration(QQmlType::SingletonType, data, type.uri, typeName, type.versionMajor))
@@ -1292,7 +1292,7 @@ int registerSingletonType(const QQmlPrivate::RegisterSingletonType &type)
int registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type)
{
// Assumes URL is absolute and valid. Checking of user input should happen before the URL enters type.
- QWriteLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QString typeName = QString::fromUtf8(type.typeName);
bool fileImport = false;
@@ -1317,7 +1317,7 @@ int registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingleton
int registerCompositeType(const QQmlPrivate::RegisterCompositeType &type)
{
// Assumes URL is absolute and valid. Checking of user input should happen before the URL enters type.
- QWriteLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QString typeName = QString::fromUtf8(type.typeName);
bool fileImport = false;
@@ -1342,7 +1342,7 @@ int registerQmlUnitCacheHook(const QQmlPrivate::RegisterQmlUnitCacheHook &hookRe
{
if (hookRegistration.version > 0)
qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
- QWriteLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
data->lookupCachedQmlUnit << hookRegistration.lookupCachedQmlUnit;
return 0;
@@ -1375,7 +1375,7 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data)
//From qqml.h
bool qmlProtectModule(const char *uri, int majVersion)
{
- QWriteLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QQmlMetaTypeData::VersionedUri versionedUri;
@@ -1424,7 +1424,7 @@ QStringList QQmlMetaType::typeRegistrationFailures()
return data->typeRegistrationFailures;
}
-QReadWriteLock *QQmlMetaType::typeRegistrationLock()
+QMutex *QQmlMetaType::typeRegistrationLock()
{
return metaTypeDataLock();
}
@@ -1434,7 +1434,7 @@ QReadWriteLock *QQmlMetaType::typeRegistrationLock()
*/
bool QQmlMetaType::isAnyModule(const QString &uri)
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
for (QQmlMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin();
@@ -1451,7 +1451,7 @@ bool QQmlMetaType::isAnyModule(const QString &uri)
*/
bool QQmlMetaType::isLockedModule(const QString &uri, int majVersion)
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QQmlMetaTypeData::VersionedUri versionedUri;
@@ -1472,7 +1472,7 @@ bool QQmlMetaType::isLockedModule(const QString &uri, int majVersion)
bool QQmlMetaType::isModule(const QString &module, int versionMajor, int versionMinor)
{
Q_ASSERT(versionMajor >= 0 && versionMinor >= 0);
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
@@ -1487,14 +1487,14 @@ bool QQmlMetaType::isModule(const QString &module, int versionMajor, int version
QQmlTypeModule *QQmlMetaType::typeModule(const QString &uri, int majorVersion)
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
return data->uriToModule.value(QQmlMetaTypeData::VersionedUri(uri, majorVersion));
}
QList<QQmlPrivate::AutoParentFunction> QQmlMetaType::parentFunctions()
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
return data->parentFunctions;
}
@@ -1516,7 +1516,7 @@ bool QQmlMetaType::isQObject(int userType)
if (userType == QMetaType::QObjectStar)
return true;
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType);
}
@@ -1526,7 +1526,7 @@ bool QQmlMetaType::isQObject(int userType)
*/
int QQmlMetaType::listType(int id)
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QQmlType *type = data->idToType.value(id);
if (type && type->qListTypeId() == id)
@@ -1537,7 +1537,7 @@ int QQmlMetaType::listType(int id)
int QQmlMetaType::attachedPropertiesFuncId(const QMetaObject *mo)
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QQmlType *type = data->metaObjectToType.value(mo);
@@ -1551,7 +1551,7 @@ QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFuncById(int id)
{
if (id < 0)
return 0;
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
return data->types.at(id)->attachedPropertiesFunction();
}
@@ -1615,7 +1615,7 @@ QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType)
if (userType == QMetaType::QObjectStar)
return Object;
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
if (userType < data->objects.size() && data->objects.testBit(userType))
return Object;
@@ -1627,14 +1627,14 @@ QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType)
bool QQmlMetaType::isInterface(int userType)
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType);
}
const char *QQmlMetaType::interfaceIId(int userType)
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QQmlType *type = data->idToType.value(userType);
lock.unlock();
@@ -1646,7 +1646,7 @@ const char *QQmlMetaType::interfaceIId(int userType)
bool QQmlMetaType::isList(int userType)
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType);
}
@@ -1668,7 +1668,7 @@ bool QQmlMetaType::isList(int userType)
*/
void QQmlMetaType::registerCustomStringConverter(int type, StringConverter converter)
{
- QWriteLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
if (data->stringConverters.contains(type))
@@ -1682,7 +1682,7 @@ void QQmlMetaType::registerCustomStringConverter(int type, StringConverter conve
*/
QQmlMetaType::StringConverter QQmlMetaType::customStringConverter(int type)
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
return data->stringConverters.value(type);
@@ -1711,7 +1711,7 @@ QQmlType *QQmlMetaType::qmlType(const QString &qualifiedName, int version_major,
QQmlType *QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int version_major, int version_minor)
{
Q_ASSERT(version_major >= 0 && version_minor >= 0);
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.constFind(name);
@@ -1731,7 +1731,7 @@ QQmlType *QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStrin
*/
QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject)
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
return data->metaObjectToType.value(metaObject);
@@ -1745,7 +1745,7 @@ QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject)
QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor)
{
Q_ASSERT(version_major >= 0 && version_minor >= 0);
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.constFind(metaObject);
@@ -1765,7 +1765,7 @@ QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStri
*/
QQmlType *QQmlMetaType::qmlType(int userType)
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QQmlType *type = data->idToType.value(userType);
@@ -1783,7 +1783,7 @@ QQmlType *QQmlMetaType::qmlType(int userType)
*/
QQmlType *QQmlMetaType::qmlType(const QUrl &url, bool includeNonFileImports /* = false */)
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QQmlType *type = data->urlToType.value(url);
@@ -1803,7 +1803,7 @@ QQmlType *QQmlMetaType::qmlType(const QUrl &url, bool includeNonFileImports /* =
*/
QQmlType *QQmlMetaType::qmlTypeFromIndex(int idx)
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
if (idx < 0 || idx >= data->types.count())
@@ -1816,7 +1816,7 @@ QQmlType *QQmlMetaType::qmlTypeFromIndex(int idx)
*/
QList<QString> QQmlMetaType::qmlTypeNames()
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QList<QString> names;
@@ -1834,7 +1834,7 @@ QList<QString> QQmlMetaType::qmlTypeNames()
*/
QList<QQmlType*> QQmlMetaType::qmlTypes()
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
return data->nameToType.values();
@@ -1845,7 +1845,7 @@ QList<QQmlType*> QQmlMetaType::qmlTypes()
*/
QList<QQmlType*> QQmlMetaType::qmlAllTypes()
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
return data->types;
@@ -1856,7 +1856,7 @@ QList<QQmlType*> QQmlMetaType::qmlAllTypes()
*/
QList<QQmlType*> QQmlMetaType::qmlSingletonTypes()
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QList<QQmlType*> alltypes = data->nameToType.values();
@@ -1872,7 +1872,7 @@ QList<QQmlType*> QQmlMetaType::qmlSingletonTypes()
const QQmlPrivate::CachedQmlUnit *QQmlMetaType::findCachedCompilationUnit(const QUrl &uri)
{
- QReadLocker lock(metaTypeDataLock());
+ QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
for (QVector<QQmlPrivate::QmlUnitCacheLookupFunction>::ConstIterator it = data->lookupCachedQmlUnit.constBegin(), end = data->lookupCachedQmlUnit.constEnd();
it != end; ++it) {
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 63e6e3bec8..e5ac20d314 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -62,7 +62,7 @@ class QQmlTypePrivate;
class QQmlTypeModule;
class QHashedString;
class QHashedStringRef;
-class QReadWriteLock;
+class QMutex;
namespace QV4 { struct String; }
@@ -121,7 +121,7 @@ public:
static void setTypeRegistrationNamespace(const QString &);
static QStringList typeRegistrationFailures();
- static QReadWriteLock *typeRegistrationLock();
+ static QMutex *typeRegistrationLock();
};
struct QQmlMetaTypeData;
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 9abd1859b7..3c2f3690b9 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -113,6 +113,7 @@ void QQmlObjectCreator::init(QQmlContextData *providedParentContext)
{
parentContext = providedParentContext;
engine = parentContext->engine;
+ v4 = QV8Engine::getV4(engine);
if (!compiledData->isInitialized())
compiledData->initialize(engine);
@@ -123,10 +124,11 @@ void QQmlObjectCreator::init(QQmlContextData *providedParentContext)
_scopeObject = 0;
_valueTypeProperty = 0;
_compiledObject = 0;
+ _compiledObjectIndex = -1;
_ddata = 0;
_propertyCache = 0;
_vmeMetaObject = 0;
- _qmlContext = 0;
+ _qmlBindingWrapper = 0;
}
QQmlObjectCreator::~QQmlObjectCreator()
@@ -174,8 +176,6 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
context = new QQmlContextData;
context->isInternal = true;
- context->url = compiledData->url();
- context->urlString = compiledData->fileName();
context->imports = compiledData->importCache;
context->imports->addref();
context->typeCompilationUnit = compiledData->compilationUnit;
@@ -187,26 +187,15 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
sharedState->rootContext->isRootObjectInCreation = true;
}
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
Q_ASSERT(sharedState->allJavaScriptObjects || topLevelCreator);
if (topLevelCreator)
sharedState->allJavaScriptObjects = scope.alloc(compiledData->totalObjectCount);
- QVector<QQmlContextData::ObjectIdMapping> mapping(objectIndexToId.count());
- for (QHash<int, int>::ConstIterator it = objectIndexToId.constBegin(), end = objectIndexToId.constEnd();
- it != end; ++it) {
- const QV4::CompiledData::Object *obj = qmlUnit->objectAt(it.key());
+ context->setIdPropertyData(objectIndexToId);
- QQmlContextData::ObjectIdMapping m;
- m.id = it.value();
- m.name = stringAt(obj->idIndex);
- mapping[m.id] = m;
- }
- context->setIdPropertyData(mapping);
-
- if (subComponentIndex == -1) {
+ if (subComponentIndex == -1 && compiledData->scripts.count()) {
QV4::ScopedObject scripts(scope, v4->newArrayObject(compiledData->scripts.count()));
context->importedScripts.set(v4, scripts);
for (int i = 0; i < compiledData->scripts.count(); ++i) {
@@ -245,9 +234,7 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
QQmlData *declarativeData = QQmlData::get(instance);
context = declarativeData->deferredData->context;
sharedState->rootContext = context;
- const int objectIndex = declarativeData->deferredData->deferredIdx;
- const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
QObject *bindingTarget = instance;
QQmlRefPointer<QQmlPropertyCache> cache = declarativeData->propertyCache;
@@ -256,29 +243,30 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
QObject *scopeObject = instance;
qSwap(_scopeObject, scopeObject);
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope valueScope(v4);
Q_ASSERT(topLevelCreator);
Q_ASSERT(!sharedState->allJavaScriptObjects);
sharedState->allJavaScriptObjects = valueScope.alloc(compiledData->totalObjectCount);
- QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(v4, context, _scopeObject));
- QV4::ScopedContext global(valueScope, valueScope.engine->rootContext());
- QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, v4->memoryManager->alloc<QV4::QmlBindingWrapper>(global, qmlScope));
- // ### GC
- QV4::ExecutionContext *qmlContext = QV4::ScopedContext(valueScope, qmlBindingWrapper->context());
+ QV4::Value *qmlBindingWrapper = valueScope.alloc(1);
- qSwap(_qmlContext, qmlContext);
+ qSwap(_qmlBindingWrapper, qmlBindingWrapper);
qSwap(_propertyCache, cache);
qSwap(_qobject, instance);
+
+ int objectIndex = declarativeData->deferredData->deferredIdx;
+ qSwap(_compiledObjectIndex, objectIndex);
+
+ const QV4::CompiledData::Object *obj = qmlUnit->objectAt(_compiledObjectIndex);
qSwap(_compiledObject, obj);
+
qSwap(_ddata, declarativeData);
qSwap(_bindingTarget, bindingTarget);
qSwap(_vmeMetaObject, vmeMetaObject);
- QBitArray bindingSkipList = compiledData->deferredBindingsPerObject.value(objectIndex);
+ QBitArray bindingSkipList = compiledData->deferredBindingsPerObject.value(_compiledObjectIndex);
for (int i = 0; i < bindingSkipList.count(); ++i)
bindingSkipList.setBit(i, !bindingSkipList.testBit(i));
@@ -288,10 +276,11 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
qSwap(_bindingTarget, bindingTarget);
qSwap(_ddata, declarativeData);
qSwap(_compiledObject, obj);
+ qSwap(_compiledObjectIndex, objectIndex);
qSwap(_qobject, instance);
qSwap(_propertyCache, cache);
- qSwap(_qmlContext, qmlContext);
+ qSwap(_qmlBindingWrapper, qmlBindingWrapper);
qSwap(_scopeObject, scopeObject);
phase = ObjectsCreated;
@@ -299,14 +288,13 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
return errors.isEmpty();
}
-void QQmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
+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 };
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
int propertyType = property->propType;
@@ -654,13 +642,12 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
QQmlListProperty<void> savedList;
qSwap(_currentList, savedList);
- QQmlPropertyData *property = 0;
- QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultProperty != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
+ const QV4::CompiledData::BindingPropertyData &propertyData = compiledData->compilationUnit->bindingPropertyDataPerObject.at(_compiledObjectIndex);
- QString id = stringAt(_compiledObject->idIndex);
- if (!id.isEmpty()) {
- QQmlPropertyData *idProperty = _propertyCache->property(QStringLiteral("id"), _qobject, context);
- if (idProperty && idProperty->isWritable() && idProperty->propType == QMetaType::QString) {
+ if (_compiledObject->idIndex) {
+ const QQmlPropertyData *idProperty = propertyData.last();
+ Q_ASSERT(!idProperty || !idProperty->isValid() || idProperty->name(_qobject) == QStringLiteral("id"));
+ if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType == QMetaType::QString) {
QV4::CompiledData::Binding idBinding;
idBinding.propertyNameIndex = 0; // Not used
idBinding.flags = 0;
@@ -686,50 +673,40 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
if (qmlTypeForObject(_bindingTarget)) {
quint32 bindingSkipList = 0;
+ QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultProperty != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
+
const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
- property = binding->propertyNameIndex != 0 ? _propertyCache->property(stringAt(binding->propertyNameIndex), _qobject, context) : defaultProperty;
+ QQmlPropertyData *property = binding->propertyNameIndex != 0 ? _propertyCache->property(stringAt(binding->propertyNameIndex), _qobject, context) : defaultProperty;
if (property)
bindingSkipList |= (1 << property->coreIndex);
}
- property = 0;
proxy->removeBindings(bindingSkipList);
}
}
}
+ int currentListPropertyIndex = -1;
+
const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
+ if (static_cast<int>(i) < bindingsToSkip.size() && bindingsToSkip.testBit(i))
+ continue;
- QString name = stringAt(binding->propertyNameIndex);
- if (name.isEmpty())
- property = 0;
-
- if (!property
- || (i > 0 && ((binding - 1)->propertyNameIndex != binding->propertyNameIndex
- || (binding - 1)->flags != binding->flags))
- ) {
- if (!name.isEmpty()) {
- if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
- || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
- property = QmlIR::PropertyResolver(_propertyCache).signal(name, /*notInRevision*/0, _qobject, context);
- else
- property = _propertyCache->property(name, _qobject, context);
- } else
- property = defaultProperty;
-
- if (property && property->isQList()) {
+ const QQmlPropertyData *property = propertyData.at(i);
+
+ if (property && property->isQList()) {
+ if (property->coreIndex != currentListPropertyIndex) {
void *argv[1] = { (void*)&_currentList };
QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex, argv);
- } else if (_currentList.object)
- _currentList = QQmlListProperty<void>();
-
+ currentListPropertyIndex = property->coreIndex;
+ }
+ } else if (_currentList.object) {
+ _currentList = QQmlListProperty<void>();
+ currentListPropertyIndex = -1;
}
- if (static_cast<int>(i) < bindingsToSkip.size() && bindingsToSkip.testBit(i))
- continue;
-
if (!setPropertyBinding(property, binding))
return;
}
@@ -737,7 +714,7 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
qSwap(_currentList, savedList);
}
-bool QQmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
+bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
{
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
Q_ASSERT(stringAt(qmlUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty());
@@ -785,7 +762,7 @@ bool QQmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4
QObject *groupObject = 0;
QQmlValueType *valueType = 0;
- QQmlPropertyData *valueTypeProperty = 0;
+ const QQmlPropertyData *valueTypeProperty = 0;
QObject *bindingTarget = _bindingTarget;
if (QQmlValueTypeFactory::isValueType(property->propType)) {
@@ -828,8 +805,9 @@ bool QQmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4
if (binding->type == QV4::CompiledData::Binding::Type_Script) {
QV4::Function *runtimeFunction = compiledData->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
- QV4::Scope scope(_qmlContext);
- QV4::ScopedFunctionObject function(scope, QV4::FunctionObject::createScriptFunction(_qmlContext, runtimeFunction, /*createProto*/ false));
+ QV4::Scope scope(v4);
+ QV4::ScopedContext qmlContext(scope, currentQmlContext());
+ QV4::ScopedFunctionObject function(scope, QV4::FunctionObject::createScriptFunction(qmlContext, runtimeFunction, /*createProto*/ false));
if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) {
int signalIndex = _propertyCache->methodIndexToSignalIndex(property->coreIndex);
@@ -948,7 +926,6 @@ bool QQmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4
}
} else if (property->propType == QMetaType::QVariant) {
if (property->isVarProperty()) {
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
QV4::ScopedValue wrappedObject(scope, QV4::QObjectWrapper::wrap(QV8Engine::getV4(engine), createdSubObject));
_vmeMetaObject->setVMEProperty(property->coreIndex, wrappedObject);
@@ -995,8 +972,9 @@ bool QQmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4
void QQmlObjectCreator::setupFunctions()
{
- QV4::Scope scope(_qmlContext);
+ QV4::Scope scope(v4);
QV4::ScopedValue function(scope);
+ QV4::ScopedContext qmlContext(scope, currentQmlContext());
const quint32 *functionIdx = _compiledObject->functionOffsetTable();
for (quint32 i = 0; i < _compiledObject->nFunctions; ++i, ++functionIdx) {
@@ -1007,7 +985,7 @@ void QQmlObjectCreator::setupFunctions()
if (!property->isVMEFunction())
continue;
- function = QV4::FunctionObject::createScriptFunction(_qmlContext, runtimeFunction);
+ function = QV4::FunctionObject::createScriptFunction(qmlContext, runtimeFunction);
_vmeMetaObject->setVmeMethod(property->coreIndex, function);
}
}
@@ -1029,6 +1007,17 @@ void QQmlObjectCreator::registerObjectWithContextById(int objectIndex, QObject *
context->setIdProperty(idEntry.value(), instance);
}
+QV4::Heap::ExecutionContext *QQmlObjectCreator::currentQmlContext()
+{
+ if (!_qmlBindingWrapper->objectValue()) {
+ QV4::Scope valueScope(v4);
+ QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(v4, context, _scopeObject));
+ QV4::ScopedContext global(valueScope, v4->rootContext());
+ *_qmlBindingWrapper = v4->memoryManager->alloc<QV4::QmlBindingWrapper>(global, qmlScope);
+ }
+ return static_cast<QV4::QmlBindingWrapper*>(_qmlBindingWrapper->objectValue())->context();
+}
+
QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject)
{
QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler);
@@ -1046,7 +1035,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
isComponent = true;
QQmlComponent *component = new QQmlComponent(engine, compiledData, index, parent);
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(QStringLiteral("<component>"),
- context->url, obj->location.line, obj->location.column));
+ context->url(), obj->location.line, obj->location.column));
QQmlComponentPrivate::get(component)->creationContext = context;
instance = component;
ddata = QQmlData::get(instance, /*create*/true);
@@ -1057,7 +1046,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
QQmlType *type = typeRef->type;
if (type) {
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(type->qmlTypeName(),
- context->url, obj->location.line, obj->location.column));
+ context->url(), obj->location.line, obj->location.column));
instance = type->create();
if (!instance) {
recordError(obj->location, tr("Unable to create object of type %1").arg(stringAt(obj->inheritedTypeNameIndex)));
@@ -1080,7 +1069,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
} else {
Q_ASSERT(typeRef->component);
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(typeRef->component->fileName(),
- context->url, obj->location.line, obj->location.column));
+ context->url(), obj->location.line, obj->location.column));
if (typeRef->component->compilationUnit->data->isSingleton())
{
recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex)));
@@ -1168,24 +1157,18 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
QObject *scopeObject = instance;
qSwap(_scopeObject, scopeObject);
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
-
Q_ASSERT(sharedState->allJavaScriptObjects);
*sharedState->allJavaScriptObjects = QV4::QObjectWrapper::wrap(v4, instance);
++sharedState->allJavaScriptObjects;
QV4::Scope valueScope(v4);
- QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(v4, context, _scopeObject));
- QV4::ScopedContext global(valueScope, valueScope.engine->rootContext());
- QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, v4->memoryManager->alloc<QV4::QmlBindingWrapper>(global, qmlScope));
- // ### GC
- QV4::ExecutionContext *qmlContext = QV4::ScopedContext(valueScope, qmlBindingWrapper->context());
+ QV4::Value *qmlBindingWrapper = valueScope.alloc(1);
- qSwap(_qmlContext, qmlContext);
+ qSwap(_qmlBindingWrapper, qmlBindingWrapper);
bool result = populateInstance(index, instance, /*binding target*/instance, /*value type property*/0, bindingsToSkip);
- qSwap(_qmlContext, qmlContext);
+ qSwap(_qmlBindingWrapper, qmlBindingWrapper);
qSwap(_scopeObject, scopeObject);
return result ? instance : 0;
@@ -1277,26 +1260,25 @@ void QQmlObjectCreator::clear()
phase = Done;
}
-bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *bindingTarget, QQmlPropertyData *valueTypeProperty, const QBitArray &bindingsToSkip)
+bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *bindingTarget, const QQmlPropertyData *valueTypeProperty, const QBitArray &bindingsToSkip)
{
- const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
-
QQmlData *declarativeData = QQmlData::get(instance, /*create*/true);
qSwap(_qobject, instance);
qSwap(_valueTypeProperty, valueTypeProperty);
+ qSwap(_compiledObjectIndex, index);
+ const QV4::CompiledData::Object *obj = qmlUnit->objectAt(_compiledObjectIndex);
qSwap(_compiledObject, obj);
qSwap(_ddata, declarativeData);
qSwap(_bindingTarget, bindingTarget);
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope valueScope(v4);
QV4::ScopedValue scopeObjectProtector(valueScope);
- QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches.at(index);
+ QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches.at(_compiledObjectIndex);
QQmlVMEMetaObject *vmeMetaObject = 0;
- const QByteArray data = vmeMetaObjectData.value(index);
+ const QByteArray data = vmeMetaObjectData.value(_compiledObjectIndex);
if (!data.isEmpty()) {
Q_ASSERT(!cache.isNull());
// install on _object
@@ -1310,14 +1292,14 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
vmeMetaObject = QQmlVMEMetaObject::get(_qobject);
}
- registerObjectWithContextById(index, _qobject);
+ registerObjectWithContextById(_compiledObjectIndex, _qobject);
qSwap(_propertyCache, cache);
qSwap(_vmeMetaObject, vmeMetaObject);
QBitArray bindingSkipList = bindingsToSkip;
{
- QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.find(index);
+ QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.find(_compiledObjectIndex);
if (deferredBindings != compiledData->deferredBindingsPerObject.constEnd()) {
if (bindingSkipList.isEmpty())
bindingSkipList.resize(deferredBindings->count());
@@ -1326,7 +1308,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
if (deferredBindings->testBit(i))
bindingSkipList.setBit(i);
QQmlData::DeferredData *deferData = new QQmlData::DeferredData;
- deferData->deferredIdx = index;
+ deferData->deferredIdx = _compiledObjectIndex;
deferData->compiledData = compiledData;
deferData->compiledData->addref();
deferData->context = context;
@@ -1334,13 +1316,15 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
}
}
- setupFunctions();
+ if (_compiledObject->nFunctions > 0)
+ setupFunctions();
setupBindings(bindingSkipList);
qSwap(_vmeMetaObject, vmeMetaObject);
qSwap(_bindingTarget, bindingTarget);
qSwap(_ddata, declarativeData);
qSwap(_compiledObject, obj);
+ qSwap(_compiledObjectIndex, index);
qSwap(_valueTypeProperty, valueTypeProperty);
qSwap(_qobject, instance);
qSwap(_propertyCache, cache);
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 3886155786..60fefe494f 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -94,12 +94,12 @@ private:
QObject *createInstance(int index, QObject *parent = 0, bool isContextObject = false);
bool populateInstance(int index, QObject *instance,
- QObject *bindingTarget, QQmlPropertyData *valueTypeProperty,
+ QObject *bindingTarget, const QQmlPropertyData *valueTypeProperty,
const QBitArray &bindingsToSkip = QBitArray());
void setupBindings(const QBitArray &bindingsToSkip);
- bool setPropertyBinding(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
- void setPropertyValue(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
+ bool setPropertyBinding(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
+ void setPropertyValue(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
void setupFunctions();
QString stringAt(int idx) const { return qmlUnit->stringAt(idx); }
@@ -107,6 +107,8 @@ private:
void registerObjectWithContextById(int objectIndex, QObject *instance) const;
+ QV4::Heap::ExecutionContext *currentQmlContext();
+
enum Phase {
Startup,
CreatingObjects,
@@ -117,6 +119,7 @@ private:
} phase;
QQmlEngine *engine;
+ QV4::ExecutionEngine *v4;
QQmlCompiledData *compiledData;
const QV4::CompiledData::Unit *qmlUnit;
QQmlGuardedContextData parentContext;
@@ -133,13 +136,14 @@ private:
QObject *_scopeObject;
QObject *_bindingTarget;
- QQmlPropertyData *_valueTypeProperty; // belongs to _qobjectForBindings's property cache
+ const QQmlPropertyData *_valueTypeProperty; // belongs to _qobjectForBindings's property cache
+ int _compiledObjectIndex;
const QV4::CompiledData::Object *_compiledObject;
QQmlData *_ddata;
QQmlRefPointer<QQmlPropertyCache> _propertyCache;
QQmlVMEMetaObject *_vmeMetaObject;
QQmlListProperty<void> _currentList;
- QV4::ExecutionContext *_qmlContext;
+ QV4::Value *_qmlBindingWrapper;
friend struct QQmlObjectCreatorRecursionWatcher;
};
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index aef2bf0420..1036d68713 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -53,6 +53,7 @@
#include <QStringList>
#include <private/qmetaobject_p.h>
+#include <private/qqmlvaluetypewrapper_p.h>
#include <QtCore/qdebug.h>
Q_DECLARE_METATYPE(QList<int>)
@@ -1519,6 +1520,11 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
QUICK_STORE(QString, result.toQStringNoThrow())
break;
default:
+ if (const QV4::QQmlValueTypeWrapper *vtw = result.as<const QV4::QQmlValueTypeWrapper>()) {
+ if (vtw->d()->valueType->typeId == core.propType) {
+ return vtw->write(object, core.coreIndex);
+ }
+ }
break;
}
}
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 0bf8043cdb..d713e9ee03 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2478,8 +2478,8 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare
ctxt->isPragmaLibraryContext = true;
else
ctxt->isPragmaLibraryContext = parentCtxt->isPragmaLibraryContext;
- ctxt->url = url;
- ctxt->urlString = urlString;
+ ctxt->baseUrl = url;
+ ctxt->baseUrlString = urlString;
// For backward compatibility, if there are no imports, we need to use the
// imports from the parent context. See QTBUG-17518.
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 3b8a17960e..3d22b0b38f 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -51,6 +51,9 @@ DEFINE_OBJECT_VTABLE(QmlTypeWrapper);
Heap::QmlTypeWrapper::QmlTypeWrapper(ExecutionEngine *engine)
: Heap::Object(engine)
, mode(IncludeEnums)
+ , type(Q_NULLPTR)
+ , typeNamespace(Q_NULLPTR)
+ , importNamespace(Q_NULLPTR)
{
}
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 490ac66f1f..341ddf802d 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -38,6 +38,7 @@
#include <QtCore/qdebug.h>
#include <private/qmetaobjectbuilder_p.h>
#include <private/qqmlmodelindexvaluetype_p.h>
+#include <private/qmetatype_p.h>
QT_BEGIN_NAMESPACE
@@ -182,8 +183,9 @@ void QQmlValueTypeFactory::registerValueTypes(const char *uri, int versionMajor,
}
QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject)
- : typeId(typeId)
- , gadgetPtr(QMetaType::create(typeId))
+ : gadgetPtr(QMetaType::create(typeId))
+ , typeId(typeId)
+ , metaType(typeId)
{
QObjectPrivate *op = QObjectPrivate::get(this);
Q_ASSERT(!op->metaObject);
@@ -201,7 +203,7 @@ QQmlValueType::~QQmlValueType()
Q_ASSERT(op->metaObject == this);
op->metaObject = 0;
::free((void*)_metaObject);
- QMetaType::destroy(typeId, gadgetPtr);
+ metaType.destroy(gadgetPtr);
}
void QQmlValueType::read(QObject *obj, int idx)
@@ -227,8 +229,8 @@ QVariant QQmlValueType::value()
void QQmlValueType::setValue(const QVariant &value)
{
Q_ASSERT(typeId == value.userType());
- QMetaType::destruct(typeId, gadgetPtr);
- QMetaType::construct(typeId, gadgetPtr, value.constData());
+ metaType.destruct(gadgetPtr);
+ metaType.construct(gadgetPtr, value.constData());
}
QAbstractDynamicMetaObject *QQmlValueType::toDynamicMetaObject(QObject *)
diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h
index f534fedf5d..be453ae35a 100644
--- a/src/qml/qml/qqmlvaluetype_p.h
+++ b/src/qml/qml/qqmlvaluetype_p.h
@@ -75,8 +75,11 @@ public:
private:
const QMetaObject *_metaObject;
- int typeId;
void *gadgetPtr;
+
+public:
+ int typeId;
+ QMetaType metaType;
};
class Q_QML_PRIVATE_EXPORT QQmlValueTypeFactory
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 0f48c91737..77d76e89c8 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -79,27 +79,31 @@ using namespace QV4;
Heap::QQmlValueTypeWrapper::QQmlValueTypeWrapper(ExecutionEngine *engine)
: Heap::Object(engine)
- , gadgetPtr(0)
{
}
Heap::QQmlValueTypeWrapper::~QQmlValueTypeWrapper()
{
- if (gadgetPtr)
- QMetaType::destroy(metaType, gadgetPtr);
+ if (gadgetPtr) {
+ valueType->metaType.destruct(gadgetPtr);
+ ::operator delete(gadgetPtr);
+ }
}
void Heap::QQmlValueTypeWrapper::setValue(const QVariant &value) const
{
- Q_ASSERT(metaType == value.userType());
- QMetaType::destruct(metaType, gadgetPtr);
- QMetaType::construct(metaType, gadgetPtr, value.constData());
+ Q_ASSERT(valueType->typeId == value.userType());
+ if (gadgetPtr)
+ valueType->metaType.destruct(gadgetPtr);
+ if (!gadgetPtr)
+ gadgetPtr = ::operator new(valueType->metaType.sizeOf());
+ valueType->metaType.construct(gadgetPtr, value.constData());
}
QVariant Heap::QQmlValueTypeWrapper::toVariant() const
{
Q_ASSERT(gadgetPtr);
- return QVariant(metaType, gadgetPtr);
+ return QVariant(valueType->typeId, gadgetPtr);
}
@@ -123,7 +127,7 @@ bool QQmlValueTypeReference::readReferenceValue() const
QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->property, a);
int variantReferenceType = variantReferenceValue.userType();
- if (variantReferenceType != d()->metaType) {
+ if (variantReferenceType != typeId()) {
// This is a stale VariantReference. That is, the variant has been
// overwritten with a different type in the meantime.
// We need to modify this reference to the updated value type, if
@@ -132,24 +136,27 @@ bool QQmlValueTypeReference::readReferenceValue() const
QQmlPropertyCache *cache = 0;
if (const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(variantReferenceType))
cache = QJSEnginePrivate::get(engine())->cache(mo);
- if (d()->gadgetPtr)
- QMetaType::destroy(d()->metaType, d()->gadgetPtr);
- d()->gadgetPtr = 0;
+ if (d()->gadgetPtr) {
+ d()->valueType->metaType.destruct(d()->gadgetPtr);
+ ::operator delete(d()->gadgetPtr);
+ }
+ d()->gadgetPtr =0;
d()->propertyCache = cache;
- d()->metaType = variantReferenceType;
- if (cache) {
- d()->gadgetPtr = QMetaType::create(d()->metaType);
- } else {
+ d()->valueType = QQmlValueTypeFactory::valueType(variantReferenceType);
+ if (!cache)
return false;
- }
} else {
return false;
}
}
d()->setValue(variantReferenceValue);
} else {
+ if (!d()->gadgetPtr) {
+ d()->gadgetPtr = ::operator new(d()->valueType->metaType.sizeOf());
+ d()->valueType->metaType.construct(d()->gadgetPtr, 0);
+ }
// value-type reference
- void *args[] = { d()->gadget(), 0 };
+ void *args[] = { d()->gadgetPtr, 0 };
QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->property, args);
}
return true;
@@ -176,8 +183,8 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj
r->setPrototype(proto);
r->d()->object = object; r->d()->property = property;
r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject);
- r->d()->metaType = typeId;
- r->d()->gadgetPtr = QMetaType::create(r->d()->metaType);
+ r->d()->valueType = QQmlValueTypeFactory::valueType(typeId);
+ r->d()->gadgetPtr = 0;
return r->asReturnedValue();
}
@@ -190,8 +197,8 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVaria
ScopedObject proto(scope, engine->qmlExtensions()->valueTypeWrapperPrototype);
r->setPrototype(proto);
r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject);
- r->d()->metaType = typeId;
- r->d()->gadgetPtr = QMetaType::create(r->d()->metaType);
+ r->d()->valueType = QQmlValueTypeFactory::valueType(typeId);
+ r->d()->gadgetPtr = 0;
r->d()->setValue(value);
return r->asReturnedValue();
}
@@ -204,11 +211,15 @@ QVariant QQmlValueTypeWrapper::toVariant() const
return d()->toVariant();
}
-void QQmlValueTypeWrapper::toGadget(void *data) const
+bool QQmlValueTypeWrapper::toGadget(void *data) const
{
- int typeId = d()->metaType;
+ if (const QQmlValueTypeReference *ref = as<const QQmlValueTypeReference>())
+ if (!ref->readReferenceValue())
+ return false;
+ const int typeId = d()->valueType->typeId;
QMetaType::destruct(typeId, data);
- QMetaType::construct(typeId, data, d()->gadget());
+ QMetaType::construct(typeId, data, d()->gadgetPtr);
+ return true;
}
void QQmlValueTypeWrapper::destroy(Heap::Base *that)
@@ -248,6 +259,36 @@ bool QQmlValueTypeWrapper::isEqual(const QVariant& value)
return (value == d()->toVariant());
}
+int QQmlValueTypeWrapper::typeId() const
+{
+ return d()->valueType->typeId;
+}
+
+bool QQmlValueTypeWrapper::write(QObject *target, int propertyIndex) const
+{
+ bool destructGadgetOnExit = false;
+ if (const QQmlValueTypeReference *ref = as<const QQmlValueTypeReference>()) {
+ if (!d()->gadgetPtr) {
+ d()->gadgetPtr = alloca(d()->valueType->metaType.sizeOf());
+ d()->valueType->metaType.construct(d()->gadgetPtr, 0);
+ destructGadgetOnExit = true;
+ }
+ if (!ref->readReferenceValue())
+ return false;
+ }
+
+ int flags = 0;
+ int status = -1;
+ void *a[] = { d()->gadgetPtr, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty, propertyIndex, a);
+
+ if (destructGadgetOnExit) {
+ d()->valueType->metaType.destruct(d()->gadgetPtr);
+ d()->gadgetPtr = 0;
+ }
+ return true;
+}
+
ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
{
Object *o = ctx->thisObject().as<Object>();
@@ -265,15 +306,15 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
// Prepare a buffer to pass to QMetaType::convert()
QString convertResult;
convertResult.~QString();
- if (QMetaType::convert(w->d()->gadgetPtr, w->d()->metaType, &convertResult, QMetaType::QString)) {
+ if (QMetaType::convert(w->d()->gadgetPtr, w->d()->valueType->typeId, &convertResult, QMetaType::QString)) {
result = convertResult;
} else {
- result = QString::fromUtf8(QMetaType::typeName(w->d()->metaType));
+ result = QString::fromUtf8(QMetaType::typeName(w->d()->valueType->typeId));
result += QLatin1Char('(');
const QMetaObject *mo = w->d()->propertyCache->metaObject();
const int propCount = mo->propertyCount();
for (int i = 0; i < propCount; ++i) {
- QVariant value = mo->property(i).readOnGadget(w->d()->gadget());
+ QVariant value = mo->property(i).readOnGadget(w->d()->gadgetPtr);
result += value.toString();
if (i < propCount - 1)
result += QStringLiteral(", ");
@@ -322,7 +363,7 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha
int index = result->coreIndex;
QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(QMetaObject::ReadProperty, &metaObject, &index);
- void *gadget = r->d()->gadget();
+ void *gadget = r->d()->gadgetPtr;
// These four types are the most common used by the value type wrappers
VALUE_TYPE_LOAD(QMetaType::QReal, qreal, qreal);
@@ -411,7 +452,7 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
if (property.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double)
v = v.toInt();
- void *gadget = r->d()->gadget();
+ void *gadget = r->d()->gadgetPtr;
property.writeOnGadget(gadget, v);
@@ -427,7 +468,7 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
} else {
int flags = 0;
int status = -1;
- void *a[] = { r->d()->gadget(), 0, &status, &flags };
+ void *a[] = { r->d()->gadgetPtr, 0, &status, &flags };
QMetaObject::metacall(reference->d()->object, QMetaObject::WriteProperty, reference->d()->property, a);
}
}
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index 08b3ec76e9..efc4a78835 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -54,6 +54,7 @@
QT_BEGIN_NAMESPACE
class QV8Engine;
+class QQmlValueType;
namespace QV4 {
@@ -62,13 +63,12 @@ namespace Heap {
struct QQmlValueTypeWrapper : Object {
QQmlValueTypeWrapper(ExecutionEngine *engine);
~QQmlValueTypeWrapper();
- mutable QQmlRefPointer<QQmlPropertyCache> propertyCache;
+ QQmlRefPointer<QQmlPropertyCache> propertyCache;
mutable void *gadgetPtr;
- mutable int metaType;
+ QQmlValueType *valueType;
void setValue(const QVariant &value) const;
QVariant toVariant() const;
- void *gadget() const { return gadgetPtr; }
};
}
@@ -84,8 +84,10 @@ public:
static ReturnedValue create(ExecutionEngine *engine, const QVariant &, const QMetaObject *metaObject, int typeId);
QVariant toVariant() const;
- void toGadget(void *data) const;
+ bool toGadget(void *data) const;
bool isEqual(const QVariant& value);
+ int typeId() const;
+ bool write(QObject *target, int propertyIndex) const;
static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 39196e0e65..33c687dcd0 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -815,8 +815,15 @@ ReturnedValue QtObject::method_formatDateTime(QV4::CallContext *ctx)
}
/*!
-\qmlmethod bool Qt::openUrlExternally(url target)
-Attempts to open the specified \c target url in an external application, based on the user's desktop preferences. Returns true if it succeeds, and false otherwise.
+ \qmlmethod bool Qt::openUrlExternally(url target)
+
+ Attempts to open the specified \c target url in an external application, based on the user's
+ desktop preferences. Returns true if it succeeds, and false otherwise.
+
+ \warning A return value of \c true indicates that the application has successfully requested
+ the operating system to open the URL in an external application. The external application may
+ still fail to launch or fail to open the requested URL. This result will not be reported back
+ to the application.
*/
ReturnedValue QtObject::method_openUrlExternally(QV4::CallContext *ctx)
{
@@ -1723,7 +1730,7 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx)
QV8Engine *v8engine = ctx->d()->engine->v8Engine;
QString context;
if (QQmlContextData *ctxt = v8engine->callingContext()) {
- QString path = ctxt->url.toString();
+ QString path = ctxt->urlString();
int lastSlash = path.lastIndexOf(QLatin1Char('/'));
int lastDot = path.lastIndexOf(QLatin1Char('.'));
int length = lastDot - (lastSlash + 1);
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index 11aff9b95d..cb694c499a 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -277,7 +277,7 @@ QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate()
\section1 Tips for Porting Existing HTML5 Canvas Applications
- Although the Canvas item is provides a HTML5 like API, HTML5 canvas
+ Although the Canvas item provides an HTML5-like API, HTML5 canvas
applications need to be modified to run in the Canvas item:
\list
\li Replace all DOM API calls with QML property bindings or Canvas item methods.
diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp
index 64e46d1762..4d46485718 100644
--- a/src/quick/items/qquickdrag.cpp
+++ b/src/quick/items/qquickdrag.cpp
@@ -33,6 +33,9 @@
#include "qquickdrag_p.h"
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformdrag.h>
#include <private/qquickitem_p.h>
#include <QtQuick/private/qquickevents_p_p.h>
#include <private/qquickitemchangelistener_p.h>
@@ -724,7 +727,8 @@ Qt::DropAction QQuickDragAttachedPrivate::startDrag(Qt::DropActions supportedAct
Qt::DropAction dropAction = drag->exec(supportedActions);
- delete drag;
+ if (!QGuiApplicationPrivate::platformIntegration()->drag()->ownsDragObject())
+ drag->deleteLater();
deliverLeaveEvent();
diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp
index 414f068285..5c66a2ef84 100644
--- a/src/quick/items/qquickwindowmodule.cpp
+++ b/src/quick/items/qquickwindowmodule.cpp
@@ -143,9 +143,9 @@ void QQuickWindowQmlImpl::setWindowVisibility()
error.setObject(this);
const QQmlContextData* urlContext = data->context;
- while (urlContext && urlContext->url.isEmpty())
+ while (urlContext && urlContext->url().isEmpty())
urlContext = urlContext->parent;
- error.setUrl(urlContext ? urlContext->url : QUrl());
+ error.setUrl(urlContext ? urlContext->url() : QUrl());
QString objectId = data->context->findObjectId(this);
if (!objectId.isEmpty())
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 100861bfc1..dd071d757e 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -256,12 +256,12 @@ public:
advanceAnimation();
}
- float m_time;
- float m_vsync;
+ double m_time;
+ double m_vsync;
Mode m_mode;
QElapsedTimer m_timer;
QElapsedTimer m_wallTime;
- float m_lag;
+ double m_lag;
int m_bad;
int m_good;
};
diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
index b88d21ce66..0e22fa8b7b 100644
--- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp
+++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
@@ -35,6 +35,7 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QLibraryInfo>
+#include <QtCore/QThread>
#include <QtGui/QScreen>
#include <QtGui/QGuiApplication>
@@ -355,13 +356,20 @@ bool QSGWindowsRenderLoop::event(QEvent *event)
void QSGWindowsRenderLoop::render()
{
RLDEBUG("render");
+ bool rendered = false;
foreach (const WindowData &wd, m_windows) {
if (wd.pendingUpdate) {
const_cast<WindowData &>(wd).pendingUpdate = false;
renderWindow(wd.window);
+ rendered = true;
}
}
+ if (!rendered) {
+ RLDEBUG("no changes, sleep");
+ QThread::msleep(m_vsyncDelta);
+ }
+
if (m_animationDriver->isRunning()) {
RLDEBUG("advancing animations");
QSG_LOG_TIME_SAMPLE(time_start);
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index 09418ecfd7..076b068f27 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -394,8 +394,8 @@ void Atlas::bind(QSGTexture::Filtering filtering)
t->releaseImage();
qCDebug(QSG_LOG_TIME_TEXTURE).nospace() << "atlastexture uploaded in: " << qsg_renderer_timer.elapsed()
- << "ms (" << m_pending_uploads.at(i)->image().width() << "x"
- << m_pending_uploads.at(i)->image().height() << ")";
+ << "ms (" << t->textureSize().width() << "x"
+ << t->textureSize().height() << ")";
// Skip mipmap; unused
Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare);
diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp
index 4e96d90fde..6c333c6b13 100644
--- a/src/quick/util/qquickpropertychanges.cpp
+++ b/src/quick/util/qquickpropertychanges.cpp
@@ -295,8 +295,8 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix,
int column = -1;
QQmlData *ddata = QQmlData::get(q);
- if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty()) {
- url = ddata->outerContext->url;
+ if (ddata && ddata->outerContext && !ddata->outerContext->url().isEmpty()) {
+ url = ddata->outerContext->url();
line = ddata->lineNumber;
column = ddata->columnNumber;
}
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index 29577b856d..5dd439fdd0 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -630,6 +630,22 @@ void QQuickWidgetPrivate::updateSize()
}
}
+/*!
+ \internal
+
+ Update the position of the offscreen window, so it matches the position of the QQuickWidget.
+ */
+void QQuickWidgetPrivate::updatePosition()
+{
+ Q_Q(QQuickWidget);
+ if (offscreenWindow == 0)
+ return;
+
+ const QPoint &pos = q->mapToGlobal(QPoint(0, 0));
+ if (offscreenWindow->position() != pos)
+ offscreenWindow->setPosition(pos);
+}
+
QSize QQuickWidgetPrivate::rootObjectSize() const
{
QSize rootObjectSize(0,0);
@@ -746,6 +762,16 @@ void QQuickWidget::createFramebufferObject()
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
format.setSamples(samples);
+ // The default framebuffer for normal windows have sRGB support on OS X which leads to the Qt Quick text item
+ // utilizing sRGB blending. To get identical results with QQuickWidget we have to have our framebuffer backed
+ // by an sRGB texture.
+#ifdef Q_OS_OSX
+ if (context->hasExtension("GL_ARB_framebuffer_sRGB")
+ && context->hasExtension("GL_EXT_texture_sRGB")
+ && context->hasExtension("GL_EXT_texture_sRGB_decode"))
+ format.setInternalTextureFormat(GL_SRGB8_ALPHA8_EXT);
+#endif
+
const QSize fboSize = size() * devicePixelRatio();
// Could be a simple hide - show, in which case the previous fbo is just fine.
@@ -754,7 +780,22 @@ void QQuickWidget::createFramebufferObject()
d->fbo = new QOpenGLFramebufferObject(fboSize, format);
}
- d->offscreenWindow->setGeometry(0, 0, width(), height());
+ // When compositing in the backingstore, sampling the sRGB texture would perform an
+ // sRGB-linear conversion which is not what we want when the final framebuffer (the window's)
+ // is sRGB too. Disable the conversion.
+#ifdef Q_OS_OSX
+ if (format.internalTextureFormat() == GL_SRGB8_ALPHA8_EXT) {
+ QOpenGLFunctions *funcs = context->functions();
+ funcs->glBindTexture(GL_TEXTURE_2D, d->fbo->texture());
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
+ }
+#endif
+
+ // Even though this is just an offscreen window we should set the position on it, as it might be
+ // useful for an item to know the actual position of the scene.
+ // Note: The position will be update when we get a move event (see: updatePosition()).
+ const QPoint &globalPos = mapToGlobal(QPoint(0, 0));
+ d->offscreenWindow->setGeometry(globalPos.x(), globalPos.y(), width(), height());
d->offscreenWindow->setRenderTarget(d->fbo);
if (samples > 0)
@@ -1108,6 +1149,10 @@ bool QQuickWidget::event(QEvent *e)
}
break;
+ case QEvent::Move:
+ d->updatePosition();
+ break;
+
default:
break;
}
diff --git a/src/quickwidgets/qquickwidget_p.h b/src/quickwidgets/qquickwidget_p.h
index c16ce2fece..dd0da96c3d 100644
--- a/src/quickwidgets/qquickwidget_p.h
+++ b/src/quickwidgets/qquickwidget_p.h
@@ -73,6 +73,7 @@ public:
void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
void initResize();
void updateSize();
+ void updatePosition();
void updateFrambufferObjectSize();
void setRootObject(QObject *);
void render(bool needsSync);
@@ -81,7 +82,7 @@ public:
void destroyContext();
void handleContextCreationFailure(const QSurfaceFormat &format, bool isEs);
- QObject *focusObject() Q_DECL_OVERRIDE;
+ QObject *focusObject();
GLuint textureId() const Q_DECL_OVERRIDE;
QImage grabFramebuffer() Q_DECL_OVERRIDE;
diff --git a/tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro b/tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro
index 3608375771..0d6484f8e6 100644
--- a/tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro
+++ b/tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro
@@ -1,6 +1,6 @@
CONFIG += testcase
TARGET = tst_qdebugmessageservice
-QT += qml network testlib gui-private
+QT += qml network testlib gui-private core-private
macx:CONFIG -= app_bundle
SOURCES += tst_qdebugmessageservice.cpp
diff --git a/tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro b/tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro
index 98c0fc2542..716d8f0be9 100644
--- a/tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro
+++ b/tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro
@@ -8,5 +8,5 @@ INCLUDEPATH += ../shared
include(../shared/debugutil.pri)
CONFIG += parallel_test
-QT += qml network testlib gui-private
+QT += qml network testlib gui-private core-private
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/qml/debugger/qqmldebugclient/qqmldebugclient.pro b/tests/auto/qml/debugger/qqmldebugclient/qqmldebugclient.pro
index 38f78e8248..ad431d4871 100644
--- a/tests/auto/qml/debugger/qqmldebugclient/qqmldebugclient.pro
+++ b/tests/auto/qml/debugger/qqmldebugclient/qqmldebugclient.pro
@@ -14,5 +14,5 @@ DEFINES += QT_QML_DEBUG_NO_WARNING
CONFIG += qml_debug
-QT += qml-private testlib gui-private
+QT += qml-private testlib gui-private core-private
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler.pro b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler.pro
index 330c8bcdbf..eb41f759c9 100644
--- a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler.pro
+++ b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler.pro
@@ -1,6 +1,6 @@
CONFIG += testcase
TARGET = tst_qqmldebuggingenabler
-QT += qml testlib gui-private
+QT += qml testlib gui-private core-private
osx:CONFIG -= app_bundle
SOURCES += tst_qqmldebuggingenabler.cpp
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro
index eb5f17a55d..fb06df9c99 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro
+++ b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro
@@ -1,6 +1,6 @@
CONFIG += testcase
TARGET = tst_qqmldebugjs
-QT += qml testlib gui-private
+QT += qml testlib gui-private core-private
macx:CONFIG -= app_bundle
SOURCES += tst_qqmldebugjs.cpp
diff --git a/tests/auto/qml/debugger/qqmldebugservice/qqmldebugservice.pro b/tests/auto/qml/debugger/qqmldebugservice/qqmldebugservice.pro
index 5879506a58..573e58d3a6 100644
--- a/tests/auto/qml/debugger/qqmldebugservice/qqmldebugservice.pro
+++ b/tests/auto/qml/debugger/qqmldebugservice/qqmldebugservice.pro
@@ -18,5 +18,5 @@ OTHER_FILES += \
DEFINES += QT_QML_DEBUG_NO_WARNING
-QT += qml-private testlib gui-private
+QT += qml-private testlib gui-private core-private
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/qml/debugger/qqmlenginecontrol/qqmlenginecontrol.pro b/tests/auto/qml/debugger/qqmlenginecontrol/qqmlenginecontrol.pro
index 09332cc302..901dd229c0 100644
--- a/tests/auto/qml/debugger/qqmlenginecontrol/qqmlenginecontrol.pro
+++ b/tests/auto/qml/debugger/qqmlenginecontrol/qqmlenginecontrol.pro
@@ -10,7 +10,7 @@ include(../shared/debugutil.pri)
TESTDATA = data/*
-QT += core qml testlib gui-private
+QT += core qml testlib gui-private core-private
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
OTHER_FILES += \
diff --git a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/qqmlenginedebuginspectorintegrationtest.pro b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/qqmlenginedebuginspectorintegrationtest.pro
index 9da6bda28e..028eb3644d 100644
--- a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/qqmlenginedebuginspectorintegrationtest.pro
+++ b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/qqmlenginedebuginspectorintegrationtest.pro
@@ -1,7 +1,7 @@
CONFIG += testcase
TARGET = tst_qqmlenginedebuginspectorintegration
-QT += qml testlib gui-private
+QT += qml testlib gui-private core-private
macx:CONFIG -= app_bundle
SOURCES += tst_qqmlenginedebuginspectorintegration.cpp
diff --git a/tests/auto/qml/debugger/qqmlinspector/qqmlinspector.pro b/tests/auto/qml/debugger/qqmlinspector/qqmlinspector.pro
index 4adda35aea..3a1d59f3fa 100644
--- a/tests/auto/qml/debugger/qqmlinspector/qqmlinspector.pro
+++ b/tests/auto/qml/debugger/qqmlinspector/qqmlinspector.pro
@@ -1,7 +1,7 @@
CONFIG += testcase
TARGET = tst_qqmlinspector
-QT += qml testlib gui-private
+QT += qml testlib gui-private core-private
macx:CONFIG -= app_bundle
SOURCES += tst_qqmlinspector.cpp
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro
index 1bab614b63..ec84139797 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro
@@ -10,7 +10,7 @@ include(../shared/debugutil.pri)
TESTDATA = data/*
-QT += core qml testlib gui-private
+QT += core qml testlib gui-private core-private
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
OTHER_FILES += \
diff --git a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
index e78427df3b..7df020405f 100644
--- a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
+++ b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
@@ -134,31 +134,30 @@ void tst_qquickapplication::state()
QQuickWindow window;
item->setParentItem(window.contentItem());
- // initial state should be ApplicationInactive
- QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationInactive);
- QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationInactive);
-
// If the platform plugin has the ApplicationState capability, state changes originate from it
// as a result of a system event. We therefore have to simulate these events here.
if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)) {
+ // Flush pending events, in case the platform have already queued real application state events
+ QWindowSystemInterface::flushWindowSystemEvents();
+
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
- QTest::waitForEvents();
+ QWindowSystemInterface::flushWindowSystemEvents();
QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationActive);
QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationActive);
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
- QTest::waitForEvents();
+ QWindowSystemInterface::flushWindowSystemEvents();
QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationInactive);
QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationInactive);
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationSuspended);
- QTest::waitForEvents();
+ QWindowSystemInterface::flushWindowSystemEvents();
QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationSuspended);
QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationSuspended);
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationHidden);
- QTest::waitForEvents();
+ QWindowSystemInterface::flushWindowSystemEvents();
QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationHidden);
QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationHidden);
diff --git a/tests/manual/shorcuts/shortcuts.qml b/tests/manual/shortcuts/shortcuts.qml
index beb931389d..beb931389d 100644
--- a/tests/manual/shorcuts/shortcuts.qml
+++ b/tests/manual/shortcuts/shortcuts.qml
diff --git a/tests/manual/touch/flicktext.qml b/tests/manual/touch/flicktext.qml
new file mode 100644
index 0000000000..e541d5e35e
--- /dev/null
+++ b/tests/manual/touch/flicktext.qml
@@ -0,0 +1,378 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the manual tests 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
+import "qrc:/quick/shared/" as Examples
+
+Rectangle {
+ id: root
+
+ Item {
+ id: flickArea
+ anchors.fill: parent
+ anchors.bottomMargin: bottomFlow.implicitHeight + 4
+ clip: true
+
+ Flickable {
+ id: flick
+ anchors.fill: parent
+ anchors.margins: 6
+ contentWidth: text.implicitWidth
+ contentHeight: text.implicitHeight
+ pixelAligned: pxAlignCB.checked
+ Text {
+ id: text
+ text: "foo bar"
+ font.family: "mono"
+ }
+ onContentXChanged: canvas.requestPaint()
+ onContentYChanged: canvas.requestPaint()
+ }
+
+ Timer { id: fadeTimer; interval: 1000; onTriggered: { hfade.start(); } }
+
+ MouseArea {
+ id: verticalScrollArea
+ anchors {
+ right: parent.right
+ top: flick.top
+ bottom: flick.bottom
+ }
+ width: 36
+ onMouseYChanged: {
+ var contentY = Math.min(height, mouseY) / height * (flick.contentHeight - height)
+ flick.contentY = Math.max(0, contentY)
+ }
+ onReleased: flick.returnToBounds()
+ Rectangle {
+ anchors.right: parent.right
+ anchors.margins: 2
+ color: "darkgrey"
+ width: 20
+ radius: 2
+ antialiasing: true
+ height: flick.height * (flick.height / flick.contentHeight) - anchors.margins * 2
+ y: flick.contentY * (flick.height / flick.contentHeight)
+
+ Rectangle {
+ anchors.top: parent.top
+ width: parent.width
+ height: 6
+ radius: 2
+ color: "blue"
+ visible: flick.atYBeginning
+ }
+
+ Rectangle {
+ anchors.top: parent.bottom
+ width: parent.width
+ height: 6
+ radius: 2
+ color: "blue"
+ visible: flick.atYEnd
+ }
+
+ Text {
+ anchors.centerIn: parent
+ text: flick.contentY.toFixed(2)
+ rotation: 90
+ style: Text.Outline
+ styleColor: "white"
+ color: "black"
+ }
+
+ }
+ }
+
+ Rectangle {
+ id: horizontalScrollDecorator
+ anchors.bottom: flick.bottom
+ anchors.bottomMargin: -4
+ color: "darkgrey"
+ border.color: "black"
+ border.width: 1
+ height: 5
+ radius: 2
+ antialiasing: true
+ width: flick.width * (flick.width / flick.contentWidth) - (height - anchors.margins) * 2
+ x: flick.contentX * (flick.width / flick.contentWidth)
+ NumberAnimation on opacity { id: hfade; to: 0; duration: 500 }
+ onXChanged: { opacity = 1.0; fadeTimer.restart() }
+ }
+
+ Canvas {
+ id: canvas
+ anchors.fill: parent
+ antialiasing: true
+ renderTarget: Canvas.FramebufferObject
+ onPaint: {
+ var ctx = canvas.getContext('2d');
+ ctx.save()
+ ctx.clearRect(0, 0, canvas.width, canvas.height)
+ ctx.strokeStyle = "green"
+ ctx.fillStyle = "green"
+ ctx.lineWidth = 1
+
+ if (flick.horizontalVelocity) {
+ ctx.save()
+ ctx.beginPath()
+ ctx.translate((flick.horizontalVelocity < 0 ? width : 0), height / 2)
+ ctx.moveTo(0, 0)
+ var velScaled = flick.horizontalVelocity / 10
+ var arrowOffset = (flick.horizontalVelocity < 0 ? 10 : -10)
+ ctx.lineTo(velScaled, 0)
+ ctx.lineTo(velScaled + arrowOffset, -4)
+ ctx.lineTo(velScaled + arrowOffset, 4)
+ ctx.lineTo(velScaled, 0)
+ ctx.closePath()
+ ctx.stroke()
+ ctx.fill()
+ ctx.restore()
+ }
+
+ if (flick.verticalVelocity) {
+ ctx.save()
+ ctx.beginPath()
+ ctx.translate(width / 2, (flick.verticalVelocity < 0 ? height : 0))
+ ctx.moveTo(0, 0)
+ var velScaled = flick.verticalVelocity / 10
+ var arrowOffset = (flick.verticalVelocity < 0 ? 10 : -10)
+ ctx.lineTo(0, velScaled)
+ ctx.lineTo(-4, velScaled + arrowOffset)
+ ctx.lineTo(4, velScaled + arrowOffset)
+ ctx.lineTo(0, velScaled)
+ ctx.closePath()
+ ctx.stroke()
+ ctx.fill()
+ ctx.restore()
+ }
+
+ ctx.restore()
+ }
+ }
+ }
+
+ Row {
+ id: bottomFlow
+ anchors.bottom: parent.bottom
+ width: parent.width - 12
+ x: 6
+ spacing: 12
+
+ Item {
+ id: progFlickItem
+ width: progFlickRow.implicitWidth
+ height: progFlickRow.implicitHeight + 4 + flickingLabel.implicitHeight
+ Text { id: progLabel; text: "programmatic flick: h " + xvelSlider.value.toFixed(1) + " v " + yvelSlider.value.toFixed(1) }
+ Row {
+ id: progFlickRow
+ y: progLabel.height
+ spacing: 4
+
+ Column {
+ Examples.Slider {
+ id: xvelSlider
+ min: -5000
+ max: 5000
+ init: 5000
+ width: 250
+ name: "X"
+ minLabelWidth: 0
+ }
+ Examples.Slider {
+ id: yvelSlider
+ min: -5000
+ max: 5000
+ init: 2500
+ width: 250
+ name: "Y"
+ minLabelWidth: 0
+ }
+ }
+
+ Grid {
+ columns: 2
+ spacing: 2
+ Examples.Button {
+ text: "flick"
+ onClicked: flick.flick(xvelSlider.value, yvelSlider.value)
+ width: zeroButton.width
+ }
+ Examples.Button {
+ text: "cancel"
+ onClicked: flick.cancelFlick()
+ width: zeroButton.width
+ }
+ Examples.Button {
+ id: zeroButton
+ text: "<- zero"
+ onClicked: {
+ xvelSlider.setValue(5000)
+ yvelSlider.setValue(5000)
+ }
+ }
+ Examples.Button {
+ text: "home"
+ width: zeroButton.width
+ onClicked: {
+ flick.contentX = 0
+ flick.contentY = 0
+ }
+ }
+ }
+ }
+ }
+
+ Column {
+ height: parent.height
+ width: movingLabel.implicitWidth * 1.5
+ spacing: 2
+ Text {
+ id: movingLabel
+ text: "moving:"
+ color: flick.moving ? "green" : "black"
+ }
+ Rectangle {
+ width: parent.width
+ height: hVelLabel.implicitHeight + 4
+ color: flick.movingHorizontally ? "green" : "darkgrey"
+ Text {
+ id: hVelLabel
+ anchors.centerIn: parent
+ color: "white"
+ text: "h " + flick.horizontalVelocity.toFixed(2)
+ }
+ }
+ Rectangle {
+ width: parent.width
+ height: vVelLabel.implicitHeight + 4
+ color: flick.movingVertically ? "green" : "darkgrey"
+ Text {
+ id: vVelLabel
+ anchors.centerIn: parent
+ color: "white"
+ text: "v " + flick.verticalVelocity.toFixed(2)
+ }
+ }
+ }
+
+ Column {
+ height: parent.height
+ width: draggingLabel.implicitWidth
+ spacing: 2
+ Text {
+ id: draggingLabel
+ text: "dragging:"
+ color: flick.dragging ? "green" : "black"
+ }
+ Rectangle {
+ width: draggingLabel.implicitWidth
+ height: hVelLabel.implicitHeight + 4
+ color: flick.draggingHorizontally ? "green" : "darkgrey"
+ Text {
+ anchors.centerIn: parent
+ color: "white"
+ text: "h"
+ }
+ }
+ Rectangle {
+ width: draggingLabel.implicitWidth
+ height: vVelLabel.implicitHeight + 4
+ color: flick.draggingVertically ? "green" : "darkgrey"
+ Text {
+ anchors.centerIn: parent
+ color: "white"
+ text: "v"
+ }
+ }
+ }
+
+ Column {
+ height: parent.height
+ width: flickingLabel.implicitWidth
+ spacing: 2
+ Text {
+ id: flickingLabel
+ text: "flicking:"
+ color: flick.flicking ? "green" : "black"
+ }
+ Rectangle {
+ width: flickingLabel.implicitWidth
+ height: hVelLabel.implicitHeight + 4
+ color: flick.flickingHorizontally ? "green" : "darkgrey"
+ Text {
+ anchors.centerIn: parent
+ color: "white"
+ text: "h"
+ }
+ }
+ Rectangle {
+ width: flickingLabel.implicitWidth
+ height: vVelLabel.implicitHeight + 4
+ color: flick.flickingVertically ? "green" : "darkgrey"
+ Text {
+ anchors.centerIn: parent
+ color: "white"
+ text: "v"
+ }
+ }
+ }
+
+ Column {
+ Examples.CheckBox {
+ id: pxAlignCB
+ text: "pixel aligned"
+ }
+ Text {
+ text: "content X " + flick.contentX.toFixed(2) + " Y " + flick.contentY.toFixed(2)
+ }
+ }
+ }
+
+ Component.onCompleted: {
+ var request = new XMLHttpRequest()
+ request.open('GET', 'qrc:/flicktext.qml')
+ request.onreadystatechange = function(event) {
+ if (request.readyState === XMLHttpRequest.DONE)
+ text.text = request.responseText
+ }
+ request.send()
+ }
+}
diff --git a/tests/manual/touch/main.cpp b/tests/manual/touch/main.cpp
new file mode 100644
index 0000000000..baa9603175
--- /dev/null
+++ b/tests/manual/touch/main.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the manual tests 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$
+**
+****************************************************************************/
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QQmlApplicationEngine engine;
+ engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
+
+ return app.exec();
+}
diff --git a/tests/manual/touch/main.qml b/tests/manual/touch/main.qml
new file mode 100644
index 0000000000..524f979c85
--- /dev/null
+++ b/tests/manual/touch/main.qml
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the manual tests 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
+import QtQuick.Window 2.2
+import "qrc:/quick/shared/" as Examples
+
+Window {
+ width: 800
+ height: 600
+ visible: true
+ Examples.LauncherList {
+ id: ll
+ anchors.fill: parent
+ Component.onCompleted: {
+ addExample("crosshairs", "crosshairs and velocity vectors at finger positions", Qt.resolvedUrl("mpta-crosshairs.qml"))
+ addExample("flick text", "flick a text document", Qt.resolvedUrl("flicktext.qml"))
+ }
+ }
+}
diff --git a/tests/manual/touch/mpta-crosshairs.qml b/tests/manual/touch/mpta-crosshairs.qml
new file mode 100644
index 0000000000..8b71e4fdc3
--- /dev/null
+++ b/tests/manual/touch/mpta-crosshairs.qml
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the manual tests 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
+import QtQuick.Window 2.2
+
+Rectangle {
+ id: root
+ color: "black"
+
+ MultiPointTouchArea {
+ id: mpta
+ anchors.fill: parent
+ touchPoints: [
+ TouchPoint { property color color: "red" },
+ TouchPoint { property color color: "orange" },
+ TouchPoint { property color color: "yellow" },
+ TouchPoint { property color color: "green" },
+ TouchPoint { property color color: "blue" },
+ TouchPoint { property color color: "violet" },
+ TouchPoint { property color color: "cyan" },
+ TouchPoint { property color color: "magenta" },
+ TouchPoint { property color color: "goldenrod" },
+ TouchPoint { property color color: "darkgray" }
+ ] }
+
+ Repeater {
+ model: 10
+
+ Item {
+ anchors.fill: parent
+ property TouchPoint touchPoint
+ visible: touchPoint.pressed
+
+ Rectangle {
+ color: touchPoint.color
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ width: 2
+ x: touchPoint.x - 1
+ }
+ Rectangle {
+ color: touchPoint.color
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: 2
+ y: touchPoint.y - 1
+ }
+ Rectangle {
+ color: touchPoint.color
+ width: 50 * touchPoint.pressure
+ height: width
+ radius: width / 2
+ x: touchPoint.x - width / 2
+ y: touchPoint.y - width / 2
+ }
+ Rectangle {
+ id: velocityVector
+ visible: width > 0
+ width: touchPoint.velocity.length()
+ height: 1
+ x: touchPoint.x
+ y: touchPoint.y
+ rotation: width > 0 ? Math.acos(touchPoint.velocity.x / width) : 0
+ transformOrigin: Item.BottomLeft
+ }
+
+ Component.onCompleted: touchPoint = mpta.touchPoints[index]
+ }
+ }
+}
diff --git a/tests/manual/touch/qml.qrc b/tests/manual/touch/qml.qrc
new file mode 100644
index 0000000000..478b6886d6
--- /dev/null
+++ b/tests/manual/touch/qml.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>mpta-crosshairs.qml</file>
+ <file>flicktext.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/touch/touch.pro b/tests/manual/touch/touch.pro
new file mode 100644
index 0000000000..3705d41df0
--- /dev/null
+++ b/tests/manual/touch/touch.pro
@@ -0,0 +1,7 @@
+TEMPLATE = app
+
+QT += qml quick
+
+SOURCES += main.cpp
+
+RESOURCES += qml.qrc ../../../examples/quick/shared/quick_shared.qrc
diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp
index eafd93b143..96c23ae268 100644
--- a/tools/qmlplugindump/main.cpp
+++ b/tools/qmlplugindump/main.cpp
@@ -46,6 +46,12 @@
#include <QtCore/QMetaObject>
#include <QtCore/QMetaProperty>
#include <QtCore/QDebug>
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonParseError>
+#include <QtCore/QJsonValue>
+#include <QtCore/QJsonArray>
+#include <QtCore/QJsonObject>
+#include <QtCore/QProcess>
#include <QtCore/private/qobject_p.h>
#include <QtCore/private/qmetaobject_p.h>
@@ -75,6 +81,13 @@ bool creatable = true;
QString currentProperty;
QString inObjectInstantiation;
+static QString enquote(const QString &string)
+{
+ QString s = string;
+ return QString("\"%1\"").arg(s.replace(QLatin1Char('\\'), QLatin1String("\\\\"))
+ .replace(QLatin1Char('"'),QLatin1String("\\\"")));
+}
+
void collectReachableMetaObjects(const QMetaObject *meta, QSet<const QMetaObject *> *metas, bool extended = false)
{
if (! meta || metas->contains(meta))
@@ -564,10 +577,6 @@ public:
}
private:
- static QString enquote(const QString &string)
- {
- return QString("\"%1\"").arg(string);
- }
/* Removes pointer and list annotations from a type name, returning
what was removed in isList and isPointer
@@ -705,13 +714,175 @@ void sigSegvHandler(int) {
void printUsage(const QString &appName)
{
std::cerr << qPrintable(QString(
- "Usage: %1 [-v] [-noinstantiate] [-defaultplatform] [-[non]relocatable] module.uri version [module/import/path]\n"
+ "Usage: %1 [-v] [-noinstantiate] [-defaultplatform] [-[non]relocatable] [-dependencies <dependencies.json>] module.uri version [module/import/path]\n"
" %1 [-v] [-noinstantiate] -path path/to/qmldir/directory [version]\n"
" %1 [-v] -builtins\n"
"Example: %1 Qt.labs.folderlistmodel 2.0 /home/user/dev/qt-install/imports").arg(
appName)) << std::endl;
}
+static bool readDependenciesData(QString dependenciesFile, const QByteArray &fileData,
+ QStringList *dependencies, const QStringList &urisToSkip) {
+ if (verbose) {
+ std::cerr << "parsing "
+ << qPrintable( dependenciesFile ) << " skipping";
+ foreach (const QString &uriToSkip, urisToSkip)
+ std::cerr << " " << qPrintable(uriToSkip);
+ std::cerr << std::endl;
+ }
+ QJsonParseError parseError;
+ parseError.error = QJsonParseError::NoError;
+ QJsonDocument doc = QJsonDocument::fromJson(fileData, &parseError);
+ if (parseError.error != QJsonParseError::NoError) {
+ std::cerr << "Error parsing dependencies file " << dependenciesFile.toStdString()
+ << ":" << parseError.errorString().toStdString() << " at " << parseError.offset
+ << std::endl;
+ return false;
+ }
+ if (doc.isArray()) {
+ QStringList requiredKeys = QStringList() << QStringLiteral("name")
+ << QStringLiteral("type")
+ << QStringLiteral("version");
+ foreach (const QJsonValue &dep, doc.array()) {
+ if (dep.isObject()) {
+ QJsonObject obj = dep.toObject();
+ foreach (const QString &requiredKey, requiredKeys)
+ if (!obj.contains(requiredKey) || obj.value(requiredKey).isString())
+ continue;
+ if (obj.value(QStringLiteral("type")).toString() != QLatin1String("module"))
+ continue;
+ QString name = obj.value((QStringLiteral("name"))).toString();
+ QString version = obj.value(QStringLiteral("version")).toString();
+ if (name.isEmpty() || urisToSkip.contains(name) || version.isEmpty())
+ continue;
+ if (name.endsWith(QLatin1String("Private"))) {
+ if (verbose)
+ std::cerr << "skipping private dependecy "
+ << qPrintable( name ) << " " << qPrintable(version) << std::endl;
+ continue;
+ }
+ if (verbose)
+ std::cerr << "appending dependency "
+ << qPrintable( name ) << " " << qPrintable(version) << std::endl;
+ dependencies->append(name + QLatin1Char(' ')+version);
+ }
+ }
+ } else {
+ std::cerr << "Error parsing dependencies file " << dependenciesFile.toStdString()
+ << ": expected an array" << std::endl;
+ return false;
+ }
+ return true;
+}
+
+static bool readDependenciesFile(QString dependenciesFile, QStringList *dependencies,
+ const QStringList &urisToSkip) {
+ if (!QFileInfo(dependenciesFile).exists()) {
+ std::cerr << "non existing dependencies file " << dependenciesFile.toStdString()
+ << std::endl;
+ return false;
+ }
+ QFile f(dependenciesFile);
+ if (!f.open(QFileDevice::ReadOnly)) {
+ std::cerr << "non existing dependencies file " << dependenciesFile.toStdString()
+ << ", " << f.errorString().toStdString() << std::endl;
+ return false;
+ }
+ QByteArray fileData = f.readAll();
+ return readDependenciesData(dependenciesFile, fileData, dependencies, urisToSkip);
+}
+
+static bool getDependencies(const QQmlEngine &engine, const QString &pluginImportUri,
+ const QString &pluginImportVersion, QStringList *dependencies)
+{
+ QFileInfo selfExe(QCoreApplication::applicationFilePath());
+ QString command = selfExe.absoluteDir().filePath(QLatin1String("qmlimportscanner")
+ + selfExe.suffix());
+
+ QStringList commandArgs = QStringList()
+ << QLatin1String("-qmlFiles")
+ << QLatin1String("-");
+ foreach (const QString &path, engine.importPathList())
+ commandArgs << QLatin1String("-importPath") << path;
+
+ QProcess importScanner;
+ importScanner.start(command, commandArgs, QProcess::ReadWrite);
+ if (!importScanner.waitForStarted())
+ return false;
+
+ importScanner.write("import ");
+ importScanner.write(pluginImportUri.toUtf8());
+ importScanner.write(" ");
+ importScanner.write(pluginImportVersion.toUtf8());
+ importScanner.write("\nQtObject{}\n");
+ importScanner.closeWriteChannel();
+
+ if (!importScanner.waitForFinished()) {
+ std::cerr << "failure to start " << qPrintable(command);
+ foreach (const QString &arg, commandArgs)
+ std::cerr << " " << qPrintable(arg);
+ std::cerr << std::endl;
+ return false;
+ }
+ QByteArray depencenciesData = importScanner.readAllStandardOutput();
+ if (!readDependenciesData(QLatin1String("<outputOfQmlimportscanner>"), depencenciesData,
+ dependencies, QStringList(pluginImportUri))) {
+ std::cerr << "failed to proecess output of qmlimportscanner" << std::endl;
+ return false;
+ }
+ return true;
+}
+
+bool compactDependencies(QStringList *dependencies)
+{
+ if (dependencies->isEmpty())
+ return false;
+ dependencies->sort();
+ QStringList oldDep = dependencies->first().split(QLatin1Char(' '));
+ Q_ASSERT(oldDep.size() == 2);
+ int oldPos = 0;
+ for (int idep = 1; idep < dependencies->size(); ++idep) {
+ QString depStr = dependencies->at(idep);
+ const QStringList newDep = depStr.split(QLatin1Char(' '));
+ Q_ASSERT(newDep.size() == 2);
+ if (newDep.first() != oldDep.first()) {
+ if (++oldPos != idep)
+ dependencies->replace(oldPos, depStr);
+ oldDep = newDep;
+ } else {
+ QStringList v1 = oldDep.last().split(QLatin1Char('.'));
+ QStringList v2 = newDep.last().split(QLatin1Char('.'));
+ Q_ASSERT(v1.size() == 2);
+ Q_ASSERT(v2.size() == 2);
+ bool ok;
+ int major1 = v1.first().toInt(&ok);
+ Q_ASSERT(ok);
+ int major2 = v2.first().toInt(&ok);
+ Q_ASSERT(ok);
+ if (major1 != major2) {
+ std::cerr << "Found a dependency on " << qPrintable(oldDep.first())
+ << " with two major versions:" << qPrintable(oldDep.last())
+ << " and " << qPrintable(newDep.last())
+ << " which is unsupported, discarding smaller version" << std::endl;
+ if (major1 < major2)
+ dependencies->replace(oldPos, depStr);
+ } else {
+ int minor1 = v1.last().toInt(&ok);
+ Q_ASSERT(ok);
+ int minor2 = v2.last().toInt(&ok);
+ Q_ASSERT(ok);
+ if (minor1 < minor2)
+ dependencies->replace(oldPos, depStr);
+ }
+ }
+ }
+ if (++oldPos < dependencies->size()) {
+ *dependencies = dependencies->mid(0, oldPos);
+ return true;
+ }
+ return false;
+}
+
inline std::wostream &operator<<(std::wostream &str, const QString &s)
{
#ifdef Q_OS_WIN
@@ -780,17 +951,26 @@ int main(int argc, char *argv[])
QString pluginImportUri;
QString pluginImportVersion;
bool relocatable = true;
+ QString dependenciesFile;
enum Action { Uri, Path, Builtins };
Action action = Uri;
{
QStringList positionalArgs;
- foreach (const QString &arg, args) {
+
+ for (int iArg = 0; iArg < args.size(); ++iArg) {
+ const QString &arg = args.at(iArg);
if (!arg.startsWith(QLatin1Char('-'))) {
positionalArgs.append(arg);
continue;
}
-
- if (arg == QLatin1String("--notrelocatable")
+ if (arg == QLatin1String("--dependencies")
+ || arg == QLatin1String("-dependencies")) {
+ if (++iArg == args.size()) {
+ std::cerr << "missing dependencies file" << std::endl;
+ return EXIT_INVALIDARGUMENTS;
+ }
+ dependenciesFile = args.at(iArg);
+ } else if (arg == QLatin1String("--notrelocatable")
|| arg == QLatin1String("-notrelocatable")
|| arg == QLatin1String("--nonrelocatable")
|| arg == QLatin1String("-nonrelocatable")) {
@@ -851,12 +1031,24 @@ int main(int argc, char *argv[])
QDir::setCurrent(pluginImportPath);
engine.addImportPath(pluginImportPath);
}
-
- // load the QtQuick 2 plugin
+ bool calculateDependencies = !pluginImportUri.isEmpty() && !pluginImportVersion.isEmpty();
+ QStringList dependencies;
+ if (!dependenciesFile.isEmpty())
+ calculateDependencies = !readDependenciesFile(dependenciesFile, &dependencies,
+ QStringList(pluginImportUri)) && calculateDependencies;
+ if (calculateDependencies)
+ getDependencies(engine, pluginImportUri, pluginImportVersion, &dependencies);
+ compactDependencies(&dependencies);
+ // load the QtQml 2.2 builtins and the dependencies
{
- QByteArray code("import QtQuick 2.0\nQtObject {}");
+ QByteArray code("import QtQml 2.2");
+ foreach (const QString &moduleToImport, dependencies) {
+ code.append("\nimport ");
+ code.append(moduleToImport.toUtf8());
+ }
+ code.append("\nQtObject {}");
QQmlComponent c(&engine);
- c.setData(code, QUrl::fromLocalFile(pluginImportPath + "/loadqtquick2.qml"));
+ c.setData(code, QUrl::fromLocalFile(pluginImportPath + "/loaddependencies.qml"));
c.create();
if (!c.errors().isEmpty()) {
foreach (const QQmlError &error, c.errors())
@@ -887,28 +1079,33 @@ int main(int argc, char *argv[])
QQmlType *qtObjectType = QQmlMetaType::qmlType(&QObject::staticMetaObject);
if (!qtObjectType) {
std::cerr << "Could not find QtObject type" << std::endl;
- importCode = QByteArray("import QtQuick 2.0\n");
+ importCode = QByteArray("import QtQml 2.2");
} else {
QString module = qtObjectType->qmlTypeName();
module = module.mid(0, module.lastIndexOf(QLatin1Char('/')));
- importCode = QString("import %1 %2.%3\n").arg(module,
- QString::number(qtObjectType->majorVersion()),
- QString::number(qtObjectType->minorVersion())).toUtf8();
+ importCode = QString("import %1 %2.%3").arg(module,
+ QString::number(qtObjectType->majorVersion()),
+ QString::number(qtObjectType->minorVersion())).toUtf8();
+ }
+ // avoid importing dependencies?
+ foreach (const QString &moduleToImport, dependencies) {
+ importCode.append("\nimport ");
+ importCode.append(moduleToImport.toUtf8());
}
// find all QMetaObjects reachable when the specified module is imported
if (action != Path) {
- importCode += QString("import %0 %1\n").arg(pluginImportUri, pluginImportVersion).toLatin1();
+ importCode += QString("\nimport %0 %1\n").arg(pluginImportUri, pluginImportVersion).toLatin1();
} else {
// pluginImportVersion can be empty
- importCode += QString("import \".\" %2\n").arg(pluginImportVersion).toLatin1();
+ importCode += QString("\nimport \".\" %2\n").arg(pluginImportVersion).toLatin1();
}
// create a component with these imports to make sure the imports are valid
// and to populate the declarative meta type system
{
QByteArray code = importCode;
- code += "QtObject {}";
+ code += "\nQtObject {}";
QQmlComponent c(&engine);
c.setData(code, QUrl::fromLocalFile(pluginImportPath + "/typelist.qml"));
@@ -943,7 +1140,7 @@ int main(int argc, char *argv[])
QmlStreamWriter qml(&bytes);
qml.writeStartDocument();
- qml.writeLibraryImport(QLatin1String("QtQuick.tooling"), 1, 1);
+ qml.writeLibraryImport(QLatin1String("QtQuick.tooling"), 1, 2);
qml.write(QString("\n"
"// This file describes the plugin-supplied types contained in the library.\n"
"// It is used for QML tooling purposes only.\n"
@@ -952,6 +1149,10 @@ int main(int argc, char *argv[])
"// '%1 %2'\n"
"\n").arg(QFileInfo(args.at(0)).fileName()).arg(QStringList(args.mid(1)).join(QLatin1String(" "))));
qml.writeStartObject("Module");
+ QStringList quotedDependencies;
+ foreach (const QString &dep, dependencies)
+ quotedDependencies << enquote(dep);
+ qml.writeArrayBinding("dependencies", quotedDependencies);
// put the metaobjects into a map so they are always dumped in the same order
QMap<QString, const QMetaObject *> nameToMeta;
diff --git a/tools/qmlprofiler/qpacketprotocol.cpp b/tools/qmlprofiler/qpacketprotocol.cpp
index b6543013d9..096bc142c5 100644
--- a/tools/qmlprofiler/qpacketprotocol.cpp
+++ b/tools/qmlprofiler/qpacketprotocol.cpp
@@ -35,6 +35,7 @@
#include <QtCore/QBuffer>
#include <QtCore/QElapsedTimer>
+#include <private/qiodevice_p.h> // for qt_subtract_from_timeout
static const unsigned int MAX_PACKET_SIZE = 0x7FFFFFFF;
@@ -316,19 +317,6 @@ QPacket QPacketProtocol::read()
return rv;
}
-/*
- Returns the difference between msecs and elapsed. If msecs is -1,
- however, -1 is returned.
-*/
-static int qt_timeout_value(int msecs, int elapsed)
-{
- if (msecs == -1)
- return -1;
-
- int timeout = msecs - elapsed;
- return timeout < 0 ? 0 : timeout;
-}
-
/*!
This function locks until a new packet is available for reading and the
\l{QIODevice::}{readyRead()} signal has been emitted. The function
@@ -354,7 +342,7 @@ bool QPacketProtocol::waitForReadyRead(int msecs)
return false;
if (!d->waitingForPacket)
return true;
- msecs = qt_timeout_value(msecs, stopWatch.elapsed());
+ msecs = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
} while (true);
}
diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp
index 3a1815caa6..b8920cd853 100644
--- a/tools/qmlscene/main.cpp
+++ b/tools/qmlscene/main.cpp
@@ -158,7 +158,6 @@ struct Options
bool maximized;
bool fullscreen;
bool transparent;
- bool scenegraphOnGraphicsview;
bool clip;
bool versionDetection;
bool slowAnimations;