aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/qml/qqmlcomponent.cpp1
-rw-r--r--src/qml/qml/qqmldata_p.h9
-rw-r--r--src/qml/qml/qqmlincubator.cpp1
-rw-r--r--src/qml/qml/qqmlvme.cpp6
-rw-r--r--src/qml/qml/v8/qv8qobjectwrapper.cpp7
-rw-r--r--tests/auto/qml/qqmlecmascript/data/RootObject.qml21
-rw-r--r--tests/auto/qml/qqmlecmascript/data/deleteRootObjectInCreation.qml5
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp15
8 files changed, 61 insertions, 4 deletions
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 2e46192246..e5c498a662 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -836,6 +836,7 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
//if JS ownership is needed this needs to be explicitly undone (like in component.createObject())
ddata->indestructible = true;
ddata->explicitIndestructibleSet = true;
+ ddata->inCreation = false;
}
if (enginePriv->isDebugging && rv) {
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index 1a188f9e59..ffaa7e2cb5 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -79,7 +79,7 @@ class Q_QML_EXPORT QQmlData : public QAbstractDeclarativeData
public:
QQmlData()
: ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false),
- hasTaintedV8Object(false), isQueuedForDeletion(false), notifyList(0), context(0), outerContext(0),
+ hasTaintedV8Object(false), isQueuedForDeletion(false), inCreation(false), notifyList(0), context(0), outerContext(0),
bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0), bindingBitsSize(0), bindingBits(0),
lineNumber(0), columnNumber(0), deferredComponent(0), deferredIdx(0), v8objectid(0),
propertyCache(0), guards(0), extendedData(0) {
@@ -114,7 +114,12 @@ public:
quint32 explicitIndestructibleSet:1;
quint32 hasTaintedV8Object:1;
quint32 isQueuedForDeletion:1;
- quint32 dummy:26;
+ /*
+ * inCreation should be true only when creating top level CPP and QML objects,
+ * v8 GC will check this flag, only deletes the objects when inCreation is false.
+ */
+ quint32 inCreation:1;
+ quint32 dummy:25;
struct NotifyList {
quint64 connectionMask;
diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp
index fad2ae2f28..817e7b89e7 100644
--- a/src/qml/qml/qqmlincubator.cpp
+++ b/src/qml/qml/qqmlincubator.cpp
@@ -296,6 +296,7 @@ void QQmlIncubatorPrivate::incubate(QQmlVME::Interrupt &i)
//see QQmlComponent::beginCreate for explanation of indestructible
ddata->indestructible = true;
ddata->explicitIndestructibleSet = true;
+ ddata->inCreation = false;
q->setInitialState(result);
}
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index 985d291a8e..47ea690973 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -513,6 +513,9 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QQmlData *ddata = QQmlData::get(o);
Q_ASSERT(ddata);
+ if (states.count() == 1)
+ ddata->inCreation = true;
+
if (instr.isRoot) {
if (ddata->context) {
Q_ASSERT(ddata->context != CTXT);
@@ -547,6 +550,9 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
ddata->ownMemory = false;
QObjectPrivate::get(o)->declarativeData = ddata;
+ if (states.count() == 1)
+ ddata->inCreation = true;
+
if (type.typePropertyCache && !ddata->propertyCache) {
ddata->propertyCache = type.typePropertyCache;
ddata->propertyCache->addref();
diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp
index 2d6c5ec24a..f2acac5bbc 100644
--- a/src/qml/qml/v8/qv8qobjectwrapper.cpp
+++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp
@@ -1153,6 +1153,11 @@ void QV8QObjectWrapper::deleteWeakQObject(QV8QObjectResource *resource)
if (object) {
QQmlData *ddata = QQmlData::get(object, false);
if (ddata) {
+ if (ddata->inCreation) {
+ ddata->v8object.MakeWeak(0, WeakQObjectReferenceCallback);
+ return;
+ }
+
ddata->v8object.Clear();
if (!object->parent() && !ddata->indestructible) {
ddata->isQueuedForDeletion = true;
@@ -1888,7 +1893,7 @@ static v8::Handle<v8::Value> ToString(QV8Engine *engine, QObject *object, int, v
static v8::Handle<v8::Value> Destroy(QV8Engine *, QObject *object, int argCount, v8::Handle<v8::Object> args)
{
QQmlData *ddata = QQmlData::get(object, false);
- if (!ddata || ddata->indestructible) {
+ if (!ddata || ddata->indestructible || ddata->inCreation) {
const char *error = "Invalid attempt to destroy() an indestructible object";
v8::ThrowException(v8::Exception::Error(v8::String::New(error)));
return v8::Undefined();
diff --git a/tests/auto/qml/qqmlecmascript/data/RootObject.qml b/tests/auto/qml/qqmlecmascript/data/RootObject.qml
new file mode 100644
index 0000000000..bf46155c96
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/RootObject.qml
@@ -0,0 +1,21 @@
+import QtQuick 2.0
+
+Rectangle {
+ id: root
+ color:"red"
+ property bool rootIndestructible:false
+ property bool childDestructible:child === null
+ onColorChanged: {
+ try {
+ root.destroy();
+ gc();
+ } catch(e) {
+ rootIndestructible = true;
+ }
+ }
+
+ QtObject {
+ id:child
+ }
+ Component.onCompleted: child.destroy();
+} \ No newline at end of file
diff --git a/tests/auto/qml/qqmlecmascript/data/deleteRootObjectInCreation.qml b/tests/auto/qml/qqmlecmascript/data/deleteRootObjectInCreation.qml
new file mode 100644
index 0000000000..fbb7d24471
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/deleteRootObjectInCreation.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+RootObject {
+ color:"black"
+} \ No newline at end of file
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index cb56948b6e..30914977d8 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -256,7 +256,7 @@ private slots:
void withStatement();
void tryStatement();
void replaceBinding();
-
+ void deleteRootObjectInCreation();
private:
static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
QQmlEngine engine;
@@ -6619,6 +6619,19 @@ void tst_qqmlecmascript::replaceBinding()
delete obj;
}
+void tst_qqmlecmascript::deleteRootObjectInCreation()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("deleteRootObjectInCreation.qml"));
+ QObject *obj = c.create();
+ QVERIFY(obj != 0);
+ QVERIFY(obj->property("rootIndestructible").toBool());
+ QVERIFY(!obj->property("childDestructible").toBool());
+ QTest::qWait(1);
+ QVERIFY(obj->property("childDestructible").toBool());
+ delete obj;
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"