aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-12-11 13:44:56 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-01-08 10:04:43 +0100
commitfb377763ac3eea4010c7a501b8363ca46874a5b3 (patch)
treedb7e22d735b72f7a13c54ddfa116f6209480a1e8 /src
parent2f185926500dba417b95ff33b0546c0d8d3ce9c0 (diff)
[new compiler] Fix signal handlers for properties declared in the same object
We need to generate the property caches before we can try converting the signal handler expressions in the AST to function declarations, as that conversion requires looking up the signal signature / meta-data from the property cache. This in turn requires rewriting the property cache generator code to operate on the data structure we have before creating the QV4::CompiledData. Change-Id: I0d1c59d947f36171b4eb89f47a2e1ff1bc493c6f Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/qml/compiler/qqmlcodegenerator.cpp10
-rw-r--r--src/qml/compiler/qqmlcodegenerator_p.h2
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp86
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h8
-rw-r--r--src/qml/qml/qqmltypeloader.cpp79
5 files changed, 103 insertions, 82 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp
index 19ccb6d0fd..a4da07ab66 100644
--- a/src/qml/compiler/qqmlcodegenerator.cpp
+++ b/src/qml/compiler/qqmlcodegenerator.cpp
@@ -736,6 +736,10 @@ bool QQmlCodeGenerator::visit(AST::UiSourceElement *node)
if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) {
_functions << funDecl;
Function *f = New<Function>();
+ f->functionDeclaration = funDecl;
+ AST::SourceLocation loc = funDecl->firstSourceLocation();
+ f->location.line = loc.startLine;
+ f->location.column = loc.startColumn;
f->index = _functions.size() - 1;
_object->functions->append(f);
} else {
@@ -1616,14 +1620,16 @@ SignalHandlerConverter::SignalHandlerConverter(QQmlEnginePrivate *enginePrivate,
bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclarations()
{
- foreach (QmlObject *obj, parsedQML->objects) {
+ for (int objectIndex = 0; objectIndex < parsedQML->objects.count(); ++objectIndex) {
+ QmlObject * const obj = parsedQML->objects.at(objectIndex);
QString elementName = stringAt(obj->inheritedTypeNameIndex);
if (elementName.isEmpty())
continue;
QQmlCompiledData::TypeReference &tr = unit->resolvedTypes[obj->inheritedTypeNameIndex];
if (tr.type && tr.type->customParser())
continue;
- QQmlPropertyCache *cache = tr.createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
+ QQmlPropertyCache *cache = unit->propertyCaches.value(objectIndex);
+ Q_ASSERT(cache);
if (!convertSignalHandlerExpressionsToFunctionDeclarations(obj, elementName, cache))
return false;
}
diff --git a/src/qml/compiler/qqmlcodegenerator_p.h b/src/qml/compiler/qqmlcodegenerator_p.h
index 83ff716176..18193eea2b 100644
--- a/src/qml/compiler/qqmlcodegenerator_p.h
+++ b/src/qml/compiler/qqmlcodegenerator_p.h
@@ -135,6 +135,8 @@ struct Binding : public QV4::CompiledData::Binding
struct Function
{
+ AST::FunctionDeclaration *functionDeclaration;
+ QV4::CompiledData::Location location;
int index; // index in parsedQML::functions
Function *next;
};
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index e6bf36bbf1..69ccd4c0ce 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -77,6 +77,14 @@ QQmlCompilePass::QQmlCompilePass(const QUrl &url, const QV4::CompiledData::QmlUn
{
}
+QQmlCompilePass::QQmlCompilePass(const QUrl &url, const QStringList &stringTable)
+ : url(url)
+ , qmlUnit(0)
+ , stringTable(stringTable)
+{
+
+}
+
void QQmlCompilePass::recordError(const QV4::CompiledData::Location &location, const QString &description)
{
QQmlError error;
@@ -95,32 +103,32 @@ void QQmlCompilePass::recordError(const QV4::CompiledData::Location &location, c
static QAtomicInt classIndexCounter(0);
-QQmlPropertyCacheCreator::QQmlPropertyCacheCreator(QQmlEnginePrivate *enginePrivate, const QV4::CompiledData::QmlUnit *unit, const QUrl &url, const QQmlImports *imports,
+QQmlPropertyCacheCreator::QQmlPropertyCacheCreator(QQmlEnginePrivate *enginePrivate, const QStringList &stringTable, const QUrl &url, const QQmlImports *imports,
QHash<int, QQmlCompiledData::TypeReference> *resolvedTypes)
- : QQmlCompilePass(url, unit)
+ : QQmlCompilePass(url, stringTable)
, enginePrivate(enginePrivate)
, imports(imports)
, resolvedTypes(resolvedTypes)
{
}
-bool QQmlPropertyCacheCreator::create(const QV4::CompiledData::Object *obj, QQmlPropertyCache **resultCache, QByteArray *vmeMetaObjectData)
+bool QQmlPropertyCacheCreator::create(const QtQml::QmlObject *obj, QQmlPropertyCache **resultCache, QByteArray *vmeMetaObjectData)
{
Q_ASSERT(!stringAt(obj->inheritedTypeNameIndex).isEmpty());
QQmlCompiledData::TypeReference typeRef = resolvedTypes->value(obj->inheritedTypeNameIndex);
QQmlPropertyCache *baseTypeCache = typeRef.createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
Q_ASSERT(baseTypeCache);
- if (obj->nProperties == 0 && obj->nSignals == 0 && obj->nFunctions == 0) {
+ if (obj->properties->count == 0 && obj->qmlSignals->count == 0 && obj->functions->count == 0) {
*resultCache = baseTypeCache;
vmeMetaObjectData->clear();
return true;
}
QQmlPropertyCache *cache = baseTypeCache->copyAndReserve(QQmlEnginePrivate::get(enginePrivate),
- obj->nProperties,
- obj->nFunctions + obj->nProperties + obj->nSignals,
- obj->nSignals + obj->nProperties);
+ obj->properties->count,
+ obj->functions->count + obj->properties->count + obj->qmlSignals->count,
+ obj->qmlSignals->count + obj->properties->count);
*resultCache = cache;
vmeMetaObjectData->clear();
@@ -177,9 +185,7 @@ bool QQmlPropertyCacheCreator::create(const QV4::CompiledData::Object *obj, QQml
int aliasCount = 0;
int varPropCount = 0;
- const QV4::CompiledData::Property *p = obj->propertyTable();
- for (quint32 i = 0; i < obj->nProperties; ++i, ++p) {
-
+ for (QtQml::QmlProperty *p = obj->properties->first; p; p = p->next) {
if (p->type == QV4::CompiledData::Property::Alias)
aliasCount++;
else if (p->type == QV4::CompiledData::Property::Var)
@@ -196,8 +202,8 @@ bool QQmlPropertyCacheCreator::create(const QV4::CompiledData::Object *obj, QQml
typedef QQmlVMEMetaData VMD;
QByteArray &dynamicData = *vmeMetaObjectData = QByteArray(sizeof(QQmlVMEMetaData)
- + obj->nProperties * sizeof(VMD::PropertyData)
- + obj->nFunctions * sizeof(VMD::MethodData)
+ + obj->properties->count * sizeof(VMD::PropertyData)
+ + obj->functions->count * sizeof(VMD::MethodData)
+ aliasCount * sizeof(VMD::AliasData), 0);
int effectivePropertyIndex = cache->propertyIndexCacheStart;
@@ -233,8 +239,7 @@ bool QQmlPropertyCacheCreator::create(const QV4::CompiledData::Object *obj, QQml
if (ii == NSS_Var && varPropCount == 0) continue;
else if (ii == NSS_Alias && aliasCount == 0) continue;
- const QV4::CompiledData::Property *p = obj->propertyTable();
- for (quint32 i = 0; i < obj->nProperties; ++i, ++p) {
+ for (QtQml::QmlProperty *p = obj->properties->first; p; p = p->next) {
if ((ii == NSS_Normal && (p->type == QV4::CompiledData::Property::Alias ||
p->type == QV4::CompiledData::Property::Var)) ||
((ii == NSS_Var) && (p->type != QV4::CompiledData::Property::Var)) ||
@@ -252,9 +257,8 @@ bool QQmlPropertyCacheCreator::create(const QV4::CompiledData::Object *obj, QQml
}
// Dynamic signals
- for (uint i = 0; i < obj->nSignals; ++i) {
- const QV4::CompiledData::Signal *s = obj->signalAt(i);
- const int paramCount = s->nParameters;
+ for (QtQml::Signal *s = obj->qmlSignals->first; s; s = s->next) {
+ const int paramCount = s->parameters->count;
QList<QByteArray> names;
QVarLengthArray<int, 10> paramTypes(paramCount?(paramCount + 1):0);
@@ -262,8 +266,8 @@ bool QQmlPropertyCacheCreator::create(const QV4::CompiledData::Object *obj, QQml
if (paramCount) {
paramTypes[0] = paramCount;
- for (int i = 0; i < paramCount; ++i) {
- const QV4::CompiledData::Parameter *param = s->parameterAt(i);
+ QtQml::SignalParameter *param = s->parameters->first;
+ for (int i = 0; i < paramCount; ++i, param = param->next) {
names.append(stringAt(param->nameIndex).toUtf8());
if (param->type < builtinTypeCount) {
// built-in type
@@ -311,27 +315,26 @@ bool QQmlPropertyCacheCreator::create(const QV4::CompiledData::Object *obj, QQml
// Dynamic slots
- const quint32 *functionIndex = obj->functionOffsetTable();
- for (quint32 i = 0; i < obj->nFunctions; ++i, ++functionIndex) {
- const QV4::CompiledData::Function *s = qmlUnit->header.functionAt(*functionIndex);
- int paramCount = s->nFormals;
+ for (QtQml::Function *s = obj->functions->first; s; s = s->next) {
+ AST::FunctionDeclaration *astFunction = s->functionDeclaration;
quint32 flags = QQmlPropertyData::IsFunction | QQmlPropertyData::IsVMEFunction;
- if (paramCount)
+ if (astFunction->formals)
flags |= QQmlPropertyData::HasArguments;
- QString slotName = stringAt(s->nameIndex);
+ QString slotName = astFunction->name.toString();
if (seenSignals.contains(slotName))
COMPILE_EXCEPTION(s, tr("Duplicate method name: invalid override of property change signal or superclass signal"));
// Note: we don't append slotName to the seenSignals list, since we don't
// protect against overriding change signals or methods with properties.
- const quint32 *formalsIndices = s->formalsTable();
QList<QByteArray> parameterNames;
- parameterNames.reserve(paramCount);
- for (int i = 0; i < paramCount; ++i)
- parameterNames << stringAt(formalsIndices[i]).toUtf8();
+ AST::FormalParameterList *param = astFunction->formals;
+ while (param) {
+ parameterNames << param->name.toUtf8();
+ param = param->next;
+ }
cache->appendMethod(slotName, flags, effectiveMethodIndex++, parameterNames);
}
@@ -339,8 +342,8 @@ bool QQmlPropertyCacheCreator::create(const QV4::CompiledData::Object *obj, QQml
// Dynamic properties (except var and aliases)
int effectiveSignalIndex = cache->signalHandlerIndexCacheStart;
- /* const QV4::CompiledData::Property* */ p = obj->propertyTable();
- for (quint32 i = 0; i < obj->nProperties; ++i, ++p) {
+ int propertyIdx = 0;
+ for (QtQml::QmlProperty *p = obj->properties->first; p; p = p->next, ++propertyIdx) {
if (p->type == QV4::CompiledData::Property::Alias ||
p->type == QV4::CompiledData::Property::Var)
@@ -403,7 +406,7 @@ bool QQmlPropertyCacheCreator::create(const QV4::CompiledData::Object *obj, QQml
QString propertyName = stringAt(p->nameIndex);
- if (i == obj->indexOfDefaultProperty) cache->_defaultPropertyName = propertyName;
+ if (propertyIdx == obj->indexOfDefaultProperty) cache->_defaultPropertyName = propertyName;
cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
propertyType, effectiveSignalIndex);
@@ -415,8 +418,8 @@ bool QQmlPropertyCacheCreator::create(const QV4::CompiledData::Object *obj, QQml
}
// Now do var properties
- /* const QV4::CompiledData::Property* */ p = obj->propertyTable();
- for (quint32 i = 0; i < obj->nProperties; ++i, ++p) {
+ propertyIdx = 0;
+ for (QtQml::QmlProperty *p = obj->properties->first; p; p = p->next, ++propertyIdx) {
if (p->type != QV4::CompiledData::Property::Var)
continue;
@@ -431,7 +434,7 @@ bool QQmlPropertyCacheCreator::create(const QV4::CompiledData::Object *obj, QQml
((QQmlVMEMetaData *)dynamicData.data())->varPropertyCount++;
QString propertyName = stringAt(p->nameIndex);
- if (i == obj->indexOfDefaultProperty) cache->_defaultPropertyName = propertyName;
+ if (propertyIdx == obj->indexOfDefaultProperty) cache->_defaultPropertyName = propertyName;
cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
QMetaType::QVariant, effectiveSignalIndex);
@@ -442,12 +445,17 @@ bool QQmlPropertyCacheCreator::create(const QV4::CompiledData::Object *obj, QQml
((QQmlVMEMetaData *)dynamicData.data())->aliasCount = aliasCount;
// Dynamic slot data - comes after the property data
- /*const quint32* */functionIndex = obj->functionOffsetTable();
- for (quint32 i = 0; i < obj->nFunctions; ++i, ++functionIndex) {
- const QV4::CompiledData::Function *s = qmlUnit->header.functionAt(*functionIndex);
+ for (QtQml::Function *s = obj->functions->first; s; s = s->next) {
+ AST::FunctionDeclaration *astFunction = s->functionDeclaration;
+ int formalsCount = 0;
+ AST::FormalParameterList *param = astFunction->formals;
+ while (param) {
+ formalsCount++;
+ param = param->next;
+ }
VMD::MethodData methodData = { /* runtimeFunctionIndex*/ 0, // ###
- int(s->nFormals),
+ formalsCount,
/* s->location.start.line */0 }; // ###
VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index e33e47edcc..d395f0238f 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -54,25 +54,27 @@ class QQmlAbstractBinding;
struct QQmlCompilePass
{
QQmlCompilePass(const QUrl &url, const QV4::CompiledData::QmlUnit *unit);
+ QQmlCompilePass(const QUrl &url, const QStringList &stringTable);
QList<QQmlError> errors;
+ QString stringAt(int idx) const { return qmlUnit ? qmlUnit->header.stringAt(idx): stringTable.at(idx); }
protected:
- QString stringAt(int idx) const { return qmlUnit->header.stringAt(idx); }
void recordError(const QV4::CompiledData::Location &location, const QString &description);
const QUrl url;
const QV4::CompiledData::QmlUnit *qmlUnit;
+ const QStringList stringTable;
};
class QQmlPropertyCacheCreator : public QQmlCompilePass
{
Q_DECLARE_TR_FUNCTIONS(QQmlPropertyCacheCreator)
public:
- QQmlPropertyCacheCreator(QQmlEnginePrivate *enginePrivate, const QV4::CompiledData::QmlUnit *qmlUnit,
+ QQmlPropertyCacheCreator(QQmlEnginePrivate *enginePrivate, const QStringList &stringTable,
const QUrl &url, const QQmlImports *imports,
QHash<int, QQmlCompiledData::TypeReference> *resolvedTypes);
- bool create(const QV4::CompiledData::Object *obj, QQmlPropertyCache **cache, QByteArray *vmeMetaObjectData);
+ bool create(const QtQml::QmlObject *obj, QQmlPropertyCache **cache, QByteArray *vmeMetaObjectData);
protected:
QQmlEnginePrivate *enginePrivate;
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 1a4c8f015d..5b6d91475b 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2338,6 +2338,46 @@ void QQmlTypeData::compile()
m_compiledData->resolvedTypes.insert(resolvedType.key(), ref);
}
+ // Build property caches and VME meta object data
+
+ const int objectCount = parsedQML->objects.count();
+ m_compiledData->datas.reserve(objectCount);
+ m_compiledData->propertyCaches.reserve(objectCount);
+
+ QQmlPropertyCacheCreator propertyCacheBuilder(enginePrivate,
+ parsedQML->jsGenerator.strings, m_compiledData->url,
+ &m_imports, &m_compiledData->resolvedTypes);
+
+ for (int i = 0; i < objectCount; ++i) {
+ const QtQml::QmlObject *obj = parsedQML->objects.at(i);
+
+ QByteArray vmeMetaObjectData;
+ QQmlPropertyCache *propertyCache = 0;
+
+ // If the object has no type, then it's probably a nested object definition as part
+ // of a group property.
+ const bool objectHasType = !propertyCacheBuilder.stringAt(obj->inheritedTypeNameIndex).isEmpty();
+ if (objectHasType) {
+ if (!propertyCacheBuilder.create(obj, &propertyCache, &vmeMetaObjectData)) {
+ setError(propertyCacheBuilder.errors);
+ m_compiledData->release();
+ m_compiledData = 0;
+ return;
+ }
+ }
+
+ m_compiledData->datas << vmeMetaObjectData;
+ if (propertyCache)
+ propertyCache->addref();
+ m_compiledData->propertyCaches << propertyCache;
+
+ if (i == parsedQML->indexOfRootObject) {
+ Q_ASSERT(propertyCache);
+ m_compiledData->rootPropertyCache = propertyCache;
+ propertyCache->addref();
+ }
+ }
+
{
SignalHandlerConverter converter(QQmlEnginePrivate::get(engine),
parsedQML.data(),
@@ -2399,46 +2439,9 @@ void QQmlTypeData::compile()
QList<QQmlError> errors;
- // Build property caches and VME meta object data
-
- m_compiledData->datas.reserve(qmlUnit->nObjects);
- m_compiledData->propertyCaches.reserve(qmlUnit->nObjects);
-
- QQmlPropertyCacheCreator propertyCacheBuilder(enginePrivate,
- qmlUnit, m_compiledData->url,
- &m_imports, &m_compiledData->resolvedTypes);
-
- for (quint32 i = 0; i < qmlUnit->nObjects; ++i) {
- const QV4::CompiledData::Object *obj = qmlUnit->objectAt(i);
-
- QByteArray vmeMetaObjectData;
- QQmlPropertyCache *propertyCache = 0;
-
- // If the object has no type, then it's probably a nested object definition as part
- // of a group property.
- const bool objectHasType = !parsedQML->jsGenerator.strings.at(obj->inheritedTypeNameIndex).isEmpty();
- if (objectHasType) {
- if (!propertyCacheBuilder.create(obj, &propertyCache, &vmeMetaObjectData)) {
- errors << propertyCacheBuilder.errors;
- break;
- }
- }
-
- m_compiledData->datas << vmeMetaObjectData;
- if (propertyCache)
- propertyCache->addref();
- m_compiledData->propertyCaches << propertyCache;
-
- if (i == qmlUnit->indexOfRootObject) {
- Q_ASSERT(propertyCache);
- m_compiledData->rootPropertyCache = propertyCache;
- propertyCache->addref();
- }
- }
-
// Resolve component boundaries and aliases
- if (errors.isEmpty()) {
+ {
// Scan for components, determine their scopes and resolve aliases within the scope.
QQmlComponentAndAliasResolver resolver(m_compiledData->url, m_compiledData->qmlUnit, m_compiledData->resolvedTypes, m_compiledData->propertyCaches,
&m_compiledData->datas, &m_compiledData->objectIndexToIdForRoot, &m_compiledData->objectIndexToIdPerComponent);