aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-03-04 20:48:11 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-05 15:01:07 +0100
commitc8889fbb5561d75a7a383b86daa89c1b264c6f6e (patch)
tree4393600dc118c8fa9bbd3b518d23ca12d75f67e9 /src/qml
parente4e4a7912b03499a20f25e261e1c515aab17e5a8 (diff)
[new compiler] Add support for deferred properties
Change-Id: I592518444ef353cfcf153df0e6afa2fbac613560 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp53
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h4
-rw-r--r--src/qml/qml/qqmlcompiler_p.h1
-rw-r--r--src/qml/qml/qqmlcomponent.cpp8
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp76
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h1
6 files changed, 133 insertions, 10 deletions
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 0cab2c4397..fd3d8a92e3 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -376,6 +376,11 @@ void QQmlTypeCompiler::setCustomParserBindings(const QVector<int> &bindings)
compiledData->customParserBindings = bindings;
}
+void QQmlTypeCompiler::setDeferredBindingsPerObject(const QHash<int, QBitArray> &deferredBindingsPerObject)
+{
+ compiledData->deferredBindingsPerObject = deferredBindingsPerObject;
+}
+
QQmlCompilePass::QQmlCompilePass(QQmlTypeCompiler *typeCompiler)
: compiler(typeCompiler)
{
@@ -1603,6 +1608,7 @@ QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler)
, propertyCaches(typeCompiler->propertyCaches())
, objectIndexToIdPerComponent(*typeCompiler->objectIndexToIdPerComponent())
, customParserData(typeCompiler->customParserData())
+ , _seenObjectWithId(false)
{
}
@@ -1611,6 +1617,7 @@ bool QQmlPropertyValidator::validate()
if (!validateObject(qmlUnit->indexOfRootObject, /*instantiatingBinding*/0))
return false;
compiler->setCustomParserBindings(customParserBindings);
+ compiler->setDeferredBindingsPerObject(deferredBindingsPerObject);
return true;
}
@@ -1642,6 +1649,8 @@ typedef QVarLengthArray<const QV4::CompiledData::Binding *, 8> GroupPropertyVect
bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty)
{
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
+ if (obj->idIndex != 0)
+ _seenObjectWithId = true;
if (isComponent(objectIndex)) {
Q_ASSERT(obj->nBindings == 1);
@@ -1654,6 +1663,16 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
if (!propertyCache)
return true;
+ QStringList deferredPropertyNames;
+ {
+ const QMetaObject *mo = propertyCache->firstCppMetaObject();
+ const int namesIndex = mo->indexOfClassInfo("DeferredPropertyNames");
+ if (namesIndex != -1) {
+ QMetaClassInfo classInfo = mo->classInfo(namesIndex);
+ deferredPropertyNames = QString::fromUtf8(classInfo.value()).split(QLatin1Char(','));
+ }
+ }
+
QQmlCustomParser *customParser = 0;
QQmlCompiledData::TypeReference *objectType = resolvedTypes.value(obj->inheritedTypeNameIndex);
if (objectType && objectType->type)
@@ -1687,6 +1706,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
}
QBitArray customParserBindings(obj->nBindings);
+ QBitArray deferredBindings;
PropertyResolver propertyResolver(propertyCache);
@@ -1769,16 +1789,32 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
bindingToDefaultProperty = true;
}
+ bool seenSubObjectWithId = false;
+
if (binding->type >= QV4::CompiledData::Binding::Type_Object) {
- if (!validateObject(binding->value.objectIndex, binding, pd && QQmlValueTypeFactory::valueType(pd->propType)))
+ qSwap(_seenObjectWithId, seenSubObjectWithId);
+ const bool subObjectValid = validateObject(binding->value.objectIndex, binding, pd && QQmlValueTypeFactory::valueType(pd->propType));
+ qSwap(_seenObjectWithId, seenSubObjectWithId);
+ if (!subObjectValid)
+ return false;
+ _seenObjectWithId |= seenSubObjectWithId;
+ }
+
+ if (!seenSubObjectWithId
+ && !deferredPropertyNames.isEmpty() && deferredPropertyNames.contains(name)) {
+
+ if (deferredBindings.isEmpty())
+ deferredBindings.resize(obj->nBindings);
+
+ deferredBindings.setBit(i);
+ }
+
+ if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
+ if (instantiatingBinding && (instantiatingBinding->isAttachedProperty() || instantiatingBinding->isGroupProperty())) {
+ recordError(binding->location, tr("Attached properties cannot be used here"));
return false;
- if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
- if (instantiatingBinding && (instantiatingBinding->isAttachedProperty() || instantiatingBinding->isGroupProperty())) {
- recordError(binding->location, tr("Attached properties cannot be used here"));
- return false;
- }
- continue;
}
+ continue;
}
if (pd) {
@@ -1877,6 +1913,9 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
}
}
+ if (!deferredBindings.isEmpty())
+ deferredBindingsPerObject.insert(objectIndex, deferredBindings);
+
return true;
}
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index 405438c0ab..73ca9de8b8 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -98,6 +98,7 @@ public:
QStringRef newStringRef(const QString &string);
const QStringList &stringPool() const;
void setCustomParserBindings(const QVector<int> &bindings);
+ void setDeferredBindingsPerObject(const QHash<int, QBitArray> &deferredBindingsPerObject);
private:
QList<QQmlError> errors;
@@ -264,6 +265,9 @@ private:
const QHash<int, QHash<int, int> > objectIndexToIdPerComponent;
QHash<int, QQmlCompiledData::CustomParserData> *customParserData;
QVector<int> customParserBindings;
+ QHash<int, QBitArray> deferredBindingsPerObject;
+
+ bool _seenObjectWithId;
};
// ### merge with QtQml::JSCodeGen and operate directly on object->functionsAndExpressions once old compiler is gone.
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h
index 1f28e7a370..03134091f0 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlcompiler_p.h
@@ -166,6 +166,7 @@ public:
};
QHash<int, CustomParserData> customParserData;
QVector<int> customParserBindings; // index is binding identifier, value is compiled function index.
+ QHash<int, QBitArray> deferredBindingsPerObject; // index is object index
int totalBindingsCount; // Number of bindings used in this type
int totalParserStatusCount; // Number of instantiated types that are QQmlParserStatus subclasses
int totalObjectCount; // Number of objects explicitly instantiated
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 6431094c4c..feeb42b7ed 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -923,7 +923,13 @@ void QQmlComponentPrivate::beginDeferred(QQmlEnginePrivate *enginePriv,
state->completePending = true;
if (enginePriv->useNewCompiler) {
- // ###
+ QQmlData *ddata = QQmlData::get(object);
+ Q_ASSERT(ddata->deferredData);
+ QQmlData::DeferredData *deferredData = ddata->deferredData;
+ QQmlContextData *creationContext = 0;
+ state->creator = new QQmlObjectCreator(deferredData->context->parent, deferredData->compiledData, creationContext);
+ if (!state->creator->populateDeferredProperties(object))
+ state->errors << state->creator->errors;
} else {
state->vme.initDeferred(object);
state->vme.execute(&state->errors);
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 6ec8c2bea4..abca36c6aa 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -237,6 +237,59 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
return instance;
}
+bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
+{
+ QQmlData *declarativeData = QQmlData::get(instance);
+ context = declarativeData->deferredData->context;
+ const int objectIndex = declarativeData->deferredData->deferredIdx;
+
+ const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
+ QObject *bindingTarget = instance;
+
+ QQmlRefPointer<QQmlPropertyCache> cache = declarativeData->propertyCache;
+ QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(instance);
+
+ QObject *scopeObject = instance;
+ qSwap(_scopeObject, scopeObject);
+
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
+ QV4::Scope valueScope(v4);
+ QV4::ScopedValue scopeObjectProtector(valueScope, declarativeData->jsWrapper.value());
+ Q_UNUSED(scopeObjectProtector);
+ QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, _scopeObject));
+ QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, qmlScope));
+ QV4::ExecutionContext *qmlContext = qmlBindingWrapper->context();
+
+ qSwap(_qmlContext, qmlContext);
+
+ qSwap(_propertyCache, cache);
+ qSwap(_qobject, instance);
+ qSwap(_compiledObject, obj);
+ qSwap(_ddata, declarativeData);
+ qSwap(_bindingTarget, bindingTarget);
+ qSwap(_vmeMetaObject, vmeMetaObject);
+
+ QBitArray bindingSkipList = compiledData->deferredBindingsPerObject.value(objectIndex);
+ for (int i = 0; i < bindingSkipList.count(); ++i)
+ bindingSkipList.setBit(i, !bindingSkipList.testBit(i));
+
+ setupBindings(bindingSkipList);
+
+ qSwap(_vmeMetaObject, vmeMetaObject);
+ qSwap(_bindingTarget, bindingTarget);
+ qSwap(_ddata, declarativeData);
+ qSwap(_compiledObject, obj);
+ qSwap(_qobject, instance);
+ qSwap(_propertyCache, cache);
+
+ qSwap(_qmlContext, qmlContext);
+ qSwap(_scopeObject, scopeObject);
+
+ phase = ObjectsCreated;
+
+ return errors.isEmpty();
+}
+
void QQmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
{
QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
@@ -1009,7 +1062,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent)
customParser = type->customParser();
- if (sharedState->rootContext->isRootObjectInCreation) {
+ if (sharedState->rootContext && sharedState->rootContext->isRootObjectInCreation) {
QQmlData *ddata = QQmlData::get(instance, /*create*/true);
ddata->rootObjectInCreation = true;
sharedState->rootContext->isRootObjectInCreation = false;
@@ -1243,8 +1296,27 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QQmlRefPo
QVector<QQmlAbstractBinding*> createdBindings(_compiledObject->nBindings, 0);
+ QBitArray bindingSkipList = bindingsToSkip;
+ {
+ QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.find(index);
+ if (deferredBindings != compiledData->deferredBindingsPerObject.constEnd()) {
+ if (bindingSkipList.isEmpty())
+ bindingSkipList.resize(deferredBindings->count());
+
+ for (int i = 0; i < deferredBindings->count(); ++i)
+ if (deferredBindings->testBit(i))
+ bindingSkipList.setBit(i);
+ QQmlData::DeferredData *deferData = new QQmlData::DeferredData;
+ deferData->deferredIdx = index;
+ deferData->compiledData = compiledData;
+ deferData->compiledData->addref();
+ deferData->context = context;
+ _ddata->deferredData = deferData;
+ }
+ }
+
setupFunctions();
- setupBindings(bindingsToSkip);
+ setupBindings(bindingSkipList);
qSwap(_vmeMetaObject, vmeMetaObject);
qSwap(_bindingTarget, bindingTarget);
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index b7d6790a81..6717257bcf 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -78,6 +78,7 @@ public:
~QQmlObjectCreator();
QObject *create(int subComponentIndex = -1, QObject *parent = 0, QQmlInstantiationInterrupt *interrupt = 0);
+ bool populateDeferredProperties(QObject *instance);
QQmlContextData *finalize(QQmlInstantiationInterrupt &interrupt);
void clear();