Better checking top level root object creation status
authorCharles Yin <charles.yin@nokia.com>
Tue, 8 May 2012 00:42:28 +0000 (10:42 +1000)
committerQt by Nokia <qt-info@nokia.com>
Tue, 8 May 2012 22:56:16 +0000 (00:56 +0200)
Add QQmlContextData::isRootObjectInCreation flag, only set it to true in Init qml instruction,
once a root ojbect created, set it to false and set QQmlData::rootObjectInCreation to true.

Change-Id: Iba7b348ab664a472280d8d7283e93787b3dd0a56
Reviewed-by: Chris Adams <christopher.adams@nokia.com>
src/qml/qml/qqmlcomponent.cpp
src/qml/qml/qqmlcontext.cpp
src/qml/qml/qqmlcontext_p.h
src/qml/qml/qqmldata_p.h
src/qml/qml/qqmlincubator.cpp
src/qml/qml/qqmlvme.cpp
src/qml/qml/v8/qv8qobjectwrapper.cpp

index e904188..ef2a357 100644 (file)
@@ -836,7 +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;
+        ddata->rootObjectInCreation = false;
     }
 
     if (enginePriv->isDebugging && rv) {
index 7e15993..a02b2b7 100644 (file)
@@ -513,7 +513,7 @@ QObject *QQmlContextPrivate::context_at(QQmlListProperty<QObject> *prop, int ind
 
 QQmlContextData::QQmlContextData()
 : parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false), 
-  isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false),
+  isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false),
   publicContext(0), activeVMEData(0),
   propertyNames(0), contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
   expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0),
@@ -523,7 +523,7 @@ QQmlContextData::QQmlContextData()
 
 QQmlContextData::QQmlContextData(QQmlContext *ctxt)
 : parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false), 
-  isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false),
+  isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false),
   publicContext(ctxt), activeVMEData(0),
   propertyNames(0), contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
   expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0),
index 1f1c601..4eb3117 100644 (file)
@@ -148,7 +148,8 @@ public:
     quint32 isPragmaLibraryContext:1;
     quint32 unresolvedNames:1; // True if expressions in this context failed to resolve a toplevel name
     quint32 hasEmittedDestruction:1;
-    quint32 dummy:26;
+    quint32 isRootObjectInCreation:1;
+    quint32 dummy:25;
     QQmlContext *publicContext;
 
     // VME data that is constructing this context if any
index 08f68b6..2c2c597 100644 (file)
@@ -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), inCreation(false), notifyList(0), context(0), outerContext(0),
+          hasTaintedV8Object(false), isQueuedForDeletion(false), rootObjectInCreation(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) {
@@ -116,10 +116,10 @@ public:
     quint32 hasTaintedV8Object:1;
     quint32 isQueuedForDeletion:1;
     /*
-     * 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.
+     * rootObjectInCreation should be true only when creating top level CPP and QML objects,
+     * v8 GC will check this flag, only deletes the objects when rootObjectInCreation is false.
      */
-    quint32 inCreation:1;
+    quint32 rootObjectInCreation:1;
     quint32 dummy:25;
 
     struct NotifyList {
index 817e7b8..bd3fe52 100644 (file)
@@ -296,7 +296,7 @@ void QQmlIncubatorPrivate::incubate(QQmlVME::Interrupt &i)
             //see QQmlComponent::beginCreate for explanation of indestructible
             ddata->indestructible = true;
             ddata->explicitIndestructibleSet = true;
-            ddata->inCreation = false;
+            ddata->rootObjectInCreation = false;
             q->setInitialState(result);
         }
 
index 357200d..898f598 100644 (file)
@@ -449,6 +449,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
             if (states.count() == 1) {
                 rootContext = CTXT;
                 rootContext->activeVMEData = data;
+                rootContext->isRootObjectInCreation = true;
             }
             if (states.count() == 1 && !creationContext.isNull()) {
                 // A component that is logically created within another component instance shares the 
@@ -509,13 +510,11 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
 
         QML_BEGIN_INSTR(CompleteQMLObject)
             QObject *o = objects.top();
+            Q_ASSERT(o);
 
             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);
@@ -550,8 +549,10 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
             ddata->ownMemory = false;
             QObjectPrivate::get(o)->declarativeData = ddata;
 
-            if (states.count() == 1)
-                ddata->inCreation = true;
+            if (rootContext && rootContext->isRootObjectInCreation) {
+                ddata->rootObjectInCreation = true;
+                rootContext->isRootObjectInCreation = false;
+            }
 
             if (type.typePropertyCache && !ddata->propertyCache) {
                 ddata->propertyCache = type.typePropertyCache;
index dabd09c..fde7f66 100644 (file)
@@ -1148,7 +1148,7 @@ void QV8QObjectWrapper::deleteWeakQObject(QV8QObjectResource *resource)
     if (object) {
         QQmlData *ddata = QQmlData::get(object, false);
         if (ddata) {
-            if (ddata->inCreation) {
+            if (ddata->rootObjectInCreation) {
                 ddata->v8object.MakeWeak(0, WeakQObjectReferenceCallback);
                 return;
             }
@@ -1891,7 +1891,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 || ddata->inCreation) {
+    if (!ddata || ddata->indestructible || ddata->rootObjectInCreation) {
         const char *error = "Invalid attempt to destroy() an indestructible object";
         v8::ThrowException(v8::Exception::Error(v8::String::New(error)));
         return v8::Undefined();