diff options
Diffstat (limited to 'src/qml/qml/qqmlobjectcreator.cpp')
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 140 |
1 files changed, 50 insertions, 90 deletions
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index cf1795aafa..d68ad69260 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -59,22 +59,12 @@ #include <private/qjsvalue_p.h> #include <private/qv4generatorobject_p.h> +#include <QScopedValueRollback> + #include <qtqml_tracepoints_p.h> QT_USE_NAMESPACE -namespace { -struct ActiveOCRestorer -{ - ActiveOCRestorer(QQmlObjectCreator *creator, QQmlEnginePrivate *ep) - : ep(ep), oldCreator(ep->activeObjectCreator) { ep->activeObjectCreator = creator; } - ~ActiveOCRestorer() { ep->activeObjectCreator = oldCreator; } - - QQmlEnginePrivate *ep; - QQmlObjectCreator *oldCreator; -}; -} - QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlContextData *creationContext, QQmlIncubatorPrivate *incubator) : phase(Startup) @@ -234,73 +224,20 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI return instance; } -// ### unify or keep in sync with populateDeferredBinding() -bool QQmlObjectCreator::populateDeferredProperties(QObject *instance, QQmlData::DeferredData *deferredData) +void QQmlObjectCreator::beginPopulateDeferred(QQmlContextData *newContext) { - QQmlData *declarativeData = QQmlData::get(instance); - context = deferredData->context; - sharedState->rootContext = context; - - QObject *bindingTarget = instance; - - QQmlRefPointer<QQmlPropertyCache> cache = declarativeData->propertyCache; - QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(instance); - - QObject *scopeObject = instance; - qSwap(_scopeObject, scopeObject); - - QV4::Scope valueScope(v4); + context = newContext; + sharedState->rootContext = newContext; Q_ASSERT(topLevelCreator); Q_ASSERT(!sharedState->allJavaScriptObjects); - sharedState->allJavaScriptObjects = valueScope.alloc(compilationUnit->totalObjectCount); - - QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc()); - - qSwap(_qmlContext, qmlContext); - - qSwap(_propertyCache, cache); - qSwap(_qobject, instance); - - int objectIndex = deferredData->deferredIdx; - qSwap(_compiledObjectIndex, objectIndex); - - const QV4::CompiledData::Object *obj = compilationUnit->objectAt(_compiledObjectIndex); - qSwap(_compiledObject, obj); - - qSwap(_ddata, declarativeData); - qSwap(_bindingTarget, bindingTarget); - qSwap(_vmeMetaObject, vmeMetaObject); - - setupBindings(/*applyDeferredBindings=*/true); - - qSwap(_vmeMetaObject, vmeMetaObject); - qSwap(_bindingTarget, bindingTarget); - qSwap(_ddata, declarativeData); - qSwap(_compiledObject, obj); - qSwap(_compiledObjectIndex, objectIndex); - qSwap(_qobject, instance); - qSwap(_propertyCache, cache); - - qSwap(_qmlContext, qmlContext); - qSwap(_scopeObject, scopeObject); - - deferredData->bindings.clear(); - phase = ObjectsCreated; - - return errors.isEmpty(); } -// ### unify or keep in sync with populateDeferredProperties() -bool QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty, QQmlData::DeferredData *deferredData, const QV4::CompiledData::Binding *binding) +void QQmlObjectCreator::populateDeferred(QObject *instance, int deferredIndex, + const QQmlPropertyPrivate *qmlProperty, + const QV4::CompiledData::Binding *binding) { - Q_ASSERT(binding->flags & QV4::CompiledData::Binding::IsDeferredBinding); - - QObject *instance = qmlProperty.object(); QQmlData *declarativeData = QQmlData::get(instance); - context = deferredData->context; - sharedState->rootContext = context; - QObject *bindingTarget = instance; QQmlRefPointer<QQmlPropertyCache> cache = declarativeData->propertyCache; @@ -310,11 +247,10 @@ bool QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty, qSwap(_scopeObject, scopeObject); QV4::Scope valueScope(v4); + QScopedValueRollback<QV4::Value*> jsObjectGuard(sharedState->allJavaScriptObjects, + valueScope.alloc(compilationUnit->totalObjectCount)); Q_ASSERT(topLevelCreator); - if (!sharedState->allJavaScriptObjects) - sharedState->allJavaScriptObjects = valueScope.alloc(compilationUnit->totalObjectCount); - QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc()); qSwap(_qmlContext, qmlContext); @@ -322,7 +258,7 @@ bool QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty, qSwap(_propertyCache, cache); qSwap(_qobject, instance); - int objectIndex = deferredData->deferredIdx; + int objectIndex = deferredIndex; qSwap(_compiledObjectIndex, objectIndex); const QV4::CompiledData::Object *obj = compilationUnit->objectAt(_compiledObjectIndex); @@ -332,21 +268,28 @@ bool QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty, qSwap(_bindingTarget, bindingTarget); qSwap(_vmeMetaObject, vmeMetaObject); - QQmlListProperty<void> savedList; - qSwap(_currentList, savedList); + if (binding) { + Q_ASSERT(qmlProperty); + Q_ASSERT(binding->flags & QV4::CompiledData::Binding::IsDeferredBinding); - const QQmlPropertyData &property = QQmlPropertyPrivate::get(qmlProperty)->core; + QQmlListProperty<void> savedList; + qSwap(_currentList, savedList); - if (property.isQList()) { - void *argv[1] = { (void*)&_currentList }; - QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property.coreIndex(), argv); - } else if (_currentList.object) { - _currentList = QQmlListProperty<void>(); - } + const QQmlPropertyData &property = qmlProperty->core; - setPropertyBinding(&property, binding); + if (property.isQList()) { + void *argv[1] = { (void*)&_currentList }; + QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property.coreIndex(), argv); + } else if (_currentList.object) { + _currentList = QQmlListProperty<void>(); + } - qSwap(_currentList, savedList); + setPropertyBinding(&property, binding); + + qSwap(_currentList, savedList); + } else { + setupBindings(/*applyDeferredBindings=*/true); + } qSwap(_vmeMetaObject, vmeMetaObject); qSwap(_bindingTarget, bindingTarget); @@ -358,12 +301,29 @@ bool QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty, qSwap(_qmlContext, qmlContext); qSwap(_scopeObject, scopeObject); +} - phase = ObjectsCreated; - +bool QQmlObjectCreator::populateDeferredProperties(QObject *instance, + const QQmlData::DeferredData *deferredData) +{ + beginPopulateDeferred(deferredData->context); + populateDeferred(instance, deferredData->deferredIdx); + finalizePopulateDeferred(); return errors.isEmpty(); } +void QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty, int deferredIndex, + const QV4::CompiledData::Binding *binding) +{ + populateDeferred(qmlProperty.object(), deferredIndex, QQmlPropertyPrivate::get(qmlProperty), + binding); +} + +void QQmlObjectCreator::finalizePopulateDeferred() +{ + phase = ObjectsCreated; +} + void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) { QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor | QQmlPropertyData::RemoveBindingOnAliasWrite; @@ -1191,7 +1151,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo QString typeName; Q_TRACE_EXIT(QQmlObjectCreator_createInstance_exit, typeName); - ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine)); + QScopedValueRollback<QQmlObjectCreator*> ocRestore(QQmlEnginePrivate::get(engine)->activeObjectCreator, this); bool isComponent = false; QObject *instance = nullptr; @@ -1392,7 +1352,7 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru phase = Finalizing; QQmlObjectCreatorRecursionWatcher watcher(this); - ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine)); + QScopedValueRollback<QQmlObjectCreator*> ocRestore(QQmlEnginePrivate::get(engine)->activeObjectCreator, this); while (!sharedState->allCreatedBindings.isEmpty()) { QQmlAbstractBinding::Ptr b = sharedState->allCreatedBindings.pop(); |