From 68b899266ca209d43026376a6cf9d7bbdc3483b8 Mon Sep 17 00:00:00 2001 From: Charles Yin Date: Tue, 8 May 2012 10:42:28 +1000 Subject: [PATCH] Better checking top level root object creation status 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 --- src/qml/qml/qqmlcomponent.cpp | 2 +- src/qml/qml/qqmlcontext.cpp | 4 ++-- src/qml/qml/qqmlcontext_p.h | 3 ++- src/qml/qml/qqmldata_p.h | 8 ++++---- src/qml/qml/qqmlincubator.cpp | 2 +- src/qml/qml/qqmlvme.cpp | 11 ++++++----- src/qml/qml/v8/qv8qobjectwrapper.cpp | 4 ++-- 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index e904188..ef2a357 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -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) { diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index 7e15993..a02b2b7 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -513,7 +513,7 @@ QObject *QQmlContextPrivate::context_at(QQmlListProperty *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), diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h index 1f1c601..4eb3117 100644 --- a/src/qml/qml/qqmlcontext_p.h +++ b/src/qml/qml/qqmlcontext_p.h @@ -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 diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h index 08f68b6..2c2c597 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), 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 { diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp index 817e7b8..bd3fe52 100644 --- a/src/qml/qml/qqmlincubator.cpp +++ b/src/qml/qml/qqmlincubator.cpp @@ -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); } diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index 357200d..898f598 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -449,6 +449,7 @@ QObject *QQmlVME::run(QList *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 *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 *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; diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp index dabd09c..fde7f66 100644 --- a/src/qml/qml/v8/qv8qobjectwrapper.cpp +++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp @@ -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 ToString(QV8Engine *engine, QObject *object, int, v static v8::Handle Destroy(QV8Engine *, QObject *object, int argCount, v8::Handle 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(); -- 1.7.2.5