aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-09-08 11:05:20 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-12 23:00:19 +0200
commit346662cb011b7962a8cabf6d55742cd050a6ba6c (patch)
treeef71f9e15cfb6816c793eff5c9c097cf2d121ff9
parent845b07dad47e63bf285461433f4321d71c6c343d (diff)
Fix error reporting timing
Errors for example in signal declarations are usually reported in the loader thread, during property cache construction. This patch separates out the property cache population into QQmlPropertyCacheCreator, runs it from the loader thread and reduces the QQmlObjectCreator to merely set the properties/bindings/ functions on the object. This also enables location tracking for signal declarations and their error reporting. Change-Id: Ief1ffbb3113f8279a50d1a12dab8dbe096702a60 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r--src/qml/compiler/qqmlcodegenerator.cpp6
-rw-r--r--src/qml/compiler/qqmlcodegenerator_p.h2
-rw-r--r--src/qml/compiler/qv4compileddata_p.h1
-rw-r--r--src/qml/qml/qqmlabstractbinding_p.h4
-rw-r--r--src/qml/qml/qqmlcomponent.cpp7
-rw-r--r--src/qml/qml/qqmlcomponent_p.h2
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp407
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h51
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h7
-rw-r--r--src/qml/qml/qqmltypeloader.cpp33
10 files changed, 289 insertions, 231 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp
index e3c5660f47..48e21278da 100644
--- a/src/qml/compiler/qqmlcodegenerator.cpp
+++ b/src/qml/compiler/qqmlcodegenerator.cpp
@@ -201,6 +201,11 @@ int QQmlCodeGenerator::defineQMLObject(AST::UiQualifiedId *qualifiedTypeNameId,
qSwap(_object, obj);
_object->inheritedTypeNameIndex = registerString(asString(qualifiedTypeNameId));
+
+ AST::SourceLocation loc = qualifiedTypeNameId->firstSourceLocation();
+ _object->location.line = loc.startLine;
+ _object->location.column = loc.startColumn;
+
_object->idIndex = registerString(QString());
_object->indexOfDefaultProperty = -1;
_object->properties = New<PoolList<QmlProperty> >();
@@ -681,6 +686,7 @@ QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(ParsedQML &output)
objectToWrite->inheritedTypeNameIndex = o->inheritedTypeNameIndex;
objectToWrite->indexOfDefaultProperty = o->indexOfDefaultProperty;
objectToWrite->idIndex = o->idIndex;
+ objectToWrite->location = o->location;
quint32 nextOffset = sizeof(QV4::CompiledData::Object);
diff --git a/src/qml/compiler/qqmlcodegenerator_p.h b/src/qml/compiler/qqmlcodegenerator_p.h
index 850bec95a0..4d6b988fb8 100644
--- a/src/qml/compiler/qqmlcodegenerator_p.h
+++ b/src/qml/compiler/qqmlcodegenerator_p.h
@@ -138,6 +138,8 @@ struct QmlObject
int idIndex;
int indexOfDefaultProperty;
+ QV4::CompiledData::Location location;
+
PoolList<QmlProperty> *properties;
PoolList<Signal> *qmlSignals;
PoolList<Binding> *bindings;
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 3224adad54..1308469564 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -312,6 +312,7 @@ struct Object
quint32 offsetToSignals; // which in turn will be a table with offsets to variable-sized Signal objects
quint32 nBindings;
quint32 offsetToBindings;
+ Location location;
// Function[]
// Property[]
// Signal[]
diff --git a/src/qml/qml/qqmlabstractbinding_p.h b/src/qml/qml/qqmlabstractbinding_p.h
index 8b04d823e2..ebe81d647a 100644
--- a/src/qml/qml/qqmlabstractbinding_p.h
+++ b/src/qml/qml/qqmlabstractbinding_p.h
@@ -60,9 +60,7 @@
QT_BEGIN_NAMESPACE
-namespace QtQml {
class QmlObjectCreator;
-}
class Q_QML_PRIVATE_EXPORT QQmlAbstractBinding
{
@@ -154,7 +152,7 @@ private:
friend class QQmlVME;
friend class QtSharedPointer::ExternalRefCount<QQmlAbstractBinding>;
friend class QV4Bindings;
- friend class QtQml::QmlObjectCreator;
+ friend class QmlObjectCreator;
typedef QSharedPointer<QQmlAbstractBinding> SharedPointer;
// To save memory, we also store the rarely used weakPointer() instance in here
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 475e69cd77..dfa8fc701d 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -896,7 +896,12 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
enginePriv->referenceScarceResources();
QObject *rv = 0;
if (enginePriv->useNewCompiler) {
- state.creator = new QtQml::QmlObjectCreator(engine, url, context, cc);
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
+ if (cc->compilationUnit && !cc->compilationUnit->engine)
+ cc->compilationUnit->linkToEngine(v4);
+
+ state.creator = new QmlObjectCreator(context, cc->qmlUnit, cc->compilationUnit, cc->importCache,
+ cc->propertyCaches, cc->datas);
rv = state.creator->create();
if (!rv)
state.errors = state.creator->errors;
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index 3bd0a194df..08e4dcea7d 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -116,7 +116,7 @@ public:
}
// --- new compiler
- QtQml::QmlObjectCreator *creator;
+ QmlObjectCreator *creator;
// --- old compiler
QQmlVME vme;
// ---
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index e637610800..ad437da88c 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -52,213 +52,37 @@
QT_USE_NAMESPACE
-using namespace QtQml;
-
-static void removeBindingOnProperty(QObject *o, int index)
-{
- int coreIndex = index & 0x0000FFFF;
- int valueTypeIndex = (index & 0xFFFF0000 ? index >> 16 : -1);
-
- QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(o, coreIndex, valueTypeIndex, 0);
- if (binding) binding->destroy();
-}
-
-QmlObjectCreator::QmlObjectCreator(QQmlEngine *engine, const QUrl &url, QQmlContextData *contextData, QQmlCompiledData *runtimeData)
- : engine(engine)
- , url(url)
- , unit(runtimeData->qmlUnit)
- , jsUnit(runtimeData->compilationUnit)
- , context(contextData)
- , typeNameCache(runtimeData->importCache)
- , runtimeData(runtimeData)
- , imports(&QQmlEnginePrivate::get(engine)->typeLoader)
- , _object(0)
- , _ddata(0)
- , _propertyCache(0)
-{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
- if (runtimeData->compilationUnit && !runtimeData->compilationUnit->engine)
- runtimeData->compilationUnit->linkToEngine(v4);
-}
-
-QVector<QQmlAbstractBinding*> QmlObjectCreator::setupBindings(const QV4::CompiledData::Object *obj, QV4::Object *qmlGlobal)
-{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
-
- QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
- int propertyWriteStatus = -1;
- QVariant fallbackVariantValue;
-
- QVector<QQmlAbstractBinding*> createdDynamicBindings(obj->nBindings, 0);
-
- const QV4::CompiledData::Binding *binding = obj->bindingTable();
- for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
- QString name = stringAt(binding->propertyNameIndex);
-
- if (name.isEmpty() && binding->value.type == QV4::CompiledData::Value::Type_Object) {
- create(binding->value.objectIndex, _object);
- continue;
- }
-
- QQmlPropertyData *property = _propertyCache->property(name, _object, context);
-
- if (_ddata->hasBindingBit(property->coreIndex))
- removeBindingOnProperty(_object, property->coreIndex);
-
- if (binding->value.type == QV4::CompiledData::Value::Type_Script) {
- QV4::Function *runtimeFunction = jsUnit->runtimeFunctions[binding->value.compiledScriptIndex];
- QV4::FunctionObject *function = new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, runtimeFunction, qmlGlobal);
- QQmlBinding *binding = new QQmlBinding(QV4::Value::fromObject(function), _object, context,
- QString(), 0, 0); // ###
-
- binding->setTarget(_object, *property, context);
- binding->addToObject();
-
- createdDynamicBindings[i] = binding;
- binding->m_mePtr = &createdDynamicBindings[i];
- continue;
- }
-
- void *argv[] = { 0, 0, &propertyWriteStatus, &propertyWriteFlags };
-
- // shortcuts
-#if 0
- if (property->propType == QMetaType::Double && binding->value.type == QV4::CompiledData::Value::Type_Number) {
- argv[0] = const_cast<double*>(&binding->value.d);
- } else if (property->propType == QMetaType::Bool && binding->value.type == QV4::CompiledData::Value::Type_Boolean) {
- argv[0] = const_cast<bool*>(&binding->value.b);
- } else
-#endif
- {
- // fallback
- fallbackVariantValue = variantForBinding(property->propType, binding);
-
- if (property->propType == QMetaType::QVariant)
- argv[0] = &fallbackVariantValue;
- else
- argv[0] = fallbackVariantValue.data();
- }
-
- QMetaObject::metacall(_object, QMetaObject::WriteProperty, property->coreIndex, argv);
+#define COMPILE_EXCEPTION(token, desc) \
+ { \
+ recordError((token)->location, desc); \
+ return false; \
}
- return createdDynamicBindings;
-}
+static QAtomicInt classIndexCounter(0);
-void QmlObjectCreator::setupFunctions(const QV4::CompiledData::Object *obj, QV4::Object *qmlGlobal)
+QQmlPropertyCacheCreator::QQmlPropertyCacheCreator(QQmlEnginePrivate *enginePrivate, const QV4::CompiledData::QmlUnit *unit, const QUrl &url, QQmlTypeNameCache *typeNameCache, const QQmlImports *imports)
+ : enginePrivate(enginePrivate)
+ , unit(unit)
+ , url(url)
+ , typeNameCache(typeNameCache)
+ , imports(imports)
{
- QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(_object);
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
-
- const quint32 *functionIdx = obj->functionOffsetTable();
- for (quint32 i = 0; i < obj->nFunctions; ++i, ++functionIdx) {
- QV4::Function *function = jsUnit->runtimeFunctions[*functionIdx];
- const QString name = function->name->toQString();
-
- QQmlPropertyData *property = _propertyCache->property(name, _object, context);
- if (!property->isVMEFunction())
- continue;
-
- QV4::FunctionObject *v4Function = new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, function, qmlGlobal);
- vme->setVmeMethod(property->coreIndex, QV4::Value::fromObject(v4Function));
- }
}
-QObject *QmlObjectCreator::create(int index, QObject *parent)
+bool QQmlPropertyCacheCreator::create(const QV4::CompiledData::Object *obj, QQmlPropertyCache **resultCache, QByteArray *vmeMetaObjectData)
{
- const QV4::CompiledData::Object *obj = unit->objectAt(index);
-
QQmlTypeNameCache::Result res = typeNameCache->query(stringAt(obj->inheritedTypeNameIndex));
- if (!res.isValid())
- return 0;
-
- QObject *result = res.type->create();
- // ### use no-event variant
- if (parent)
- result->setParent(parent);
-
- QQmlData *declarativeData = QQmlData::get(result, /*create*/true);
-
- qSwap(_object, result);
- qSwap(_ddata, declarativeData);
-
- context->addObject(_object);
-
- // ### avoid _object->metaObject
- QQmlRefPointer<QQmlPropertyCache> baseTypeCache = QQmlEnginePrivate::get(engine)->cache(_object->metaObject());
-
- QQmlRefPointer<QQmlPropertyCache> cache;
- QByteArray vmeMetaData;
-
- const bool customMO = needsCustomMetaObject(obj);
- if (customMO) {
- QQmlPropertyCache *newCache = 0;
- if (!createVMEMetaObjectAndPropertyCache(obj, baseTypeCache, &newCache, &vmeMetaData))
- return 0;
- cache = newCache;
- } else {
- cache = baseTypeCache;
- }
-
- baseTypeCache = 0;
-
- qSwap(_propertyCache, cache);
+ Q_ASSERT(res.isValid()); // types resolved earlier in resolveTypes()
- if (customMO) {
- runtimeData->datas.append(vmeMetaData);
- // install on _object
- (void)new QQmlVMEMetaObject(_object, _propertyCache, reinterpret_cast<const QQmlVMEMetaData*>(runtimeData->datas.last().constData()));
- if (_ddata->propertyCache)
- _ddata->propertyCache->release();
- _ddata->propertyCache = _propertyCache;
- _ddata->propertyCache->addref();
- }
-
- QV4::Value scopeObject = QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, _object);
-
- QVector<QQmlAbstractBinding*> dynamicBindings = setupBindings(obj, scopeObject.asObject());
- setupFunctions(obj, scopeObject.asObject());
-
- // ### do this later when requested
- for (int i = 0; i < dynamicBindings.count(); ++i) {
- QQmlAbstractBinding *b = dynamicBindings.at(i);
- if (!b)
- continue;
- b->m_mePtr = 0;
- QQmlData *data = QQmlData::get(b->object());
- Q_ASSERT(data);
- data->clearPendingBindingBit(b->propertyIndex());
- b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::DontRemoveBinding);
- }
-
- qSwap(_propertyCache, cache);
- qSwap(_ddata, declarativeData);
- qSwap(_object, result);
-
- return result;
-}
-
-bool QmlObjectCreator::needsCustomMetaObject(const QV4::CompiledData::Object *obj)
-{
- return obj->nProperties > 0 || obj->nSignals > 0 || obj->nFunctions > 0;
-}
-
-#define COMPILE_EXCEPTION(token, desc) \
- { \
- recordError((token)->location, desc); \
- return false; \
+ QQmlPropertyCache *baseTypeCache = enginePrivate->cache(res.type->metaObject());
+ if (obj->nProperties == 0 && obj->nSignals == 0 && obj->nFunctions == 0) {
+ *resultCache = baseTypeCache;
+ vmeMetaObjectData->clear();
+ return true;
}
-static QAtomicInt classIndexCounter(0);
-
-bool QmlObjectCreator::createVMEMetaObjectAndPropertyCache(const QV4::CompiledData::Object *obj, QQmlPropertyCache *baseTypeCache, QQmlPropertyCache **outputCache, QByteArray *vmeMetaObjectData)
-{
- Q_ASSERT(needsCustomMetaObject(obj));
-
- QQmlPropertyCache *cache = baseTypeCache->copyAndReserve(engine, obj->nProperties, /*methodCount*/0, /*signalCount*/0);
- *outputCache = cache;
+ QQmlPropertyCache *cache = baseTypeCache->copyAndReserve(QQmlEnginePrivate::get(enginePrivate), obj->nProperties, obj->nFunctions, obj->nSignals);
+ *resultCache = cache;
vmeMetaObjectData->clear();
@@ -410,11 +234,11 @@ bool QmlObjectCreator::createVMEMetaObjectAndPropertyCache(const QV4::CompiledDa
Q_ASSERT(param->type == QV4::CompiledData::Property::Custom);
const QString customTypeName = stringAt(param->customTypeNameIndex);
QQmlType *qmltype = 0;
- if (!imports.resolveType(customTypeName, &qmltype, 0, 0, 0))
+ if (!imports->resolveType(customTypeName, &qmltype, 0, 0, 0))
COMPILE_EXCEPTION(s, tr("Invalid signal parameter type: %1").arg(customTypeName));
if (qmltype->isComposite()) {
- QQmlTypeData *tdata = QQmlEnginePrivate::get(engine)->typeLoader.getType(qmltype->sourceUrl());
+ QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype->sourceUrl());
Q_ASSERT(tdata);
Q_ASSERT(tdata->isComplete());
@@ -506,13 +330,13 @@ bool QmlObjectCreator::createVMEMetaObjectAndPropertyCache(const QV4::CompiledDa
p->type == QV4::CompiledData::Property::Custom);
QQmlType *qmltype = 0;
- if (!imports.resolveType(stringAt(p->customTypeNameIndex), &qmltype, 0, 0, 0)) {
+ if (!imports->resolveType(stringAt(p->customTypeNameIndex), &qmltype, 0, 0, 0)) {
// COMPILE_EXCEPTION(p, tr("Invalid property type"));
}
Q_ASSERT(qmltype);
if (qmltype->isComposite()) {
- QQmlTypeData *tdata = QQmlEnginePrivate::get(engine)->typeLoader.getType(qmltype->sourceUrl());
+ QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype->sourceUrl());
Q_ASSERT(tdata);
Q_ASSERT(tdata->isComplete());
@@ -605,6 +429,188 @@ bool QmlObjectCreator::createVMEMetaObjectAndPropertyCache(const QV4::CompiledDa
return true;
}
+void QQmlPropertyCacheCreator::recordError(const QV4::CompiledData::Location &location, const QString &description)
+{
+ QQmlError error;
+ error.setUrl(url);
+ error.setLine(location.line);
+ error.setColumn(location.column);
+ error.setDescription(description);
+ errors << error;
+}
+
+static void removeBindingOnProperty(QObject *o, int index)
+{
+ int coreIndex = index & 0x0000FFFF;
+ int valueTypeIndex = (index & 0xFFFF0000 ? index >> 16 : -1);
+
+ QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(o, coreIndex, valueTypeIndex, 0);
+ if (binding) binding->destroy();
+}
+
+QmlObjectCreator::QmlObjectCreator(QQmlContextData *contextData, const QV4::CompiledData::QmlUnit *qmlUnit,
+ const QV4::CompiledData::CompilationUnit *jsUnit, QQmlTypeNameCache *typeNameCache,
+ const QList<QQmlPropertyCache*> &propertyCaches,
+ const QList<QByteArray> &vmeMetaObjectData)
+ : engine(contextData->engine)
+ , unit(qmlUnit)
+ , jsUnit(jsUnit)
+ , context(contextData)
+ , typeNameCache(typeNameCache)
+ , propertyCaches(propertyCaches)
+ , vmeMetaObjectData(vmeMetaObjectData)
+ , _qobject(0)
+ , _compiledObject(0)
+ , _ddata(0)
+ , _propertyCache(0)
+{
+}
+
+QVector<QQmlAbstractBinding*> QmlObjectCreator::setupBindings(QV4::Object *qmlGlobal)
+{
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
+
+ QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
+ QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
+ int propertyWriteStatus = -1;
+ QVariant fallbackVariantValue;
+
+ QVector<QQmlAbstractBinding*> createdDynamicBindings(_compiledObject->nBindings, 0);
+
+ const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
+ for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
+ QString name = stringAt(binding->propertyNameIndex);
+
+ if (name.isEmpty() && binding->value.type == QV4::CompiledData::Value::Type_Object) {
+ create(binding->value.objectIndex, _qobject);
+ continue;
+ }
+
+ QQmlPropertyData *property = _propertyCache->property(name, _qobject, context);
+
+ if (_ddata->hasBindingBit(property->coreIndex))
+ removeBindingOnProperty(_qobject, property->coreIndex);
+
+ if (binding->value.type == QV4::CompiledData::Value::Type_Script) {
+ QV4::Function *runtimeFunction = jsUnit->runtimeFunctions[binding->value.compiledScriptIndex];
+ QV4::FunctionObject *function = new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, runtimeFunction, qmlGlobal);
+ QQmlBinding *binding = new QQmlBinding(QV4::Value::fromObject(function), _qobject, context,
+ QString(), 0, 0); // ###
+
+ binding->setTarget(_qobject, *property, context);
+ binding->addToObject();
+
+ createdDynamicBindings[i] = binding;
+ binding->m_mePtr = &createdDynamicBindings[i];
+ continue;
+ }
+
+ void *argv[] = { 0, 0, &propertyWriteStatus, &propertyWriteFlags };
+
+ // shortcuts
+#if 0
+ if (property->propType == QMetaType::Double && binding->value.type == QV4::CompiledData::Value::Type_Number) {
+ argv[0] = const_cast<double*>(&binding->value.d);
+ } else if (property->propType == QMetaType::Bool && binding->value.type == QV4::CompiledData::Value::Type_Boolean) {
+ argv[0] = const_cast<bool*>(&binding->value.b);
+ } else
+#endif
+ {
+ // fallback
+ fallbackVariantValue = variantForBinding(property->propType, binding);
+
+ if (property->propType == QMetaType::QVariant)
+ argv[0] = &fallbackVariantValue;
+ else
+ argv[0] = fallbackVariantValue.data();
+ }
+
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ }
+
+ return createdDynamicBindings;
+}
+
+void QmlObjectCreator::setupFunctions(QV4::Object *qmlGlobal)
+{
+ QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(_qobject);
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
+
+ const quint32 *functionIdx = _compiledObject->functionOffsetTable();
+ for (quint32 i = 0; i < _compiledObject->nFunctions; ++i, ++functionIdx) {
+ QV4::Function *function = jsUnit->runtimeFunctions[*functionIdx];
+ const QString name = function->name->toQString();
+
+ QQmlPropertyData *property = _propertyCache->property(name, _qobject, context);
+ if (!property->isVMEFunction())
+ continue;
+
+ QV4::FunctionObject *v4Function = new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, function, qmlGlobal);
+ vme->setVmeMethod(property->coreIndex, QV4::Value::fromObject(v4Function));
+ }
+}
+
+QObject *QmlObjectCreator::create(int index, QObject *parent)
+{
+ const QV4::CompiledData::Object *obj = unit->objectAt(index);
+
+ QQmlTypeNameCache::Result res = typeNameCache->query(stringAt(obj->inheritedTypeNameIndex));
+ if (!res.isValid())
+ return 0;
+
+ QObject *result = res.type->create();
+ // ### use no-event variant
+ if (parent)
+ result->setParent(parent);
+
+ QQmlData *declarativeData = QQmlData::get(result, /*create*/true);
+
+ QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches.value(index);
+ Q_ASSERT(!cache.isNull());
+
+ qSwap(_propertyCache, cache);
+ qSwap(_qobject, result);
+ qSwap(_compiledObject, obj);
+ qSwap(_ddata, declarativeData);
+
+ context->addObject(_qobject);
+
+ const QByteArray data = vmeMetaObjectData.value(index);
+ if (!data.isEmpty()) {
+ // install on _object
+ (void)new QQmlVMEMetaObject(_qobject, _propertyCache, reinterpret_cast<const QQmlVMEMetaData*>(data.constData()));
+ if (_ddata->propertyCache)
+ _ddata->propertyCache->release();
+ _ddata->propertyCache = _propertyCache;
+ _ddata->propertyCache->addref();
+ }
+
+ QV4::Value scopeObject = QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, _qobject);
+
+ QVector<QQmlAbstractBinding*> dynamicBindings = setupBindings(scopeObject.asObject());
+ setupFunctions(scopeObject.asObject());
+
+ // ### do this later when requested
+ for (int i = 0; i < dynamicBindings.count(); ++i) {
+ QQmlAbstractBinding *b = dynamicBindings.at(i);
+ if (!b)
+ continue;
+ b->m_mePtr = 0;
+ QQmlData *data = QQmlData::get(b->object());
+ Q_ASSERT(data);
+ data->clearPendingBindingBit(b->propertyIndex());
+ b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
+ QQmlPropertyPrivate::DontRemoveBinding);
+ }
+
+ qSwap(_propertyCache, cache);
+ qSwap(_ddata, declarativeData);
+ qSwap(_compiledObject, obj);
+ qSwap(_qobject, result);
+
+ return result;
+}
+
QVariant QmlObjectCreator::variantForBinding(int expectedMetaType, const QV4::CompiledData::Binding *binding) const
{
QVariant result;
@@ -686,4 +692,3 @@ void QmlObjectCreator::recordError(const QV4::CompiledData::Location &location,
error.setDescription(description);
errors << error;
}
-
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index de868560e9..fc7aa2040c 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -49,17 +49,34 @@ QT_BEGIN_NAMESPACE
class QQmlAbstractBinding;
-namespace QtQml {
+class QQmlPropertyCacheCreator
+{
+ Q_DECLARE_TR_FUNCTIONS(QQmlPropertyCacheCreator)
+public:
+ QQmlPropertyCacheCreator(QQmlEnginePrivate *enginePrivate, const QV4::CompiledData::QmlUnit *unit,
+ const QUrl &url, QQmlTypeNameCache *typeNameCache, const QQmlImports *imports);
+
+ QList<QQmlError> errors;
+
+ bool create(const QV4::CompiledData::Object *obj, QQmlPropertyCache **cache, QByteArray *vmeMetaObjectData);
+
+protected:
+ QString stringAt(int idx) const { return unit->header.stringAt(idx); }
+ void recordError(const QV4::CompiledData::Location &location, const QString &description);
+
+ QQmlEnginePrivate *enginePrivate;
+ const QV4::CompiledData::QmlUnit *unit;
+ QUrl url;
+ QQmlTypeNameCache *typeNameCache;
+ const QQmlImports *imports;
+};
-class Q_QML_EXPORT QmlObjectCreator
+class QmlObjectCreator
{
Q_DECLARE_TR_FUNCTIONS(QQmlCompiler)
public:
-
- QmlObjectCreator(QQmlEngine *engine, const QUrl &url,
- // extra data/output stored in these two
- QQmlContextData *contextData,
- QQmlCompiledData *runtimeData);
+ QmlObjectCreator(QQmlContextData *contextData, const QV4::CompiledData::QmlUnit *qmlUnit, const QV4::CompiledData::CompilationUnit *jsUnit,
+ QQmlTypeNameCache *typeNameCache, const QList<QQmlPropertyCache *> &propertyCaches, const QList<QByteArray> &vmeMetaObjectData);
QObject *create(QObject *parent = 0)
{ return create(unit->indexOfRootObject, parent); }
@@ -67,15 +84,9 @@ public:
QList<QQmlError> errors;
- static bool needsCustomMetaObject(const QV4::CompiledData::Object *obj);
- bool createVMEMetaObjectAndPropertyCache(const QV4::CompiledData::Object *obj, QQmlPropertyCache *baseTypeCache,
- // out parameters
- QQmlPropertyCache **cache, QByteArray *vmeMetaObjectData);
private:
- QString stringAt(int idx) const { return unit->header.stringAt(idx); }
-
- QVector<QQmlAbstractBinding *> setupBindings(const QV4::CompiledData::Object *obj, QV4::Object *qmlGlobal);
- void setupFunctions(const QV4::CompiledData::Object *obj, QV4::Object *qmlGlobal);
+ QVector<QQmlAbstractBinding *> setupBindings(QV4::Object *qmlGlobal);
+ void setupFunctions(QV4::Object *qmlGlobal);
QVariant variantForBinding(int expectedMetaType, const QV4::CompiledData::Binding *binding) const;
@@ -83,6 +94,7 @@ private:
static double valueAsNumber(const QV4::CompiledData::Value *value);
static bool valueAsBoolean(const QV4::CompiledData::Value *value);
+ QString stringAt(int idx) const { return unit->header.stringAt(idx); }
void recordError(const QV4::CompiledData::Location &location, const QString &description);
QQmlEngine *engine;
@@ -91,16 +103,15 @@ private:
const QV4::CompiledData::CompilationUnit *jsUnit;
QQmlContextData *context;
QQmlTypeNameCache *typeNameCache;
- QQmlCompiledData *runtimeData;
- QQmlImports imports;
+ const QList<QQmlPropertyCache *> propertyCaches;
+ const QList<QByteArray> vmeMetaObjectData;
- QObject *_object;
+ QObject *_qobject;
+ const QV4::CompiledData::Object *_compiledObject;
QQmlData *_ddata;
QQmlRefPointer<QQmlPropertyCache> _propertyCache;
};
-} // end namespace QtQml
-
QT_END_NAMESPACE
#endif // QQMLOBJECTCREATOR_P_H
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index fe509843ab..32c0018819 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -66,10 +66,6 @@
QT_BEGIN_NAMESPACE
-namespace QtQml {
-class QmlObjectCreator;
-}
-
class QV8Engine;
class QMetaProperty;
class QQmlEngine;
@@ -78,6 +74,7 @@ class QQmlAccessors;
class QMetaObjectBuilder;
class QQmlPropertyCacheMethodArguments;
class QQmlVMEMetaObject;
+class QQmlPropertyCacheCreator;
// We have this somewhat awful split between RawData and Data so that RawData can be
// used in unions. In normal code, you should always use Data which initializes RawData
@@ -343,7 +340,7 @@ protected:
private:
friend class QQmlEnginePrivate;
friend class QQmlCompiler;
- friend class QtQml::QmlObjectCreator;
+ friend class QQmlPropertyCacheCreator;
inline QQmlPropertyCache *copy(int reserve);
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 8c3826b6df..0f83da7b0a 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2189,6 +2189,39 @@ void QQmlTypeData::compile()
if (m_compiledData->compilationUnit)
m_compiledData->compilationUnit->ref();
m_compiledData->qmlUnit = qmlUnit; // ownership transferred to m_compiledData
+
+ QList<QQmlError> errors;
+
+ m_compiledData->datas.reserve(qmlUnit->nObjects);
+ m_compiledData->propertyCaches.reserve(qmlUnit->nObjects);
+
+ QQmlPropertyCacheCreator propertyCacheBuilder(QQmlEnginePrivate::get(m_typeLoader->engine()),
+ qmlUnit, m_compiledData->url, m_compiledData->importCache,
+ &m_imports);
+
+ for (quint32 i = 0; i < qmlUnit->nObjects; ++i) {
+ const QV4::CompiledData::Object *obj = qmlUnit->objectAt(i);
+
+ QByteArray vmeMetaObjectData;
+ QQmlPropertyCache *propertyCache = 0;
+
+ if (!propertyCacheBuilder.create(obj, &propertyCache, &vmeMetaObjectData)) {
+ errors << propertyCacheBuilder.errors;
+ break;
+ }
+
+ Q_ASSERT(propertyCache);
+
+ m_compiledData->datas << vmeMetaObjectData;
+ propertyCache->addref();
+ m_compiledData->propertyCaches << propertyCache;
+ }
+
+ if (!errors.isEmpty()) {
+ setError(errors);
+ m_compiledData->release();
+ m_compiledData = 0;
+ }
} else {
QQmlCompiler compiler(&scriptParser._pool);
if (!compiler.compile(typeLoader()->engine(), this, m_compiledData)) {