Merge lp:~timo-jyrinki/kubuntu-packaging/qtdeclarative-opensource-src_530ubuntu8 into lp:~kubuntu-packagers/kubuntu-packaging/qtdeclarative-opensource-src
- qtdeclarative-opensource-src_530ubuntu8
- Merge into qtdeclarative-opensource-src
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 | ||||
Related bugs: |
|
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/
- Fix flickable interaction (LP: #1349705)
* debian/control
debian/rules
Force gcc-4.8 to avoid symbols changes
[ Timo Jyrinki ]
* debian/
- Drop, rejected by upstream
* debian/
debian/
- Replace the old patch with accepted upstream approach (LP: #1349297)
Description of the change
Timo Jyrinki (timo-jyrinki) wrote : | # |
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:/
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:164
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'debian/changelog' |
2 | --- debian/changelog 2014-07-07 08:43:27 +0000 |
3 | +++ debian/changelog 2014-08-05 16:09:22 +0000 |
4 | @@ -1,3 +1,21 @@ |
5 | +qtdeclarative-opensource-src (5.3.0-3ubuntu8) utopic; urgency=medium |
6 | + |
7 | + [ Michał Sawicz ] |
8 | + * debian/patches/8454a21b-Flickable-Cancel-interaction-on-interactive-changes.patch |
9 | + - Fix flickable interaction (LP: #1349705) |
10 | + * debian/control |
11 | + * debian/rules |
12 | + - Force gcc-4.8 to avoid symbols changes |
13 | + |
14 | + [ Timo Jyrinki ] |
15 | + * debian/patches/parenttosubcreator_qqmlobjectcreator.patch: |
16 | + - Drop, rejected by upstream |
17 | + * debian/patches/Fix-crash-when-deleting-component-in-Component.onCom.patch |
18 | + debian/patches/Fix-interaction-of-garbage-collector-with-JS-objects.patch: |
19 | + - Replace the old patch with accepted upstream approach (LP: #1349297) |
20 | + |
21 | + -- Timo Jyrinki <timo-jyrinki@ubuntu.com> Mon, 04 Aug 2014 10:58:28 +0000 |
22 | + |
23 | qtdeclarative-opensource-src (5.3.0-3ubuntu7) utopic; urgency=medium |
24 | |
25 | * debian/patches/Support-RFC2822Date-date-format-similar-to-V8.patch |
26 | |
27 | === modified file 'debian/control' |
28 | --- debian/control 2014-06-19 19:14:47 +0000 |
29 | +++ debian/control 2014-08-05 16:09:22 +0000 |
30 | @@ -11,6 +11,8 @@ |
31 | Timo Jyrinki <timo@debian.org> |
32 | Build-Depends: debhelper (>= 9), |
33 | dpkg-dev (>= 1.16.1), |
34 | +# Avoiding symbols updates due to switch to gcc 4.9 by default. |
35 | + g++-4.8, |
36 | libqt5xmlpatterns5-private-dev (>= 5.3.0-0~), |
37 | pkg-kde-tools (>= 0.15.12~), |
38 | python, |
39 | |
40 | === added file 'debian/patches/8454a21b-Flickable-Cancel-interaction-on-interactive-changes.patch' |
41 | --- debian/patches/8454a21b-Flickable-Cancel-interaction-on-interactive-changes.patch 1970-01-01 00:00:00 +0000 |
42 | +++ debian/patches/8454a21b-Flickable-Cancel-interaction-on-interactive-changes.patch 2014-08-05 16:09:22 +0000 |
43 | @@ -0,0 +1,152 @@ |
44 | +From 8454a21b837ccf3968f6dbc56ed4f06d60d63c8f Mon Sep 17 00:00:00 2001 |
45 | +From: Albert Astals Cid <albert.astals@canonical.com> |
46 | +Date: Wed, 23 Jul 2014 15:40:42 +0200 |
47 | +Subject: [PATCH] Flickable: Cancel interaction on interactive changes |
48 | + |
49 | +Otherwise if you have a listview with a flickable inside with a mouseare inside |
50 | +the pressed is never set to false if you make the interactive property of the |
51 | +outer list depend on the moving of the inner flickable. This makes that when |
52 | +later you change currentIndex of the list and you have |
53 | +StrictlyEnforceRange set, the list won't move because it still thinks it is pressed |
54 | + |
55 | +Change-Id: I2c2021f486fc0a31840c3f2199bc7cb76dc01e3e |
56 | +Reviewed-by: Martin Jones <martin.jones@jollamobile.com> |
57 | +--- |
58 | + src/quick/items/qquickflickable.cpp | 41 ++++++++++++++-------------- |
59 | + src/quick/items/qquickflickable_p_p.h | 2 ++ |
60 | + tests/auto/qmltest/listview/tst_listview.qml | 41 ++++++++++++++++++++++++++++ |
61 | + 3 files changed, 63 insertions(+), 21 deletions(-) |
62 | + |
63 | +diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp |
64 | +index ee71ea8..63dde66 100644 |
65 | +--- a/src/quick/items/qquickflickable.cpp |
66 | ++++ b/src/quick/items/qquickflickable.cpp |
67 | +@@ -763,15 +763,8 @@ void QQuickFlickable::setInteractive(bool interactive) |
68 | + Q_D(QQuickFlickable); |
69 | + if (interactive != d->interactive) { |
70 | + d->interactive = interactive; |
71 | +- if (!interactive && (d->hData.flicking || d->vData.flicking)) { |
72 | +- d->clearTimeline(); |
73 | +- d->hData.vTime = d->vData.vTime = d->timeline.time(); |
74 | +- d->hData.flicking = false; |
75 | +- d->vData.flicking = false; |
76 | +- emit flickingChanged(); |
77 | +- emit flickingHorizontallyChanged(); |
78 | +- emit flickingVerticallyChanged(); |
79 | +- emit flickEnded(); |
80 | ++ if (!interactive) { |
81 | ++ d->cancelInteraction(); |
82 | + } |
83 | + emit interactiveChanged(); |
84 | + } |
85 | +@@ -2015,18 +2008,24 @@ bool QQuickFlickable::yflick() const |
86 | + void QQuickFlickable::mouseUngrabEvent() |
87 | + { |
88 | + Q_D(QQuickFlickable); |
89 | +- if (d->pressed) { |
90 | +- // if our mouse grab has been removed (probably by another Flickable), |
91 | +- // fix our state |
92 | +- d->clearDelayedPress(); |
93 | +- d->pressed = false; |
94 | +- d->draggingEnding(); |
95 | +- d->stealMouse = false; |
96 | +- setKeepMouseGrab(false); |
97 | +- d->fixupX(); |
98 | +- d->fixupY(); |
99 | +- if (!d->isViewMoving()) |
100 | +- movementEnding(); |
101 | ++ // if our mouse grab has been removed (probably by another Flickable), |
102 | ++ // fix our state |
103 | ++ d->cancelInteraction(); |
104 | ++} |
105 | ++ |
106 | ++void QQuickFlickablePrivate::cancelInteraction() |
107 | ++{ |
108 | ++ Q_Q(QQuickFlickable); |
109 | ++ if (pressed) { |
110 | ++ clearDelayedPress(); |
111 | ++ pressed = false; |
112 | ++ draggingEnding(); |
113 | ++ stealMouse = false; |
114 | ++ q->setKeepMouseGrab(false); |
115 | ++ fixupX(); |
116 | ++ fixupY(); |
117 | ++ if (!isViewMoving()) |
118 | ++ q->movementEnding(); |
119 | + } |
120 | + } |
121 | + |
122 | +diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h |
123 | +index 33a642e..13af2e0 100644 |
124 | +--- a/src/quick/items/qquickflickable_p_p.h |
125 | ++++ b/src/quick/items/qquickflickable_p_p.h |
126 | +@@ -200,6 +200,8 @@ public: |
127 | + |
128 | + bool isViewMoving() const; |
129 | + |
130 | ++ void cancelInteraction(); |
131 | ++ |
132 | + public: |
133 | + QQuickItem *contentItem; |
134 | + |
135 | +diff --git a/tests/auto/qmltest/listview/tst_listview.qml b/tests/auto/qmltest/listview/tst_listview.qml |
136 | +index 03be579..069b62a 100644 |
137 | +--- a/tests/auto/qmltest/listview/tst_listview.qml |
138 | ++++ b/tests/auto/qmltest/listview/tst_listview.qml |
139 | +@@ -108,6 +108,33 @@ Item { |
140 | + property int createdDelegates: 0 |
141 | + } |
142 | + |
143 | ++ ListView |
144 | ++ { |
145 | ++ id: listInteractiveCurrentIndexEnforce |
146 | ++ width: 600 |
147 | ++ height: 600 |
148 | ++ |
149 | ++ snapMode: ListView.SnapOneItem |
150 | ++ orientation: ListView.Horizontal |
151 | ++ interactive: !currentItem.moving |
152 | ++ highlightRangeMode: ListView.StrictlyEnforceRange |
153 | ++ |
154 | ++ model: 4 |
155 | ++ |
156 | ++ focus: true |
157 | ++ Keys.onPressed: if (event.key == Qt.Key_K) currentIndex = currentIndex + 1; |
158 | ++ |
159 | ++ delegate: Flickable { |
160 | ++ width: 600 |
161 | ++ height: 600 |
162 | ++ contentWidth: 600 |
163 | ++ contentHeight: 1200 |
164 | ++ |
165 | ++ MouseArea { anchors.fill: parent } |
166 | ++ Rectangle { anchors.fill: parent; color: index == 0 ? "red" : index == 1 ? "green" : index == 2 ? "blue" : "white" } |
167 | ++ } |
168 | ++ } |
169 | ++ |
170 | + Component { |
171 | + id: delegateModelAfterCreateComponent |
172 | + Rectangle { |
173 | +@@ -272,5 +299,19 @@ Item { |
174 | + listViewDelegateModelAfterCreate.model = 40; |
175 | + verify(listViewDelegateModelAfterCreate.createdDelegates > 0); |
176 | + } |
177 | ++ |
178 | ++ function test_listInteractiveCurrentIndexEnforce() { |
179 | ++ mousePress(listInteractiveCurrentIndexEnforce, 10, 50); |
180 | ++ mouseMove(listInteractiveCurrentIndexEnforce, 10, 40); |
181 | ++ mouseMove(listInteractiveCurrentIndexEnforce, 10, 30); |
182 | ++ mouseMove(listInteractiveCurrentIndexEnforce, 10, 20); |
183 | ++ mouseMove(listInteractiveCurrentIndexEnforce, 10, 10); |
184 | ++ compare(listInteractiveCurrentIndexEnforce.interactive, false); |
185 | ++ mouseRelease(listInteractiveCurrentIndexEnforce, 10, 10); |
186 | ++ tryCompare(listInteractiveCurrentIndexEnforce, "interactive", true); |
187 | ++ keyClick("k"); |
188 | ++ compare(listInteractiveCurrentIndexEnforce.currentIndex, 1); |
189 | ++ tryCompare(listInteractiveCurrentIndexEnforce, "contentX", listInteractiveCurrentIndexEnforce.width); |
190 | ++ } |
191 | + } |
192 | + } |
193 | +-- |
194 | +2.0.1 |
195 | + |
196 | |
197 | === added file 'debian/patches/Fix-crash-when-deleting-component-in-Component.onCom.patch' |
198 | --- debian/patches/Fix-crash-when-deleting-component-in-Component.onCom.patch 1970-01-01 00:00:00 +0000 |
199 | +++ debian/patches/Fix-crash-when-deleting-component-in-Component.onCom.patch 2014-08-05 16:09:22 +0000 |
200 | @@ -0,0 +1,129 @@ |
201 | +From 195b998175b629e6e915588e66991f74cffa4e48 Mon Sep 17 00:00:00 2001 |
202 | +From: Simon Hausmann <simon.hausmann@digia.com> |
203 | +Date: Fri, 20 Jun 2014 17:26:57 +0200 |
204 | +Subject: [PATCH] Fix crash when deleting component in Component.onComplete |
205 | + through loader |
206 | + |
207 | +This is a regression introduced with Qt 5.3.0. The recursion watcher code that |
208 | +is supposed to handle the test case of QTBUG-39775 can detect the recursion |
209 | +into the object creator. However the boolean that indicates the recursion is a |
210 | +member of a structure that's deleted afterwards. To avoid access to deleted |
211 | +memory, this patch simply reference counts data structure shared between the |
212 | +creators and also wraps the recursion watcher into a convenience class that |
213 | +also increases/decreases the reference count accordingly. |
214 | + |
215 | +Change-Id: I8d2e3e200ab1295e89d951e09f187d382a056d5a |
216 | +Task-number: QTBUG-39775 |
217 | +Reviewed-by: Lars Knoll <lars.knoll@digia.com> |
218 | +--- |
219 | + src/qml/qml/qqmlobjectcreator.cpp | 17 ++++++++++++----- |
220 | + src/qml/qml/qqmlobjectcreator_p.h | 18 ++++++++++++++++-- |
221 | + 2 files changed, 28 insertions(+), 7 deletions(-) |
222 | + |
223 | +diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp |
224 | +index 16c9dd7..36c7dfb 100644 |
225 | +--- a/src/qml/qml/qqmlobjectcreator.cpp |
226 | ++++ b/src/qml/qml/qqmlobjectcreator.cpp |
227 | +@@ -91,7 +91,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompile |
228 | + init(parentContext); |
229 | + |
230 | + sharedState = new QQmlObjectCreatorSharedState; |
231 | +- sharedState.setFlag(); // We own it, so we must delete it |
232 | ++ topLevelCreator = true; |
233 | + sharedState->componentAttached = 0; |
234 | + sharedState->allCreatedBindings.allocate(compiledData->totalBindingsCount); |
235 | + sharedState->allParserStatusCallbacks.allocate(compiledData->totalParserStatusCount); |
236 | +@@ -115,6 +115,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompile |
237 | + init(parentContext); |
238 | + |
239 | + sharedState = inheritedSharedState; |
240 | ++ topLevelCreator = false; |
241 | + } |
242 | + |
243 | + void QQmlObjectCreator::init(QQmlContextData *providedParentContext) |
244 | +@@ -139,9 +140,9 @@ void QQmlObjectCreator::init(QQmlContextData *providedParentContext) |
245 | + |
246 | + QQmlObjectCreator::~QQmlObjectCreator() |
247 | + { |
248 | +- if (sharedState.flag()) { |
249 | ++ if (topLevelCreator) { |
250 | + { |
251 | +- QRecursionWatcher<QQmlObjectCreatorSharedState, &QQmlObjectCreatorSharedState::recursionNode> watcher(sharedState.data()); |
252 | ++ QQmlObjectCreatorRecursionWatcher watcher(this); |
253 | + } |
254 | + for (int i = 0; i < sharedState->allCreatedBindings.count(); ++i) { |
255 | + QQmlAbstractBinding *b = sharedState->allCreatedBindings.at(i); |
256 | +@@ -157,7 +158,6 @@ QQmlObjectCreator::~QQmlObjectCreator() |
257 | + QQmlComponentAttached *a = sharedState->componentAttached; |
258 | + a->rem(); |
259 | + } |
260 | +- delete sharedState.data(); |
261 | + } |
262 | + } |
263 | + |
264 | +@@ -1172,7 +1172,7 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru |
265 | + Q_ASSERT(phase == ObjectsCreated || phase == Finalizing); |
266 | + phase = Finalizing; |
267 | + |
268 | +- QRecursionWatcher<QQmlObjectCreatorSharedState, &QQmlObjectCreatorSharedState::recursionNode> watcher(sharedState.data()); |
269 | ++ QQmlObjectCreatorRecursionWatcher watcher(this); |
270 | + ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine)); |
271 | + |
272 | + { |
273 | +@@ -1334,3 +1334,10 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * |
274 | + } |
275 | + |
276 | + |
277 | ++ |
278 | ++ |
279 | ++QQmlObjectCreatorRecursionWatcher::QQmlObjectCreatorRecursionWatcher(QQmlObjectCreator *creator) |
280 | ++ : sharedState(creator->sharedState) |
281 | ++ , watcher(creator->sharedState.data()) |
282 | ++{ |
283 | ++} |
284 | +diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h |
285 | +index 379a3b2..ad2d676 100644 |
286 | +--- a/src/qml/qml/qqmlobjectcreator_p.h |
287 | ++++ b/src/qml/qml/qqmlobjectcreator_p.h |
288 | +@@ -57,7 +57,7 @@ struct QQmlTypeCompiler; |
289 | + class QQmlInstantiationInterrupt; |
290 | + struct QQmlVmeProfiler; |
291 | + |
292 | +-struct QQmlObjectCreatorSharedState |
293 | ++struct QQmlObjectCreatorSharedState : public QSharedData |
294 | + { |
295 | + QQmlContextData *rootContext; |
296 | + QQmlContextData *creationContext; |
297 | +@@ -128,7 +128,8 @@ private: |
298 | + const QVector<QQmlPropertyCache *> &propertyCaches; |
299 | + const QVector<QByteArray> &vmeMetaObjectData; |
300 | + QHash<int, int> objectIndexToId; |
301 | +- QFlagPointer<QQmlObjectCreatorSharedState> sharedState; |
302 | ++ QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState; |
303 | ++ bool topLevelCreator; |
304 | + void *activeVMEDataForRootContext; |
305 | + |
306 | + QObject *_qobject; |
307 | +@@ -142,6 +143,19 @@ private: |
308 | + QQmlVMEMetaObject *_vmeMetaObject; |
309 | + QQmlListProperty<void> _currentList; |
310 | + QV4::ExecutionContext *_qmlContext; |
311 | ++ |
312 | ++ friend struct QQmlObjectCreatorRecursionWatcher; |
313 | ++}; |
314 | ++ |
315 | ++struct QQmlObjectCreatorRecursionWatcher |
316 | ++{ |
317 | ++ QQmlObjectCreatorRecursionWatcher(QQmlObjectCreator *creator); |
318 | ++ |
319 | ++ bool hasRecursed() const { return watcher.hasRecursed(); } |
320 | ++ |
321 | ++private: |
322 | ++ QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState; |
323 | ++ QRecursionWatcher<QQmlObjectCreatorSharedState, &QQmlObjectCreatorSharedState::recursionNode> watcher; |
324 | + }; |
325 | + |
326 | + QT_END_NAMESPACE |
327 | +-- |
328 | +2.0.1 |
329 | + |
330 | |
331 | === added file 'debian/patches/Fix-interaction-of-garbage-collector-with-JS-objects.patch' |
332 | --- debian/patches/Fix-interaction-of-garbage-collector-with-JS-objects.patch 1970-01-01 00:00:00 +0000 |
333 | +++ debian/patches/Fix-interaction-of-garbage-collector-with-JS-objects.patch 2014-08-05 16:09:22 +0000 |
334 | @@ -0,0 +1,335 @@ |
335 | +From 14bc8dc3f3016889cfcbdbe7309b09be7687ebe0 Mon Sep 17 00:00:00 2001 |
336 | +From: Simon Hausmann <simon.hausmann@digia.com> |
337 | +Date: Wed, 14 May 2014 16:04:33 +0200 |
338 | +Subject: [PATCH] Fix interaction of garbage collector with JS objects during |
339 | + QML type instantiation |
340 | + |
341 | +It may happen that during the lengthy process of instantiating a tree of |
342 | +objects for QML, the garbage collector runs. |
343 | + |
344 | +For objects created by QML we support different ownership models, for example |
345 | +in QtQuick visual parents keep their visual children alive, despite perhaps a |
346 | +lack of QObject parentship. That ownership becomes active once the QML |
347 | +autoparent function has assigned the correct visual parent, which happens after |
348 | +object instantiation (after QQmlObjectCreator). |
349 | + |
350 | +Similarly when a composite type is created, its QObject parent is only set |
351 | +after all properties have been set. The root QObject is kept alive through a |
352 | +special boolean, but if the sub-objects aren't children yet, their JS wrapper |
353 | +might get deleted. For composite types with var properties, that also means |
354 | +their var properties get deleted, such as the model property of TableView.qml |
355 | +in the bug report. |
356 | + |
357 | +In the future we want to support creating QWidget hierarchies with QML, which |
358 | +also for layouts may rely on a delayed parent assignment for layouts. |
359 | + |
360 | +To accommodate all this, this patch introduces an array on the JS stack that |
361 | +keeps track of all JS wrappers for all QObjects created. This array is alive |
362 | +during object tree creation. Afterwards, the different ownership models take |
363 | +over, for example the auto parent function assigning a visual parent. |
364 | + |
365 | +This patch also fixes an off-by-one in the total object count calculation |
366 | +for composite types, where when instantiating a composite type as a sub-object |
367 | +we counted the sub composite's object count but forgot the object itself. |
368 | + |
369 | +Task-number: QTBUG-38835 |
370 | +Task-number: QTBUG-39966 |
371 | +Change-Id: I6104b2434510642081e0c54793ed296adeca7481 |
372 | +Reviewed-by: Lars Knoll <lars.knoll@digia.com> |
373 | +--- |
374 | + src/qml/compiler/qqmltypecompiler.cpp | 4 +- |
375 | + src/qml/qml/qqmlobjectcreator.cpp | 27 +++++++--- |
376 | + src/qml/qml/qqmlobjectcreator_p.h | 1 + |
377 | + tests/auto/qml/qqmlecmascript/testtypes.cpp | 60 ++++++++++++++++++++++ |
378 | + tests/auto/qml/qqmlecmascript/testtypes.h | 45 ++++++++++++++++ |
379 | + .../auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 28 ++++++++++ |
380 | + 6 files changed, 157 insertions(+), 8 deletions(-) |
381 | + |
382 | +diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp |
383 | +index 60a0829..dacaa14 100644 |
384 | +--- a/src/qml/compiler/qqmltypecompiler.cpp |
385 | ++++ b/src/qml/compiler/qqmltypecompiler.cpp |
386 | +@@ -277,12 +277,12 @@ bool QQmlTypeCompiler::compile() |
387 | + if (qmlType->parserStatusCast() != -1) |
388 | + ++parserStatusCount; |
389 | + } |
390 | ++ ++objectCount; |
391 | + if (typeRef->component) { |
392 | + bindingCount += typeRef->component->totalBindingsCount; |
393 | + parserStatusCount += typeRef->component->totalParserStatusCount; |
394 | + objectCount += typeRef->component->totalObjectCount; |
395 | +- } else |
396 | +- ++objectCount; |
397 | ++ } |
398 | + } |
399 | + } |
400 | + |
401 | +diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp |
402 | +index 36c7dfb..1de467b 100644 |
403 | +--- a/src/qml/qml/qqmlobjectcreator.cpp |
404 | ++++ b/src/qml/qml/qqmlobjectcreator.cpp |
405 | +@@ -96,6 +96,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompile |
406 | + sharedState->allCreatedBindings.allocate(compiledData->totalBindingsCount); |
407 | + sharedState->allParserStatusCallbacks.allocate(compiledData->totalParserStatusCount); |
408 | + sharedState->allCreatedObjects.allocate(compiledData->totalObjectCount); |
409 | ++ sharedState->allJavaScriptObjects = 0; |
410 | + sharedState->creationContext = creationContext; |
411 | + sharedState->rootContext = 0; |
412 | + |
413 | +@@ -195,6 +196,13 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI |
414 | + sharedState->rootContext->isRootObjectInCreation = true; |
415 | + } |
416 | + |
417 | ++ QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); |
418 | ++ QV4::Scope scope(v4); |
419 | ++ |
420 | ++ Q_ASSERT(sharedState->allJavaScriptObjects || topLevelCreator); |
421 | ++ if (topLevelCreator) |
422 | ++ sharedState->allJavaScriptObjects = scope.alloc(compiledData->totalObjectCount); |
423 | ++ |
424 | + QVector<QQmlContextData::ObjectIdMapping> mapping(objectIndexToId.count()); |
425 | + for (QHash<int, int>::ConstIterator it = objectIndexToId.constBegin(), end = objectIndexToId.constEnd(); |
426 | + it != end; ++it) { |
427 | +@@ -208,8 +216,6 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI |
428 | + context->setIdPropertyData(mapping); |
429 | + |
430 | + if (subComponentIndex == -1) { |
431 | +- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); |
432 | +- QV4::Scope scope(v4); |
433 | + QV4::ScopedObject scripts(scope, v4->newArrayObject(compiledData->scripts.count())); |
434 | + context->importedScripts = scripts; |
435 | + for (int i = 0; i < compiledData->scripts.count(); ++i) { |
436 | +@@ -230,6 +236,9 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI |
437 | + ddata->compiledData->addref(); |
438 | + } |
439 | + |
440 | ++ if (topLevelCreator) |
441 | ++ sharedState->allJavaScriptObjects = 0; |
442 | ++ |
443 | + phase = CreatingObjectsPhase2; |
444 | + |
445 | + if (interrupt && interrupt->shouldInterrupt()) |
446 | +@@ -258,8 +267,11 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance) |
447 | + |
448 | + QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); |
449 | + QV4::Scope valueScope(v4); |
450 | +- QV4::ScopedValue scopeObjectProtector(valueScope, declarativeData->jsWrapper.value()); |
451 | +- Q_UNUSED(scopeObjectProtector); |
452 | ++ |
453 | ++ Q_ASSERT(topLevelCreator); |
454 | ++ Q_ASSERT(!sharedState->allJavaScriptObjects); |
455 | ++ sharedState->allJavaScriptObjects = valueScope.alloc(compiledData->totalObjectCount); |
456 | ++ |
457 | + QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, _scopeObject)); |
458 | + QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, qmlScope)); |
459 | + QV4::ExecutionContext *qmlContext = qmlBindingWrapper->context(); |
460 | +@@ -1150,9 +1162,12 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo |
461 | + qSwap(_scopeObject, scopeObject); |
462 | + |
463 | + QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); |
464 | ++ |
465 | ++ Q_ASSERT(sharedState->allJavaScriptObjects); |
466 | ++ QV4::ValueRef ref = QV4::ValueRef::fromRawValue(sharedState->allJavaScriptObjects++); |
467 | ++ ref = QV4::QObjectWrapper::wrap(v4, instance); |
468 | ++ |
469 | + QV4::Scope valueScope(v4); |
470 | +- QV4::ScopedValue scopeObjectProtector(valueScope, ddata ? ddata->jsWrapper.value() : 0); |
471 | +- Q_UNUSED(scopeObjectProtector); |
472 | + QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, _scopeObject)); |
473 | + QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, qmlScope)); |
474 | + QV4::ExecutionContext *qmlContext = qmlBindingWrapper->context(); |
475 | +diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h |
476 | +index ad2d676..fb4d71d 100644 |
477 | +--- a/src/qml/qml/qqmlobjectcreator_p.h |
478 | ++++ b/src/qml/qml/qqmlobjectcreator_p.h |
479 | +@@ -64,6 +64,7 @@ struct QQmlObjectCreatorSharedState : public QSharedData |
480 | + QFiniteStack<QQmlAbstractBinding*> allCreatedBindings; |
481 | + QFiniteStack<QQmlParserStatus*> allParserStatusCallbacks; |
482 | + QFiniteStack<QObject*> allCreatedObjects; |
483 | ++ QV4::Value *allJavaScriptObjects; // pointer to vector on JS stack to reference JS wrappers during creation phase. |
484 | + QQmlComponentAttached *componentAttached; |
485 | + QList<QQmlEnginePrivate::FinalizeCallback> finalizeCallbacks; |
486 | + QQmlVmeProfiler profiler; |
487 | +diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp |
488 | +index eb06b9e..560d860 100644 |
489 | +--- a/tests/auto/qml/qqmlecmascript/testtypes.cpp |
490 | ++++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp |
491 | +@@ -300,6 +300,62 @@ static QObject *create_singletonWithEnum(QQmlEngine *, QJSEngine *) |
492 | + return new SingletonWithEnum; |
493 | + } |
494 | + |
495 | ++QObjectContainer::QObjectContainer() |
496 | ++ : widgetParent(0) |
497 | ++ , gcOnAppend(false) |
498 | ++{} |
499 | ++ |
500 | ++QQmlListProperty<QObject> QObjectContainer::data() |
501 | ++{ |
502 | ++ return QQmlListProperty<QObject>(this, 0, children_append, children_count, children_at, children_clear); |
503 | ++} |
504 | ++ |
505 | ++void QObjectContainer::children_append(QQmlListProperty<QObject> *prop, QObject *o) |
506 | ++{ |
507 | ++ QObjectContainer *that = static_cast<QObjectContainer*>(prop->object); |
508 | ++ that->dataChildren.append(o); |
509 | ++ QObject::connect(o, SIGNAL(destroyed(QObject*)), prop->object, SLOT(childDestroyed(QObject*))); |
510 | ++ |
511 | ++ if (that->gcOnAppend) { |
512 | ++ QQmlEngine *engine = qmlEngine(that); |
513 | ++ engine->collectGarbage(); |
514 | ++ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); |
515 | ++ QCoreApplication::processEvents(); |
516 | ++ } |
517 | ++} |
518 | ++ |
519 | ++int QObjectContainer::children_count(QQmlListProperty<QObject> *prop) |
520 | ++{ |
521 | ++ return static_cast<QObjectContainer*>(prop->object)->dataChildren.count(); |
522 | ++} |
523 | ++ |
524 | ++QObject *QObjectContainer::children_at(QQmlListProperty<QObject> *prop, int index) |
525 | ++{ |
526 | ++ return static_cast<QObjectContainer*>(prop->object)->dataChildren.at(index); |
527 | ++} |
528 | ++ |
529 | ++void QObjectContainer::children_clear(QQmlListProperty<QObject> *prop) |
530 | ++{ |
531 | ++ QObjectContainer *that = static_cast<QObjectContainer*>(prop->object); |
532 | ++ foreach (QObject *c, that->dataChildren) |
533 | ++ QObject::disconnect(c, SIGNAL(destroyed(QObject*)), that, SLOT(childDestroyed(QObject*))); |
534 | ++ that->dataChildren.clear(); |
535 | ++} |
536 | ++ |
537 | ++void QObjectContainer::childDestroyed(QObject *child) { |
538 | ++ dataChildren.removeAll(child); |
539 | ++} |
540 | ++ |
541 | ++void FloatingQObject::classBegin() |
542 | ++{ |
543 | ++ setParent(0); |
544 | ++} |
545 | ++ |
546 | ++void FloatingQObject::componentComplete() |
547 | ++{ |
548 | ++ Q_ASSERT(!parent()); |
549 | ++} |
550 | ++ |
551 | + void registerTypes() |
552 | + { |
553 | + qmlRegisterType<MyQmlObject>("Qt.test", 1,0, "MyQmlObjectAlias"); |
554 | +@@ -381,6 +437,10 @@ void registerTypes() |
555 | + qmlRegisterSingletonType<testImportOrderApi>("Qt.test.importOrderApi2",1,0,"Data",testImportOrder_api2); |
556 | + |
557 | + qmlRegisterSingletonType<SingletonWithEnum>("Qt.test.singletonWithEnum", 1, 0, "SingletonWithEnum", create_singletonWithEnum); |
558 | ++ |
559 | ++ qmlRegisterType<QObjectContainer>("Qt.test", 1, 0, "QObjectContainer"); |
560 | ++ qmlRegisterType<QObjectContainerWithGCOnAppend>("Qt.test", 1, 0, "QObjectContainerWithGCOnAppend"); |
561 | ++ qmlRegisterType<FloatingQObject>("Qt.test", 1, 0, "FloatingQObject"); |
562 | + } |
563 | + |
564 | + #include "testtypes.moc" |
565 | +diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h |
566 | +index 928d594..d5a1220 100644 |
567 | +--- a/tests/auto/qml/qqmlecmascript/testtypes.h |
568 | ++++ b/tests/auto/qml/qqmlecmascript/testtypes.h |
569 | +@@ -1661,6 +1661,51 @@ public: |
570 | + }; |
571 | + }; |
572 | + |
573 | ++// Like QtObject, but with default property |
574 | ++class QObjectContainer : public QObject |
575 | ++{ |
576 | ++ Q_OBJECT |
577 | ++ Q_CLASSINFO("DefaultProperty", "data") |
578 | ++ Q_PROPERTY(QQmlListProperty<QObject> data READ data DESIGNABLE false) |
579 | ++public: |
580 | ++ QObjectContainer(); |
581 | ++ |
582 | ++ QQmlListProperty<QObject> data(); |
583 | ++ |
584 | ++ static void children_append(QQmlListProperty<QObject> *prop, QObject *o); |
585 | ++ static int children_count(QQmlListProperty<QObject> *prop); |
586 | ++ static QObject *children_at(QQmlListProperty<QObject> *prop, int index); |
587 | ++ static void children_clear(QQmlListProperty<QObject> *prop); |
588 | ++ |
589 | ++ QList<QObject*> dataChildren; |
590 | ++ QWidget *widgetParent; |
591 | ++ bool gcOnAppend; |
592 | ++ |
593 | ++protected slots: |
594 | ++ void childDestroyed(QObject *child); |
595 | ++}; |
596 | ++ |
597 | ++class QObjectContainerWithGCOnAppend : public QObjectContainer |
598 | ++{ |
599 | ++ Q_OBJECT |
600 | ++public: |
601 | ++ QObjectContainerWithGCOnAppend() |
602 | ++ { |
603 | ++ gcOnAppend = true; |
604 | ++ } |
605 | ++}; |
606 | ++ |
607 | ++class FloatingQObject : public QObject, public QQmlParserStatus |
608 | ++{ |
609 | ++ Q_OBJECT |
610 | ++ Q_INTERFACES(QQmlParserStatus) |
611 | ++public: |
612 | ++ FloatingQObject() {} |
613 | ++ |
614 | ++ virtual void classBegin(); |
615 | ++ virtual void componentComplete(); |
616 | ++}; |
617 | ++ |
618 | + void registerTypes(); |
619 | + |
620 | + #endif // TESTTYPES_H |
621 | +diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp |
622 | +index a1e36b4..a9486a8 100644 |
623 | +--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp |
624 | ++++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp |
625 | +@@ -322,6 +322,7 @@ private slots: |
626 | + void varPropertyAccessOnObjectWithInvalidContext(); |
627 | + void importedScriptsAccessOnObjectWithInvalidContext(); |
628 | + void contextObjectOnLazyBindings(); |
629 | ++ void garbageCollectionDuringCreation(); |
630 | + |
631 | + private: |
632 | + // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter); |
633 | +@@ -7603,6 +7604,33 @@ void tst_qqmlecmascript::contextObjectOnLazyBindings() |
634 | + QCOMPARE(subObject->property("testValue").toInt(), int(42)); |
635 | + } |
636 | + |
637 | ++void tst_qqmlecmascript::garbageCollectionDuringCreation() |
638 | ++{ |
639 | ++ QQmlComponent component(&engine); |
640 | ++ component.setData("import Qt.test 1.0\n" |
641 | ++ "QObjectContainerWithGCOnAppend {\n" |
642 | ++ " objectName: \"root\"\n" |
643 | ++ " FloatingQObject {\n" |
644 | ++ " objectName: \"parentLessChild\"\n" |
645 | ++ " property var blah;\n" // Ensure we have JS wrapper |
646 | ++ " }\n" |
647 | ++ "}\n", |
648 | ++ QUrl()); |
649 | ++ |
650 | ++ QScopedPointer<QObject> object(component.create()); |
651 | ++ QVERIFY(!object.isNull()); |
652 | ++ |
653 | ++ QObjectContainer *container = qobject_cast<QObjectContainer*>(object.data()); |
654 | ++ QCOMPARE(container->dataChildren.count(), 1); |
655 | ++ |
656 | ++ QObject *child = container->dataChildren.first(); |
657 | ++ QQmlData *ddata = QQmlData::get(child); |
658 | ++ QVERIFY(!ddata->jsWrapper.isNullOrUndefined()); |
659 | ++ |
660 | ++ gc(engine); |
661 | ++ QCOMPARE(container->dataChildren.count(), 0); |
662 | ++} |
663 | ++ |
664 | + QTEST_MAIN(tst_qqmlecmascript) |
665 | + |
666 | + #include "tst_qqmlecmascript.moc" |
667 | +-- |
668 | +2.0.1 |
669 | + |
670 | |
671 | === removed file 'debian/patches/parenttosubcreator_qqmlobjectcreator.patch' |
672 | --- debian/patches/parenttosubcreator_qqmlobjectcreator.patch 2014-07-01 08:22:15 +0000 |
673 | +++ debian/patches/parenttosubcreator_qqmlobjectcreator.patch 1970-01-01 00:00:00 +0000 |
674 | @@ -1,24 +0,0 @@ |
675 | -commit 249b1a73fdb01fc27e036fc4334925674c281793 |
676 | -Author: Albert Astals Cid <albert.astals@canonical.com> |
677 | -Date: Mon Jun 30 17:22:55 2014 +0200 |
678 | - |
679 | - Pass down parent to subCreator |
680 | - |
681 | - Otherwise the object might get garbage collected while it's being created |
682 | - |
683 | - Change-Id: I553c3432d5242bcd89723b72d8f8ae82577abaf9 |
684 | - Task-number: QTBUG-39966 |
685 | - |
686 | -diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp |
687 | -index 36c7dfb..cceb9b2 100644 |
688 | ---- a/src/qml/qml/qqmlobjectcreator.cpp |
689 | -+++ b/src/qml/qml/qqmlobjectcreator.cpp |
690 | -@@ -1076,7 +1076,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo |
691 | - } |
692 | - |
693 | - QQmlObjectCreator subCreator(context, typeRef->component, sharedState.data()); |
694 | -- instance = subCreator.create(); |
695 | -+ instance = subCreator.create(-1, parent); |
696 | - if (!instance) { |
697 | - errors += subCreator.errors; |
698 | - return 0; |
699 | |
700 | === modified file 'debian/patches/series' |
701 | --- debian/patches/series 2014-07-07 08:45:33 +0000 |
702 | +++ debian/patches/series 2014-08-05 16:09:22 +0000 |
703 | @@ -6,5 +6,7 @@ |
704 | v4_yarr_jit_push_pop_addressTempRegister.patch |
705 | fix_qqmlobjectcreator.patch |
706 | Implement-proper-support-for-layoutChange-in-QQmlDel.patch |
707 | -parenttosubcreator_qqmlobjectcreator.patch |
708 | +Fix-crash-when-deleting-component-in-Component.onCom.patch |
709 | +Fix-interaction-of-garbage-collector-with-JS-objects.patch |
710 | Support-RFC2822Date-date-format-similar-to-V8.patch |
711 | +8454a21b-Flickable-Cancel-interaction-on-interactive-changes.patch |
712 | |
713 | === modified file 'debian/rules' |
714 | --- debian/rules 2014-05-28 05:57:55 +0000 |
715 | +++ debian/rules 2014-08-05 16:09:22 +0000 |
716 | @@ -1,10 +1,17 @@ |
717 | #!/usr/bin/make -f |
718 | |
719 | +include /usr/share/dpkg/default.mk |
720 | + |
721 | # Uncomment this to turn on verbose mode. |
722 | #export DH_VERBOSE=1 |
723 | |
724 | DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) |
725 | |
726 | +# Explicitly selecting a G{CC,++}-version here to avoid symbol changes |
727 | +# because of the default gcc switch. |
728 | +export CC=$(DEB_HOST_GNU_TYPE)-gcc-4.8 |
729 | +export CXX=$(DEB_HOST_GNU_TYPE)-g++-4.8 |
730 | + |
731 | export CFLAGS := $(shell dpkg-buildflags --get CFLAGS) $(shell dpkg-buildflags --get CPPFLAGS) |
732 | export CXXFLAGS := $(shell dpkg-buildflags --get CXXFLAGS) $(shell dpkg-buildflags --get CPPFLAGS) |
733 | export LDFLAGS := $(shell dpkg-buildflags --get LDFLAGS) -Wl,--as-needed |
734 | @@ -14,7 +21,7 @@ |
735 | dh $@ --parallel --with pkgkde_symbolshelper --dbg-package=qtdeclarative5-dbg |
736 | |
737 | override_dh_auto_configure: |
738 | - qmake QT_BUILD_PARTS+=tests |
739 | + qmake QT_BUILD_PARTS+=tests QMAKE_CC=$(CC) QMAKE_CXX=$(CXX) |
740 | |
741 | override_dh_auto_build-indep: |
742 | dh_auto_build -Smakefile -- html_docs |
Released, this is to trigger code coverage collection only.