Merge lp:~timo-jyrinki/kubuntu-packaging/qtdeclarative-opensource-src_530ubuntu8 into lp:~kubuntu-packagers/kubuntu-packaging/qtdeclarative-opensource-src

Proposed by Timo Jyrinki
Status: Merged
Approved by: Timo Jyrinki
Approved revision: 164
Merged at revision: 162
Proposed branch: lp:~timo-jyrinki/kubuntu-packaging/qtdeclarative-opensource-src_530ubuntu8
Merge into: lp:~kubuntu-packagers/kubuntu-packaging/qtdeclarative-opensource-src
Diff against target: 742 lines (+647/-26)
8 files modified
debian/changelog (+18/-0)
debian/control (+2/-0)
debian/patches/8454a21b-Flickable-Cancel-interaction-on-interactive-changes.patch (+152/-0)
debian/patches/Fix-crash-when-deleting-component-in-Component.onCom.patch (+129/-0)
debian/patches/Fix-interaction-of-garbage-collector-with-JS-objects.patch (+335/-0)
debian/patches/parenttosubcreator_qqmlobjectcreator.patch (+0/-24)
debian/patches/series (+3/-1)
debian/rules (+8/-1)
To merge this branch: bzr merge lp:~timo-jyrinki/kubuntu-packaging/qtdeclarative-opensource-src_530ubuntu8
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Kubuntu Packagers Pending
Review via email: mp+229651@code.launchpad.net

Commit message

[ Michał Sawicz ]
 * debian/patches/8454a21b-Flickable-Cancel-interaction-on-interactive-changes.patch
   - Fix flickable interaction (LP: #1349705)
 * debian/control
   debian/rules
   Force gcc-4.8 to avoid symbols changes

[ Timo Jyrinki ]
 * debian/patches/parenttosubcreator_qqmlobjectcreator.patch:
   - Drop, rejected by upstream
 * debian/patches/Fix-crash-when-deleting-component-in-Component.onCom.patch
   debian/patches/Fix-interaction-of-garbage-collector-with-JS-objects.patch:
   - Replace the old patch with accepted upstream approach (LP: #1349297)

To post a comment you must log in.
Revision history for this message
Timo Jyrinki (timo-jyrinki) wrote :

Released, this is to trigger code coverage collection only.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Autolanding.
No commit message was specified in the merge proposal. Hit 'Add commit message' on the merge proposal web page or follow the link below. You can approve the merge proposal yourself to rerun.
https://code.launchpad.net/~timo-jyrinki/kubuntu-packaging/qtdeclarative-opensource-src_530ubuntu8/+merge/229651/+edit-commit-message

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/changelog'
--- debian/changelog 2014-07-07 08:43:27 +0000
+++ debian/changelog 2014-08-05 16:09:22 +0000
@@ -1,3 +1,21 @@
1qtdeclarative-opensource-src (5.3.0-3ubuntu8) utopic; urgency=medium
2
3 [ Michał Sawicz ]
4 * debian/patches/8454a21b-Flickable-Cancel-interaction-on-interactive-changes.patch
5 - Fix flickable interaction (LP: #1349705)
6 * debian/control
7 * debian/rules
8 - Force gcc-4.8 to avoid symbols changes
9
10 [ Timo Jyrinki ]
11 * debian/patches/parenttosubcreator_qqmlobjectcreator.patch:
12 - Drop, rejected by upstream
13 * debian/patches/Fix-crash-when-deleting-component-in-Component.onCom.patch
14 debian/patches/Fix-interaction-of-garbage-collector-with-JS-objects.patch:
15 - Replace the old patch with accepted upstream approach (LP: #1349297)
16
17 -- Timo Jyrinki <timo-jyrinki@ubuntu.com> Mon, 04 Aug 2014 10:58:28 +0000
18
1qtdeclarative-opensource-src (5.3.0-3ubuntu7) utopic; urgency=medium19qtdeclarative-opensource-src (5.3.0-3ubuntu7) utopic; urgency=medium
220
3 * debian/patches/Support-RFC2822Date-date-format-similar-to-V8.patch21 * debian/patches/Support-RFC2822Date-date-format-similar-to-V8.patch
422
=== modified file 'debian/control'
--- debian/control 2014-06-19 19:14:47 +0000
+++ debian/control 2014-08-05 16:09:22 +0000
@@ -11,6 +11,8 @@
11 Timo Jyrinki <timo@debian.org>11 Timo Jyrinki <timo@debian.org>
12Build-Depends: debhelper (>= 9),12Build-Depends: debhelper (>= 9),
13 dpkg-dev (>= 1.16.1),13 dpkg-dev (>= 1.16.1),
14# Avoiding symbols updates due to switch to gcc 4.9 by default.
15 g++-4.8,
14 libqt5xmlpatterns5-private-dev (>= 5.3.0-0~),16 libqt5xmlpatterns5-private-dev (>= 5.3.0-0~),
15 pkg-kde-tools (>= 0.15.12~),17 pkg-kde-tools (>= 0.15.12~),
16 python,18 python,
1719
=== added file 'debian/patches/8454a21b-Flickable-Cancel-interaction-on-interactive-changes.patch'
--- debian/patches/8454a21b-Flickable-Cancel-interaction-on-interactive-changes.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/8454a21b-Flickable-Cancel-interaction-on-interactive-changes.patch 2014-08-05 16:09:22 +0000
@@ -0,0 +1,152 @@
1From 8454a21b837ccf3968f6dbc56ed4f06d60d63c8f Mon Sep 17 00:00:00 2001
2From: Albert Astals Cid <albert.astals@canonical.com>
3Date: Wed, 23 Jul 2014 15:40:42 +0200
4Subject: [PATCH] Flickable: Cancel interaction on interactive changes
5
6Otherwise if you have a listview with a flickable inside with a mouseare inside
7the pressed is never set to false if you make the interactive property of the
8outer list depend on the moving of the inner flickable. This makes that when
9later you change currentIndex of the list and you have
10StrictlyEnforceRange set, the list won't move because it still thinks it is pressed
11
12Change-Id: I2c2021f486fc0a31840c3f2199bc7cb76dc01e3e
13Reviewed-by: Martin Jones <martin.jones@jollamobile.com>
14---
15 src/quick/items/qquickflickable.cpp | 41 ++++++++++++++--------------
16 src/quick/items/qquickflickable_p_p.h | 2 ++
17 tests/auto/qmltest/listview/tst_listview.qml | 41 ++++++++++++++++++++++++++++
18 3 files changed, 63 insertions(+), 21 deletions(-)
19
20diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
21index ee71ea8..63dde66 100644
22--- a/src/quick/items/qquickflickable.cpp
23+++ b/src/quick/items/qquickflickable.cpp
24@@ -763,15 +763,8 @@ void QQuickFlickable::setInteractive(bool interactive)
25 Q_D(QQuickFlickable);
26 if (interactive != d->interactive) {
27 d->interactive = interactive;
28- if (!interactive && (d->hData.flicking || d->vData.flicking)) {
29- d->clearTimeline();
30- d->hData.vTime = d->vData.vTime = d->timeline.time();
31- d->hData.flicking = false;
32- d->vData.flicking = false;
33- emit flickingChanged();
34- emit flickingHorizontallyChanged();
35- emit flickingVerticallyChanged();
36- emit flickEnded();
37+ if (!interactive) {
38+ d->cancelInteraction();
39 }
40 emit interactiveChanged();
41 }
42@@ -2015,18 +2008,24 @@ bool QQuickFlickable::yflick() const
43 void QQuickFlickable::mouseUngrabEvent()
44 {
45 Q_D(QQuickFlickable);
46- if (d->pressed) {
47- // if our mouse grab has been removed (probably by another Flickable),
48- // fix our state
49- d->clearDelayedPress();
50- d->pressed = false;
51- d->draggingEnding();
52- d->stealMouse = false;
53- setKeepMouseGrab(false);
54- d->fixupX();
55- d->fixupY();
56- if (!d->isViewMoving())
57- movementEnding();
58+ // if our mouse grab has been removed (probably by another Flickable),
59+ // fix our state
60+ d->cancelInteraction();
61+}
62+
63+void QQuickFlickablePrivate::cancelInteraction()
64+{
65+ Q_Q(QQuickFlickable);
66+ if (pressed) {
67+ clearDelayedPress();
68+ pressed = false;
69+ draggingEnding();
70+ stealMouse = false;
71+ q->setKeepMouseGrab(false);
72+ fixupX();
73+ fixupY();
74+ if (!isViewMoving())
75+ q->movementEnding();
76 }
77 }
78
79diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h
80index 33a642e..13af2e0 100644
81--- a/src/quick/items/qquickflickable_p_p.h
82+++ b/src/quick/items/qquickflickable_p_p.h
83@@ -200,6 +200,8 @@ public:
84
85 bool isViewMoving() const;
86
87+ void cancelInteraction();
88+
89 public:
90 QQuickItem *contentItem;
91
92diff --git a/tests/auto/qmltest/listview/tst_listview.qml b/tests/auto/qmltest/listview/tst_listview.qml
93index 03be579..069b62a 100644
94--- a/tests/auto/qmltest/listview/tst_listview.qml
95+++ b/tests/auto/qmltest/listview/tst_listview.qml
96@@ -108,6 +108,33 @@ Item {
97 property int createdDelegates: 0
98 }
99
100+ ListView
101+ {
102+ id: listInteractiveCurrentIndexEnforce
103+ width: 600
104+ height: 600
105+
106+ snapMode: ListView.SnapOneItem
107+ orientation: ListView.Horizontal
108+ interactive: !currentItem.moving
109+ highlightRangeMode: ListView.StrictlyEnforceRange
110+
111+ model: 4
112+
113+ focus: true
114+ Keys.onPressed: if (event.key == Qt.Key_K) currentIndex = currentIndex + 1;
115+
116+ delegate: Flickable {
117+ width: 600
118+ height: 600
119+ contentWidth: 600
120+ contentHeight: 1200
121+
122+ MouseArea { anchors.fill: parent }
123+ Rectangle { anchors.fill: parent; color: index == 0 ? "red" : index == 1 ? "green" : index == 2 ? "blue" : "white" }
124+ }
125+ }
126+
127 Component {
128 id: delegateModelAfterCreateComponent
129 Rectangle {
130@@ -272,5 +299,19 @@ Item {
131 listViewDelegateModelAfterCreate.model = 40;
132 verify(listViewDelegateModelAfterCreate.createdDelegates > 0);
133 }
134+
135+ function test_listInteractiveCurrentIndexEnforce() {
136+ mousePress(listInteractiveCurrentIndexEnforce, 10, 50);
137+ mouseMove(listInteractiveCurrentIndexEnforce, 10, 40);
138+ mouseMove(listInteractiveCurrentIndexEnforce, 10, 30);
139+ mouseMove(listInteractiveCurrentIndexEnforce, 10, 20);
140+ mouseMove(listInteractiveCurrentIndexEnforce, 10, 10);
141+ compare(listInteractiveCurrentIndexEnforce.interactive, false);
142+ mouseRelease(listInteractiveCurrentIndexEnforce, 10, 10);
143+ tryCompare(listInteractiveCurrentIndexEnforce, "interactive", true);
144+ keyClick("k");
145+ compare(listInteractiveCurrentIndexEnforce.currentIndex, 1);
146+ tryCompare(listInteractiveCurrentIndexEnforce, "contentX", listInteractiveCurrentIndexEnforce.width);
147+ }
148 }
149 }
150--
1512.0.1
152
0153
=== added file 'debian/patches/Fix-crash-when-deleting-component-in-Component.onCom.patch'
--- debian/patches/Fix-crash-when-deleting-component-in-Component.onCom.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/Fix-crash-when-deleting-component-in-Component.onCom.patch 2014-08-05 16:09:22 +0000
@@ -0,0 +1,129 @@
1From 195b998175b629e6e915588e66991f74cffa4e48 Mon Sep 17 00:00:00 2001
2From: Simon Hausmann <simon.hausmann@digia.com>
3Date: Fri, 20 Jun 2014 17:26:57 +0200
4Subject: [PATCH] Fix crash when deleting component in Component.onComplete
5 through loader
6
7This is a regression introduced with Qt 5.3.0. The recursion watcher code that
8is supposed to handle the test case of QTBUG-39775 can detect the recursion
9into the object creator. However the boolean that indicates the recursion is a
10member of a structure that's deleted afterwards. To avoid access to deleted
11memory, this patch simply reference counts data structure shared between the
12creators and also wraps the recursion watcher into a convenience class that
13also increases/decreases the reference count accordingly.
14
15Change-Id: I8d2e3e200ab1295e89d951e09f187d382a056d5a
16Task-number: QTBUG-39775
17Reviewed-by: Lars Knoll <lars.knoll@digia.com>
18---
19 src/qml/qml/qqmlobjectcreator.cpp | 17 ++++++++++++-----
20 src/qml/qml/qqmlobjectcreator_p.h | 18 ++++++++++++++++--
21 2 files changed, 28 insertions(+), 7 deletions(-)
22
23diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
24index 16c9dd7..36c7dfb 100644
25--- a/src/qml/qml/qqmlobjectcreator.cpp
26+++ b/src/qml/qml/qqmlobjectcreator.cpp
27@@ -91,7 +91,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompile
28 init(parentContext);
29
30 sharedState = new QQmlObjectCreatorSharedState;
31- sharedState.setFlag(); // We own it, so we must delete it
32+ topLevelCreator = true;
33 sharedState->componentAttached = 0;
34 sharedState->allCreatedBindings.allocate(compiledData->totalBindingsCount);
35 sharedState->allParserStatusCallbacks.allocate(compiledData->totalParserStatusCount);
36@@ -115,6 +115,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompile
37 init(parentContext);
38
39 sharedState = inheritedSharedState;
40+ topLevelCreator = false;
41 }
42
43 void QQmlObjectCreator::init(QQmlContextData *providedParentContext)
44@@ -139,9 +140,9 @@ void QQmlObjectCreator::init(QQmlContextData *providedParentContext)
45
46 QQmlObjectCreator::~QQmlObjectCreator()
47 {
48- if (sharedState.flag()) {
49+ if (topLevelCreator) {
50 {
51- QRecursionWatcher<QQmlObjectCreatorSharedState, &QQmlObjectCreatorSharedState::recursionNode> watcher(sharedState.data());
52+ QQmlObjectCreatorRecursionWatcher watcher(this);
53 }
54 for (int i = 0; i < sharedState->allCreatedBindings.count(); ++i) {
55 QQmlAbstractBinding *b = sharedState->allCreatedBindings.at(i);
56@@ -157,7 +158,6 @@ QQmlObjectCreator::~QQmlObjectCreator()
57 QQmlComponentAttached *a = sharedState->componentAttached;
58 a->rem();
59 }
60- delete sharedState.data();
61 }
62 }
63
64@@ -1172,7 +1172,7 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
65 Q_ASSERT(phase == ObjectsCreated || phase == Finalizing);
66 phase = Finalizing;
67
68- QRecursionWatcher<QQmlObjectCreatorSharedState, &QQmlObjectCreatorSharedState::recursionNode> watcher(sharedState.data());
69+ QQmlObjectCreatorRecursionWatcher watcher(this);
70 ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine));
71
72 {
73@@ -1334,3 +1334,10 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
74 }
75
76
77+
78+
79+QQmlObjectCreatorRecursionWatcher::QQmlObjectCreatorRecursionWatcher(QQmlObjectCreator *creator)
80+ : sharedState(creator->sharedState)
81+ , watcher(creator->sharedState.data())
82+{
83+}
84diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
85index 379a3b2..ad2d676 100644
86--- a/src/qml/qml/qqmlobjectcreator_p.h
87+++ b/src/qml/qml/qqmlobjectcreator_p.h
88@@ -57,7 +57,7 @@ struct QQmlTypeCompiler;
89 class QQmlInstantiationInterrupt;
90 struct QQmlVmeProfiler;
91
92-struct QQmlObjectCreatorSharedState
93+struct QQmlObjectCreatorSharedState : public QSharedData
94 {
95 QQmlContextData *rootContext;
96 QQmlContextData *creationContext;
97@@ -128,7 +128,8 @@ private:
98 const QVector<QQmlPropertyCache *> &propertyCaches;
99 const QVector<QByteArray> &vmeMetaObjectData;
100 QHash<int, int> objectIndexToId;
101- QFlagPointer<QQmlObjectCreatorSharedState> sharedState;
102+ QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState;
103+ bool topLevelCreator;
104 void *activeVMEDataForRootContext;
105
106 QObject *_qobject;
107@@ -142,6 +143,19 @@ private:
108 QQmlVMEMetaObject *_vmeMetaObject;
109 QQmlListProperty<void> _currentList;
110 QV4::ExecutionContext *_qmlContext;
111+
112+ friend struct QQmlObjectCreatorRecursionWatcher;
113+};
114+
115+struct QQmlObjectCreatorRecursionWatcher
116+{
117+ QQmlObjectCreatorRecursionWatcher(QQmlObjectCreator *creator);
118+
119+ bool hasRecursed() const { return watcher.hasRecursed(); }
120+
121+private:
122+ QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState;
123+ QRecursionWatcher<QQmlObjectCreatorSharedState, &QQmlObjectCreatorSharedState::recursionNode> watcher;
124 };
125
126 QT_END_NAMESPACE
127--
1282.0.1
129
0130
=== added file 'debian/patches/Fix-interaction-of-garbage-collector-with-JS-objects.patch'
--- debian/patches/Fix-interaction-of-garbage-collector-with-JS-objects.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/Fix-interaction-of-garbage-collector-with-JS-objects.patch 2014-08-05 16:09:22 +0000
@@ -0,0 +1,335 @@
1From 14bc8dc3f3016889cfcbdbe7309b09be7687ebe0 Mon Sep 17 00:00:00 2001
2From: Simon Hausmann <simon.hausmann@digia.com>
3Date: Wed, 14 May 2014 16:04:33 +0200
4Subject: [PATCH] Fix interaction of garbage collector with JS objects during
5 QML type instantiation
6
7It may happen that during the lengthy process of instantiating a tree of
8objects for QML, the garbage collector runs.
9
10For objects created by QML we support different ownership models, for example
11in QtQuick visual parents keep their visual children alive, despite perhaps a
12lack of QObject parentship. That ownership becomes active once the QML
13autoparent function has assigned the correct visual parent, which happens after
14object instantiation (after QQmlObjectCreator).
15
16Similarly when a composite type is created, its QObject parent is only set
17after all properties have been set. The root QObject is kept alive through a
18special boolean, but if the sub-objects aren't children yet, their JS wrapper
19might get deleted. For composite types with var properties, that also means
20their var properties get deleted, such as the model property of TableView.qml
21in the bug report.
22
23In the future we want to support creating QWidget hierarchies with QML, which
24also for layouts may rely on a delayed parent assignment for layouts.
25
26To accommodate all this, this patch introduces an array on the JS stack that
27keeps track of all JS wrappers for all QObjects created. This array is alive
28during object tree creation. Afterwards, the different ownership models take
29over, for example the auto parent function assigning a visual parent.
30
31This patch also fixes an off-by-one in the total object count calculation
32for composite types, where when instantiating a composite type as a sub-object
33we counted the sub composite's object count but forgot the object itself.
34
35Task-number: QTBUG-38835
36Task-number: QTBUG-39966
37Change-Id: I6104b2434510642081e0c54793ed296adeca7481
38Reviewed-by: Lars Knoll <lars.knoll@digia.com>
39---
40 src/qml/compiler/qqmltypecompiler.cpp | 4 +-
41 src/qml/qml/qqmlobjectcreator.cpp | 27 +++++++---
42 src/qml/qml/qqmlobjectcreator_p.h | 1 +
43 tests/auto/qml/qqmlecmascript/testtypes.cpp | 60 ++++++++++++++++++++++
44 tests/auto/qml/qqmlecmascript/testtypes.h | 45 ++++++++++++++++
45 .../auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 28 ++++++++++
46 6 files changed, 157 insertions(+), 8 deletions(-)
47
48diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
49index 60a0829..dacaa14 100644
50--- a/src/qml/compiler/qqmltypecompiler.cpp
51+++ b/src/qml/compiler/qqmltypecompiler.cpp
52@@ -277,12 +277,12 @@ bool QQmlTypeCompiler::compile()
53 if (qmlType->parserStatusCast() != -1)
54 ++parserStatusCount;
55 }
56+ ++objectCount;
57 if (typeRef->component) {
58 bindingCount += typeRef->component->totalBindingsCount;
59 parserStatusCount += typeRef->component->totalParserStatusCount;
60 objectCount += typeRef->component->totalObjectCount;
61- } else
62- ++objectCount;
63+ }
64 }
65 }
66
67diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
68index 36c7dfb..1de467b 100644
69--- a/src/qml/qml/qqmlobjectcreator.cpp
70+++ b/src/qml/qml/qqmlobjectcreator.cpp
71@@ -96,6 +96,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompile
72 sharedState->allCreatedBindings.allocate(compiledData->totalBindingsCount);
73 sharedState->allParserStatusCallbacks.allocate(compiledData->totalParserStatusCount);
74 sharedState->allCreatedObjects.allocate(compiledData->totalObjectCount);
75+ sharedState->allJavaScriptObjects = 0;
76 sharedState->creationContext = creationContext;
77 sharedState->rootContext = 0;
78
79@@ -195,6 +196,13 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
80 sharedState->rootContext->isRootObjectInCreation = true;
81 }
82
83+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
84+ QV4::Scope scope(v4);
85+
86+ Q_ASSERT(sharedState->allJavaScriptObjects || topLevelCreator);
87+ if (topLevelCreator)
88+ sharedState->allJavaScriptObjects = scope.alloc(compiledData->totalObjectCount);
89+
90 QVector<QQmlContextData::ObjectIdMapping> mapping(objectIndexToId.count());
91 for (QHash<int, int>::ConstIterator it = objectIndexToId.constBegin(), end = objectIndexToId.constEnd();
92 it != end; ++it) {
93@@ -208,8 +216,6 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
94 context->setIdPropertyData(mapping);
95
96 if (subComponentIndex == -1) {
97- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
98- QV4::Scope scope(v4);
99 QV4::ScopedObject scripts(scope, v4->newArrayObject(compiledData->scripts.count()));
100 context->importedScripts = scripts;
101 for (int i = 0; i < compiledData->scripts.count(); ++i) {
102@@ -230,6 +236,9 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
103 ddata->compiledData->addref();
104 }
105
106+ if (topLevelCreator)
107+ sharedState->allJavaScriptObjects = 0;
108+
109 phase = CreatingObjectsPhase2;
110
111 if (interrupt && interrupt->shouldInterrupt())
112@@ -258,8 +267,11 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
113
114 QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
115 QV4::Scope valueScope(v4);
116- QV4::ScopedValue scopeObjectProtector(valueScope, declarativeData->jsWrapper.value());
117- Q_UNUSED(scopeObjectProtector);
118+
119+ Q_ASSERT(topLevelCreator);
120+ Q_ASSERT(!sharedState->allJavaScriptObjects);
121+ sharedState->allJavaScriptObjects = valueScope.alloc(compiledData->totalObjectCount);
122+
123 QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, _scopeObject));
124 QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, qmlScope));
125 QV4::ExecutionContext *qmlContext = qmlBindingWrapper->context();
126@@ -1150,9 +1162,12 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
127 qSwap(_scopeObject, scopeObject);
128
129 QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
130+
131+ Q_ASSERT(sharedState->allJavaScriptObjects);
132+ QV4::ValueRef ref = QV4::ValueRef::fromRawValue(sharedState->allJavaScriptObjects++);
133+ ref = QV4::QObjectWrapper::wrap(v4, instance);
134+
135 QV4::Scope valueScope(v4);
136- QV4::ScopedValue scopeObjectProtector(valueScope, ddata ? ddata->jsWrapper.value() : 0);
137- Q_UNUSED(scopeObjectProtector);
138 QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, _scopeObject));
139 QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, qmlScope));
140 QV4::ExecutionContext *qmlContext = qmlBindingWrapper->context();
141diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
142index ad2d676..fb4d71d 100644
143--- a/src/qml/qml/qqmlobjectcreator_p.h
144+++ b/src/qml/qml/qqmlobjectcreator_p.h
145@@ -64,6 +64,7 @@ struct QQmlObjectCreatorSharedState : public QSharedData
146 QFiniteStack<QQmlAbstractBinding*> allCreatedBindings;
147 QFiniteStack<QQmlParserStatus*> allParserStatusCallbacks;
148 QFiniteStack<QObject*> allCreatedObjects;
149+ QV4::Value *allJavaScriptObjects; // pointer to vector on JS stack to reference JS wrappers during creation phase.
150 QQmlComponentAttached *componentAttached;
151 QList<QQmlEnginePrivate::FinalizeCallback> finalizeCallbacks;
152 QQmlVmeProfiler profiler;
153diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp
154index eb06b9e..560d860 100644
155--- a/tests/auto/qml/qqmlecmascript/testtypes.cpp
156+++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp
157@@ -300,6 +300,62 @@ static QObject *create_singletonWithEnum(QQmlEngine *, QJSEngine *)
158 return new SingletonWithEnum;
159 }
160
161+QObjectContainer::QObjectContainer()
162+ : widgetParent(0)
163+ , gcOnAppend(false)
164+{}
165+
166+QQmlListProperty<QObject> QObjectContainer::data()
167+{
168+ return QQmlListProperty<QObject>(this, 0, children_append, children_count, children_at, children_clear);
169+}
170+
171+void QObjectContainer::children_append(QQmlListProperty<QObject> *prop, QObject *o)
172+{
173+ QObjectContainer *that = static_cast<QObjectContainer*>(prop->object);
174+ that->dataChildren.append(o);
175+ QObject::connect(o, SIGNAL(destroyed(QObject*)), prop->object, SLOT(childDestroyed(QObject*)));
176+
177+ if (that->gcOnAppend) {
178+ QQmlEngine *engine = qmlEngine(that);
179+ engine->collectGarbage();
180+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
181+ QCoreApplication::processEvents();
182+ }
183+}
184+
185+int QObjectContainer::children_count(QQmlListProperty<QObject> *prop)
186+{
187+ return static_cast<QObjectContainer*>(prop->object)->dataChildren.count();
188+}
189+
190+QObject *QObjectContainer::children_at(QQmlListProperty<QObject> *prop, int index)
191+{
192+ return static_cast<QObjectContainer*>(prop->object)->dataChildren.at(index);
193+}
194+
195+void QObjectContainer::children_clear(QQmlListProperty<QObject> *prop)
196+{
197+ QObjectContainer *that = static_cast<QObjectContainer*>(prop->object);
198+ foreach (QObject *c, that->dataChildren)
199+ QObject::disconnect(c, SIGNAL(destroyed(QObject*)), that, SLOT(childDestroyed(QObject*)));
200+ that->dataChildren.clear();
201+}
202+
203+void QObjectContainer::childDestroyed(QObject *child) {
204+ dataChildren.removeAll(child);
205+}
206+
207+void FloatingQObject::classBegin()
208+{
209+ setParent(0);
210+}
211+
212+void FloatingQObject::componentComplete()
213+{
214+ Q_ASSERT(!parent());
215+}
216+
217 void registerTypes()
218 {
219 qmlRegisterType<MyQmlObject>("Qt.test", 1,0, "MyQmlObjectAlias");
220@@ -381,6 +437,10 @@ void registerTypes()
221 qmlRegisterSingletonType<testImportOrderApi>("Qt.test.importOrderApi2",1,0,"Data",testImportOrder_api2);
222
223 qmlRegisterSingletonType<SingletonWithEnum>("Qt.test.singletonWithEnum", 1, 0, "SingletonWithEnum", create_singletonWithEnum);
224+
225+ qmlRegisterType<QObjectContainer>("Qt.test", 1, 0, "QObjectContainer");
226+ qmlRegisterType<QObjectContainerWithGCOnAppend>("Qt.test", 1, 0, "QObjectContainerWithGCOnAppend");
227+ qmlRegisterType<FloatingQObject>("Qt.test", 1, 0, "FloatingQObject");
228 }
229
230 #include "testtypes.moc"
231diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h
232index 928d594..d5a1220 100644
233--- a/tests/auto/qml/qqmlecmascript/testtypes.h
234+++ b/tests/auto/qml/qqmlecmascript/testtypes.h
235@@ -1661,6 +1661,51 @@ public:
236 };
237 };
238
239+// Like QtObject, but with default property
240+class QObjectContainer : public QObject
241+{
242+ Q_OBJECT
243+ Q_CLASSINFO("DefaultProperty", "data")
244+ Q_PROPERTY(QQmlListProperty<QObject> data READ data DESIGNABLE false)
245+public:
246+ QObjectContainer();
247+
248+ QQmlListProperty<QObject> data();
249+
250+ static void children_append(QQmlListProperty<QObject> *prop, QObject *o);
251+ static int children_count(QQmlListProperty<QObject> *prop);
252+ static QObject *children_at(QQmlListProperty<QObject> *prop, int index);
253+ static void children_clear(QQmlListProperty<QObject> *prop);
254+
255+ QList<QObject*> dataChildren;
256+ QWidget *widgetParent;
257+ bool gcOnAppend;
258+
259+protected slots:
260+ void childDestroyed(QObject *child);
261+};
262+
263+class QObjectContainerWithGCOnAppend : public QObjectContainer
264+{
265+ Q_OBJECT
266+public:
267+ QObjectContainerWithGCOnAppend()
268+ {
269+ gcOnAppend = true;
270+ }
271+};
272+
273+class FloatingQObject : public QObject, public QQmlParserStatus
274+{
275+ Q_OBJECT
276+ Q_INTERFACES(QQmlParserStatus)
277+public:
278+ FloatingQObject() {}
279+
280+ virtual void classBegin();
281+ virtual void componentComplete();
282+};
283+
284 void registerTypes();
285
286 #endif // TESTTYPES_H
287diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
288index a1e36b4..a9486a8 100644
289--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
290+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
291@@ -322,6 +322,7 @@ private slots:
292 void varPropertyAccessOnObjectWithInvalidContext();
293 void importedScriptsAccessOnObjectWithInvalidContext();
294 void contextObjectOnLazyBindings();
295+ void garbageCollectionDuringCreation();
296
297 private:
298 // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
299@@ -7603,6 +7604,33 @@ void tst_qqmlecmascript::contextObjectOnLazyBindings()
300 QCOMPARE(subObject->property("testValue").toInt(), int(42));
301 }
302
303+void tst_qqmlecmascript::garbageCollectionDuringCreation()
304+{
305+ QQmlComponent component(&engine);
306+ component.setData("import Qt.test 1.0\n"
307+ "QObjectContainerWithGCOnAppend {\n"
308+ " objectName: \"root\"\n"
309+ " FloatingQObject {\n"
310+ " objectName: \"parentLessChild\"\n"
311+ " property var blah;\n" // Ensure we have JS wrapper
312+ " }\n"
313+ "}\n",
314+ QUrl());
315+
316+ QScopedPointer<QObject> object(component.create());
317+ QVERIFY(!object.isNull());
318+
319+ QObjectContainer *container = qobject_cast<QObjectContainer*>(object.data());
320+ QCOMPARE(container->dataChildren.count(), 1);
321+
322+ QObject *child = container->dataChildren.first();
323+ QQmlData *ddata = QQmlData::get(child);
324+ QVERIFY(!ddata->jsWrapper.isNullOrUndefined());
325+
326+ gc(engine);
327+ QCOMPARE(container->dataChildren.count(), 0);
328+}
329+
330 QTEST_MAIN(tst_qqmlecmascript)
331
332 #include "tst_qqmlecmascript.moc"
333--
3342.0.1
335
0336
=== removed file 'debian/patches/parenttosubcreator_qqmlobjectcreator.patch'
--- debian/patches/parenttosubcreator_qqmlobjectcreator.patch 2014-07-01 08:22:15 +0000
+++ debian/patches/parenttosubcreator_qqmlobjectcreator.patch 1970-01-01 00:00:00 +0000
@@ -1,24 +0,0 @@
1commit 249b1a73fdb01fc27e036fc4334925674c281793
2Author: Albert Astals Cid <albert.astals@canonical.com>
3Date: Mon Jun 30 17:22:55 2014 +0200
4
5 Pass down parent to subCreator
6
7 Otherwise the object might get garbage collected while it's being created
8
9 Change-Id: I553c3432d5242bcd89723b72d8f8ae82577abaf9
10 Task-number: QTBUG-39966
11
12diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
13index 36c7dfb..cceb9b2 100644
14--- a/src/qml/qml/qqmlobjectcreator.cpp
15+++ b/src/qml/qml/qqmlobjectcreator.cpp
16@@ -1076,7 +1076,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
17 }
18
19 QQmlObjectCreator subCreator(context, typeRef->component, sharedState.data());
20- instance = subCreator.create();
21+ instance = subCreator.create(-1, parent);
22 if (!instance) {
23 errors += subCreator.errors;
24 return 0;
250
=== modified file 'debian/patches/series'
--- debian/patches/series 2014-07-07 08:45:33 +0000
+++ debian/patches/series 2014-08-05 16:09:22 +0000
@@ -6,5 +6,7 @@
6v4_yarr_jit_push_pop_addressTempRegister.patch6v4_yarr_jit_push_pop_addressTempRegister.patch
7fix_qqmlobjectcreator.patch7fix_qqmlobjectcreator.patch
8Implement-proper-support-for-layoutChange-in-QQmlDel.patch8Implement-proper-support-for-layoutChange-in-QQmlDel.patch
9parenttosubcreator_qqmlobjectcreator.patch9Fix-crash-when-deleting-component-in-Component.onCom.patch
10Fix-interaction-of-garbage-collector-with-JS-objects.patch
10Support-RFC2822Date-date-format-similar-to-V8.patch11Support-RFC2822Date-date-format-similar-to-V8.patch
128454a21b-Flickable-Cancel-interaction-on-interactive-changes.patch
1113
=== modified file 'debian/rules'
--- debian/rules 2014-05-28 05:57:55 +0000
+++ debian/rules 2014-08-05 16:09:22 +0000
@@ -1,10 +1,17 @@
1#!/usr/bin/make -f1#!/usr/bin/make -f
22
3include /usr/share/dpkg/default.mk
4
3# Uncomment this to turn on verbose mode.5# Uncomment this to turn on verbose mode.
4#export DH_VERBOSE=16#export DH_VERBOSE=1
57
6DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)8DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
79
10# Explicitly selecting a G{CC,++}-version here to avoid symbol changes
11# because of the default gcc switch.
12export CC=$(DEB_HOST_GNU_TYPE)-gcc-4.8
13export CXX=$(DEB_HOST_GNU_TYPE)-g++-4.8
14
8export CFLAGS := $(shell dpkg-buildflags --get CFLAGS) $(shell dpkg-buildflags --get CPPFLAGS)15export CFLAGS := $(shell dpkg-buildflags --get CFLAGS) $(shell dpkg-buildflags --get CPPFLAGS)
9export CXXFLAGS := $(shell dpkg-buildflags --get CXXFLAGS) $(shell dpkg-buildflags --get CPPFLAGS)16export CXXFLAGS := $(shell dpkg-buildflags --get CXXFLAGS) $(shell dpkg-buildflags --get CPPFLAGS)
10export LDFLAGS := $(shell dpkg-buildflags --get LDFLAGS) -Wl,--as-needed17export LDFLAGS := $(shell dpkg-buildflags --get LDFLAGS) -Wl,--as-needed
@@ -14,7 +21,7 @@
14 dh $@ --parallel --with pkgkde_symbolshelper --dbg-package=qtdeclarative5-dbg21 dh $@ --parallel --with pkgkde_symbolshelper --dbg-package=qtdeclarative5-dbg
1522
16override_dh_auto_configure:23override_dh_auto_configure:
17 qmake QT_BUILD_PARTS+=tests24 qmake QT_BUILD_PARTS+=tests QMAKE_CC=$(CC) QMAKE_CXX=$(CXX)
1825
19override_dh_auto_build-indep:26override_dh_auto_build-indep:
20 dh_auto_build -Smakefile -- html_docs27 dh_auto_build -Smakefile -- html_docs

Subscribers

People subscribed via source and target branches