diff options
author | Matthew Vogt <matthew.vogt@nokia.com> | 2012-04-27 16:12:09 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-05-04 03:41:33 +0200 |
commit | c31026c9ca7ff0c745dba577f9ac2c14d1ef68c5 (patch) | |
tree | dd3150dd95af2fa9759852d61d9c87b86322852a /src | |
parent | 6318560eca7e3247a63620ce24d2d7e291dd5d84 (diff) |
Emit Component.onDestruction before context is invalidated
When a component no longer has any live references, emit the
destruction signal immediately so that handlers are run before the
associated V8 resources are invalidated. Also, when the root
context of the engine is destroyed, emit the destruction signal
before destroying any resources needed to process the resulting
binding invocations.
Change-Id: I722dd6e4b60c499b533fc45e33b61e95bca6187f
Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/qml/qqmlcontext.cpp | 54 | ||||
-rw-r--r-- | src/qml/qml/qqmlcontext_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/v8/qv8qobjectwrapper.cpp | 3 |
4 files changed, 43 insertions, 23 deletions
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index cbb8430f40..7e15993a65 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -513,7 +513,8 @@ 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), publicContext(0), activeVMEData(0), + isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(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), componentAttached(0), v4bindings(0), v8bindings(0) @@ -522,25 +523,45 @@ QQmlContextData::QQmlContextData() QQmlContextData::QQmlContextData(QQmlContext *ctxt) : parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false), - isPragmaLibraryContext(false), unresolvedNames(false), publicContext(ctxt), activeVMEData(0), + isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(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), componentAttached(0), v4bindings(0), v8bindings(0) { } -void QQmlContextData::invalidate() +void QQmlContextData::emitDestruction() { - while (componentAttached) { - QQmlComponentAttached *a = componentAttached; - componentAttached = a->next; - if (componentAttached) componentAttached->prev = &componentAttached; + if (!hasEmittedDestruction) { + hasEmittedDestruction = true; + + // Emit the destruction signal - must be emitted before invalidate so that the + // context is still valid if bindings or resultant expression evaluation requires it + if (engine) { + while (componentAttached) { + QQmlComponentAttached *a = componentAttached; + componentAttached = a->next; + if (componentAttached) componentAttached->prev = &componentAttached; - a->next = 0; - a->prev = 0; + a->next = 0; + a->prev = 0; + + emit a->destruction(); + } - emit a->destruction(); + QQmlContextData * child = childContexts; + while (child) { + child->emitDestruction(); + child = child->nextChild; + } + } } +} + +void QQmlContextData::invalidate() +{ + emitDestruction(); while (childContexts) { if (childContexts->ownedByParent) { @@ -563,18 +584,7 @@ void QQmlContextData::invalidate() void QQmlContextData::clearContext() { - if (engine) { - while (componentAttached) { - QQmlComponentAttached *a = componentAttached; - componentAttached = a->next; - if (componentAttached) componentAttached->prev = &componentAttached; - - a->next = 0; - a->prev = 0; - - emit a->destruction(); - } - } + emitDestruction(); QQmlAbstractExpression *expression = expressions; while (expression) { diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h index 97bc04b91d..1f1c6011a2 100644 --- a/src/qml/qml/qqmlcontext_p.h +++ b/src/qml/qml/qqmlcontext_p.h @@ -118,6 +118,7 @@ class Q_QML_EXPORT QQmlContextData public: QQmlContextData(); QQmlContextData(QQmlContext *); + void emitDestruction(); void clearContext(); void destroy(); void invalidate(); @@ -146,7 +147,8 @@ public: quint32 isJSContext:1; quint32 isPragmaLibraryContext:1; quint32 unresolvedNames:1; // True if expressions in this context failed to resolve a toplevel name - quint32 dummy:27; + quint32 hasEmittedDestruction:1; + quint32 dummy:26; QQmlContext *publicContext; // VME data that is constructing this context if any diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index c79e756147..2717ed3a08 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -575,6 +575,11 @@ QQmlEngine::~QQmlEngine() QQmlEngineDebugService::instance()->remEngine(this); } + // Emit onDestruction signals for the root context before + // we destroy the contexts, engine, Module APIs etc. that + // may be required to handle the destruction signal. + QQmlContextData::get(rootContext())->emitDestruction(); + // if we are the parent of any of the qobject module api instances, // we need to remove them from our internal list, in order to prevent // a segfault in engine private dtor. diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp index f2acac5bbc..7e7b6eb570 100644 --- a/src/qml/qml/v8/qv8qobjectwrapper.cpp +++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp @@ -1160,6 +1160,9 @@ void QV8QObjectWrapper::deleteWeakQObject(QV8QObjectResource *resource) ddata->v8object.Clear(); if (!object->parent() && !ddata->indestructible) { + // This object is notionally destroyed now + if (ddata->ownContext && ddata->context) + ddata->context->emitDestruction(); ddata->isQueuedForDeletion = true; object->deleteLater(); } |