aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)) {