diff options
-rw-r--r-- | src/qml/compiler/qqmlcodegenerator.cpp | 6 | ||||
-rw-r--r-- | src/qml/compiler/qqmlcodegenerator_p.h | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata_p.h | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlabstractbinding_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 7 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 407 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator_p.h | 51 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache_p.h | 7 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 33 |
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)) { |