aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp292
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h14
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp130
-rw-r--r--src/qml/compiler/qv4compileddata_p.h32
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp2
5 files changed, 282 insertions, 188 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index bd4261493c..ac59c04e87 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -80,8 +80,10 @@ void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int id, const QQm
location.column = loc.startColumn;
idIndex = id;
- indexOfDefaultProperty = -1;
+ indexOfDefaultPropertyOrAlias = -1;
+ defaultPropertyIsAlias = false;
properties = pool->New<PoolList<Property> >();
+ aliases = pool->New<PoolList<Alias> >();
qmlSignals = pool->New<PoolList<Signal> >();
bindings = pool->New<PoolList<Binding> >();
functions = pool->New<PoolList<Function> >();
@@ -145,15 +147,42 @@ QString Object::appendProperty(Property *prop, const QString &propertyName, bool
const int index = target->properties->append(prop);
if (isDefaultProperty) {
- if (target->indexOfDefaultProperty != -1) {
+ if (target->indexOfDefaultPropertyOrAlias != -1) {
*errorLocation = defaultToken;
return tr("Duplicate default property");
}
- target->indexOfDefaultProperty = index;
+ target->indexOfDefaultPropertyOrAlias = index;
}
return QString(); // no error
}
+QString Object::appendAlias(Alias *alias, const QString &aliasName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation)
+{
+ Object *target = declarationsOverride;
+ if (!target)
+ target = this;
+
+ for (Alias *p = target->aliases->first; p; p = p->next)
+ if (p->nameIndex == alias->nameIndex)
+ return tr("Duplicate alias name");
+
+ if (aliasName.constData()->isUpper())
+ return tr("Alias names cannot begin with an upper case letter");
+
+ const int index = target->aliases->append(alias);
+
+ if (isDefaultProperty) {
+ if (target->indexOfDefaultPropertyOrAlias != -1) {
+ *errorLocation = defaultToken;
+ return tr("Duplicate default property");
+ }
+ target->indexOfDefaultPropertyOrAlias = index;
+ target->defaultPropertyIsAlias = true;
+ }
+
+ return QString(); // no error
+}
+
void Object::appendFunction(QmlIR::Function *f)
{
Object *target = declarationsOverride;
@@ -806,128 +835,86 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
}
} else {
const QStringRef &memberType = node->memberType;
- const QStringRef &name = node->name;
-
- bool typeFound = false;
- QV4::CompiledData::Property::Type type;
-
if (memberType == QLatin1String("alias")) {
- type = QV4::CompiledData::Property::Alias;
- typeFound = true;
- }
+ return appendAlias(node);
+ } else {
+ const QStringRef &name = node->name;
- for (int ii = 0; !typeFound && ii < propTypeNameToTypesCount; ++ii) {
- const TypeNameToType *t = propTypeNameToTypes + ii;
- if (memberType == QLatin1String(t->name, static_cast<int>(t->nameLength))) {
- type = t->type;
- typeFound = true;
+ bool typeFound = false;
+ QV4::CompiledData::Property::Type type;
+
+ for (int ii = 0; !typeFound && ii < propTypeNameToTypesCount; ++ii) {
+ const TypeNameToType *t = propTypeNameToTypes + ii;
+ if (memberType == QLatin1String(t->name, static_cast<int>(t->nameLength))) {
+ type = t->type;
+ typeFound = true;
+ }
}
- }
- if (!typeFound && memberType.at(0).isUpper()) {
- const QStringRef &typeModifier = node->typeModifier;
+ if (!typeFound && memberType.at(0).isUpper()) {
+ const QStringRef &typeModifier = node->typeModifier;
- if (typeModifier.isEmpty()) {
- type = QV4::CompiledData::Property::Custom;
- } else if (typeModifier == QLatin1String("list")) {
- type = QV4::CompiledData::Property::CustomList;
- } else {
- recordError(node->typeModifierToken, QCoreApplication::translate("QQmlParser","Invalid property type modifier"));
+ if (typeModifier.isEmpty()) {
+ type = QV4::CompiledData::Property::Custom;
+ } else if (typeModifier == QLatin1String("list")) {
+ type = QV4::CompiledData::Property::CustomList;
+ } else {
+ recordError(node->typeModifierToken, QCoreApplication::translate("QQmlParser","Invalid property type modifier"));
+ return false;
+ }
+ typeFound = true;
+ } else if (!node->typeModifier.isNull()) {
+ recordError(node->typeModifierToken, QCoreApplication::translate("QQmlParser","Unexpected property type modifier"));
return false;
}
- typeFound = true;
- } else if (!node->typeModifier.isNull()) {
- recordError(node->typeModifierToken, QCoreApplication::translate("QQmlParser","Unexpected property type modifier"));
- return false;
- }
-
- if (!typeFound) {
- recordError(node->typeToken, QCoreApplication::translate("QQmlParser","Expected property type"));
- return false;
- }
-
- Property *property = New<Property>();
- property->flags = 0;
- if (node->isReadonlyMember)
- property->flags |= QV4::CompiledData::Property::IsReadOnly;
- property->type = type;
- if (type >= QV4::CompiledData::Property::Custom)
- property->customTypeNameIndex = registerString(memberType.toString());
- else
- property->customTypeNameIndex = emptyStringIndex;
- const QString propName = name.toString();
- property->nameIndex = registerString(propName);
-
- QQmlJS::AST::SourceLocation loc = node->firstSourceLocation();
- property->location.line = loc.startLine;
- property->location.column = loc.startColumn;
-
- property->aliasPropertyValueIndex = emptyStringIndex;
-
- if (type == QV4::CompiledData::Property::Alias) {
- if (!node->statement && !node->binding)
- COMPILE_EXCEPTION(loc, tr("No property alias location"));
+ if (!typeFound) {
+ recordError(node->typeToken, QCoreApplication::translate("QQmlParser","Expected property type"));
+ return false;
+ }
- QQmlJS::AST::SourceLocation rhsLoc;
- if (node->binding)
- rhsLoc = node->binding->firstSourceLocation();
- else if (node->statement)
- rhsLoc = node->statement->firstSourceLocation();
+ Property *property = New<Property>();
+ property->flags = 0;
+ if (node->isReadonlyMember)
+ property->flags |= QV4::CompiledData::Property::IsReadOnly;
+ property->type = type;
+ if (type >= QV4::CompiledData::Property::Custom)
+ property->customTypeNameIndex = registerString(memberType.toString());
else
- rhsLoc = node->semicolonToken;
- property->aliasLocation.line = rhsLoc.startLine;
- property->aliasLocation.column = rhsLoc.startColumn;
-
- QStringList alias;
-
- if (QQmlJS::AST::ExpressionStatement *stmt = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement*>(node->statement)) {
- alias = astNodeToStringList(stmt->expression);
- if (alias.isEmpty()) {
- if (isStatementNodeScript(node->statement)) {
- COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
- } else {
- COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias location"));
- }
- }
- } else {
- COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
- }
+ property->customTypeNameIndex = emptyStringIndex;
- if (alias.count() < 1 || alias.count() > 3)
- COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
+ const QString propName = name.toString();
+ property->nameIndex = registerString(propName);
- property->aliasIdValueIndex = registerString(alias.first());
+ QQmlJS::AST::SourceLocation loc = node->firstSourceLocation();
+ property->location.line = loc.startLine;
+ property->location.column = loc.startColumn;
- QString propertyValue = alias.value(1);
- if (alias.count() == 3)
- propertyValue += QLatin1Char('.') + alias.at(2);
- property->aliasPropertyValueIndex = registerString(propertyValue);
- }
- QQmlJS::AST::SourceLocation errorLocation;
- QString error;
+ QQmlJS::AST::SourceLocation errorLocation;
+ QString error;
- if (illegalNames.contains(propName))
- error = tr("Illegal property name");
- else
- error = _object->appendProperty(property, propName, node->isDefaultMember, node->defaultToken, &errorLocation);
+ if (illegalNames.contains(propName))
+ error = tr("Illegal property name");
+ else
+ error = _object->appendProperty(property, propName, node->isDefaultMember, node->defaultToken, &errorLocation);
- if (!error.isEmpty()) {
- if (errorLocation.startLine == 0)
- errorLocation = node->identifierToken;
+ if (!error.isEmpty()) {
+ if (errorLocation.startLine == 0)
+ errorLocation = node->identifierToken;
- recordError(errorLocation, error);
- return false;
- }
+ recordError(errorLocation, error);
+ return false;
+ }
- qSwap(_propertyDeclaration, property);
- if (node->binding) {
- // process QML-like initializers (e.g. property Object o: Object {})
- QQmlJS::AST::Node::accept(node->binding, this);
- } else if (node->statement && type != QV4::CompiledData::Property::Alias) {
- appendBinding(node->identifierToken, node->identifierToken, _propertyDeclaration->nameIndex, node->statement);
+ qSwap(_propertyDeclaration, property);
+ if (node->binding) {
+ // process QML-like initializers (e.g. property Object o: Object {})
+ QQmlJS::AST::Node::accept(node->binding, this);
+ } else if (node->statement) {
+ appendBinding(node->identifierToken, node->identifierToken, _propertyDeclaration->nameIndex, node->statement);
+ }
+ qSwap(_propertyDeclaration, property);
}
- qSwap(_propertyDeclaration, property);
}
return false;
@@ -1132,6 +1119,79 @@ void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLo
}
}
+bool IRBuilder::appendAlias(QQmlJS::AST::UiPublicMember *node)
+{
+ Alias *alias = New<Alias>();
+ alias->flags = 0;
+ if (node->isReadonlyMember)
+ alias->flags |= QV4::CompiledData::Alias::IsReadOnly;
+
+ const QString propName = node->name.toString();
+ alias->nameIndex = registerString(propName);
+
+ QQmlJS::AST::SourceLocation loc = node->firstSourceLocation();
+ alias->location.line = loc.startLine;
+ alias->location.column = loc.startColumn;
+
+ alias->propertyIndex = emptyStringIndex;
+
+ if (!node->statement && !node->binding)
+ COMPILE_EXCEPTION(loc, tr("No property alias location"));
+
+ QQmlJS::AST::SourceLocation rhsLoc;
+ if (node->binding)
+ rhsLoc = node->binding->firstSourceLocation();
+ else if (node->statement)
+ rhsLoc = node->statement->firstSourceLocation();
+ else
+ rhsLoc = node->semicolonToken;
+ alias->referenceLocation.line = rhsLoc.startLine;
+ alias->referenceLocation.column = rhsLoc.startColumn;
+
+ QStringList aliasReference;
+
+ if (QQmlJS::AST::ExpressionStatement *stmt = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement*>(node->statement)) {
+ aliasReference = astNodeToStringList(stmt->expression);
+ if (aliasReference.isEmpty()) {
+ if (isStatementNodeScript(node->statement)) {
+ COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
+ } else {
+ COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias location"));
+ }
+ }
+ } else {
+ COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
+ }
+
+ if (aliasReference.count() < 1 || aliasReference.count() > 3)
+ COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
+
+ alias->idIndex = registerString(aliasReference.first());
+
+ QString propertyValue = aliasReference.value(1);
+ if (aliasReference.count() == 3)
+ propertyValue += QLatin1Char('.') + aliasReference.at(2);
+ alias->propertyIndex = registerString(propertyValue);
+
+ QQmlJS::AST::SourceLocation errorLocation;
+ QString error;
+
+ if (illegalNames.contains(propName))
+ error = tr("Illegal property name");
+ else
+ error = _object->appendAlias(alias, propName, node->isDefaultMember, node->defaultToken, &errorLocation);
+
+ if (!error.isEmpty()) {
+ if (errorLocation.startLine == 0)
+ errorLocation = node->identifierToken;
+
+ recordError(errorLocation, error);
+ return false;
+ }
+
+ return false;
+}
+
Object *IRBuilder::bindingsTarget() const
{
if (_propertyDeclaration && _object->declarationsOverride)
@@ -1313,7 +1373,7 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
int objectsSize = 0;
foreach (Object *o, output.objects) {
objectOffsets.insert(o, unitSize + importSize + objectOffsetTableSize + objectsSize);
- objectsSize += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->signalCount(), o->bindingCount());
+ objectsSize += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->aliasCount(), o->signalCount(), o->bindingCount());
int signalTableSize = 0;
for (const Signal *s = o->firstSignal(); s; s = s->next)
@@ -1358,7 +1418,8 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
QV4::CompiledData::Object *objectToWrite = reinterpret_cast<QV4::CompiledData::Object*>(objectPtr);
objectToWrite->inheritedTypeNameIndex = o->inheritedTypeNameIndex;
- objectToWrite->indexOfDefaultProperty = o->indexOfDefaultProperty;
+ objectToWrite->indexOfDefaultPropertyOrAlias = o->indexOfDefaultPropertyOrAlias;
+ objectToWrite->defaultPropertyIsAlias = o->defaultPropertyIsAlias;
objectToWrite->idIndex = o->idIndex;
objectToWrite->location = o->location;
objectToWrite->locationOfIdProperty = o->locationOfIdProperty;
@@ -1373,6 +1434,10 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
objectToWrite->offsetToProperties = nextOffset;
nextOffset += objectToWrite->nProperties * sizeof(QV4::CompiledData::Property);
+ objectToWrite->nAliases = o->aliasCount();
+ objectToWrite->offsetToAliases = nextOffset;
+ nextOffset += objectToWrite->nAliases * sizeof(QV4::CompiledData::Alias);
+
objectToWrite->nSignals = o->signalCount();
objectToWrite->offsetToSignals = nextOffset;
nextOffset += objectToWrite->nSignals * sizeof(quint32);
@@ -1392,6 +1457,13 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
propertiesPtr += sizeof(QV4::CompiledData::Property);
}
+ char *aliasesPtr = objectPtr + objectToWrite->offsetToAliases;
+ for (const Alias *a = o->firstAlias(); a; a = a->next) {
+ QV4::CompiledData::Alias *aliasToWrite = reinterpret_cast<QV4::CompiledData::Alias*>(aliasesPtr);
+ *aliasToWrite = *a;
+ aliasesPtr += sizeof(QV4::CompiledData::Alias);
+ }
+
char *bindingPtr = objectPtr + objectToWrite->offsetToBindings;
bindingPtr = writeBindings(bindingPtr, o, &QV4::CompiledData::Binding::isValueBindingNoAlias);
bindingPtr = writeBindings(bindingPtr, o, &QV4::CompiledData::Binding::isSignalHandler);
@@ -1420,7 +1492,7 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
signalPtr += size;
}
- objectPtr += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->signalCount(), o->bindingCount());
+ objectPtr += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->aliasCount(), o->signalCount(), o->bindingCount());
objectPtr += signalTableSize;
}
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 18daab9ce4..060c888cd8 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -235,6 +235,11 @@ struct Binding : public QV4::CompiledData::Binding
Binding *next;
};
+struct Alias : public QV4::CompiledData::Alias
+{
+ Alias *next;
+};
+
struct Function
{
QQmlJS::AST::FunctionDeclaration *functionDeclaration;
@@ -270,13 +275,16 @@ struct Q_QML_PRIVATE_EXPORT Object
public:
quint32 inheritedTypeNameIndex;
quint32 idIndex;
- int indexOfDefaultProperty;
+ int indexOfDefaultPropertyOrAlias : 31;
+ int defaultPropertyIsAlias : 1;
QV4::CompiledData::Location location;
QV4::CompiledData::Location locationOfIdProperty;
const Property *firstProperty() const { return properties->first; }
int propertyCount() const { return properties->count; }
+ const Alias *firstAlias() const { return aliases->first; }
+ int aliasCount() const { return aliases->count; }
const Signal *firstSignal() const { return qmlSignals->first; }
int signalCount() const { return qmlSignals->count; }
Binding *firstBinding() const { return bindings->first; }
@@ -294,6 +302,7 @@ public:
QString appendSignal(Signal *signal);
QString appendProperty(Property *prop, const QString &propertyName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation);
+ QString appendAlias(Alias *prop, const QString &aliasName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation);
void appendFunction(QmlIR::Function *f);
QString appendBinding(Binding *b, bool isListBinding);
@@ -309,6 +318,7 @@ private:
friend struct IRLoader;
PoolList<Property> *properties;
+ PoolList<Alias> *aliases;
PoolList<Signal> *qmlSignals;
PoolList<Binding> *bindings;
PoolList<Function> *functions;
@@ -414,6 +424,8 @@ public:
void appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, QQmlJS::AST::Statement *value);
void appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, int objectIndex, bool isListItem = false, bool isOnAssignment = false);
+ bool appendAlias(QQmlJS::AST::UiPublicMember *node);
+
Object *bindingsTarget() const;
bool setId(const QQmlJS::AST::SourceLocation &idLocation, QQmlJS::AST::Statement *value);
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index fcb94a9645..fed0ec1f37 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -480,7 +480,7 @@ bool QQmlPropertyCacheCreator::buildMetaObjectRecursively(int objectIndex, int r
}
}
- bool needVMEMetaObject = obj->propertyCount() != 0 || obj->signalCount() != 0 || obj->functionCount() != 0;
+ bool needVMEMetaObject = obj->propertyCount() != 0 || obj->aliasCount() != 0 || obj->signalCount() != 0 || obj->functionCount() != 0;
if (!needVMEMetaObject) {
for (const QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
if (binding->type == QV4::CompiledData::Binding::Type_Object && (binding->flags & QV4::CompiledData::Binding::IsOnAssignment)) {
@@ -507,7 +507,7 @@ bool QQmlPropertyCacheCreator::buildMetaObjectRecursively(int objectIndex, int r
Q_ASSERT(typeRef);
if (typeRef->isFullyDynamicType) {
- if (obj->propertyCount() > 0) {
+ if (obj->propertyCount() > 0 || obj->aliasCount() > 0) {
recordError(obj->location, tr("Fully dynamic types cannot declare new properties."));
return false;
}
@@ -586,9 +586,9 @@ bool QQmlPropertyCacheCreator::ensureMetaObject(int objectIndex)
bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Object *obj, QQmlPropertyCache *baseTypeCache)
{
- QQmlPropertyCache *cache = baseTypeCache->copyAndReserve(obj->propertyCount(),
- obj->functionCount() + obj->propertyCount() + obj->signalCount(),
- obj->signalCount() + obj->propertyCount());
+ QQmlPropertyCache *cache = baseTypeCache->copyAndReserve(obj->propertyCount() + obj->aliasCount(),
+ obj->functionCount() + obj->propertyCount() + obj->aliasCount() + obj->signalCount(),
+ obj->signalCount() + obj->propertyCount() + obj->aliasCount());
propertyCaches[objectIndex] = cache;
struct TypeData {
@@ -638,29 +638,40 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
cache->_dynamicClassName = newClassName;
- int aliasCount = 0;
int varPropCount = 0;
QmlIR::PropertyResolver resolver(baseTypeCache);
for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next) {
- if (p->type == QV4::CompiledData::Property::Alias)
- aliasCount++;
- else if (p->type == QV4::CompiledData::Property::Var)
+ if (p->type == QV4::CompiledData::Property::Var)
varPropCount++;
- // No point doing this for both the alias and non alias cases
bool notInRevision = false;
QQmlPropertyData *d = resolver.property(stringAt(p->nameIndex), &notInRevision);
if (d && d->isFinal())
COMPILE_EXCEPTION(p, tr("Cannot override FINAL property"));
}
+ for (const QmlIR::Alias *a = obj->firstAlias(); a; a = a->next) {
+ bool notInRevision = false;
+ QQmlPropertyData *d = resolver.property(stringAt(a->nameIndex), &notInRevision);
+ if (d && d->isFinal())
+ COMPILE_EXCEPTION(a, tr("Cannot override FINAL property"));
+ }
+
typedef QQmlVMEMetaData VMD;
QByteArray &dynamicData = vmeMetaObjects[objectIndex] = QByteArray(sizeof(QQmlVMEMetaData)
+ obj->propertyCount() * sizeof(VMD::PropertyData)
- + aliasCount * sizeof(VMD::AliasData), 0);
+ + obj->aliasCount() * sizeof(VMD::AliasData), 0);
+
+ VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
+ // Dynamic slot data - comes after the property data
+ vmd->methodCount = obj->functionCount();
+ // Alias property count. Actual data is setup in resolveAliases()
+ vmd->aliasCount = obj->aliasCount();
+ vmd->signalCount = obj->signalCount();
+ vmd->propertyCount = obj->propertyCount();
int effectivePropertyIndex = cache->propertyIndexCacheStart;
int effectiveMethodIndex = cache->methodIndexCacheStart;
@@ -688,25 +699,25 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
}
}
- // First set up notify signals for properties - first normal, then var, then alias
- enum { NSS_Normal = 0, NSS_Alias = 1 };
- for (int ii = NSS_Normal; ii <= NSS_Alias; ++ii) { // 0 == normal, 1 == var, 2 == alias
+ // Set up notify signals for properties - first normal, then alias
+ for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next) {
+ quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
+ QQmlPropertyData::IsVMESignal;
- if (ii == NSS_Alias && aliasCount == 0) continue;
+ QString changedSigName = stringAt(p->nameIndex) + QLatin1String("Changed");
+ seenSignals.insert(changedSigName);
- for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next) {
- if ((ii == NSS_Normal && p->type == QV4::CompiledData::Property::Alias) ||
- (ii == NSS_Alias && p->type != QV4::CompiledData::Property::Alias))
- continue;
+ cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
+ }
- quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
- QQmlPropertyData::IsVMESignal;
+ for (const QmlIR::Alias *a = obj->firstAlias(); a; a = a->next) {
+ quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
+ QQmlPropertyData::IsVMESignal;
- QString changedSigName = stringAt(p->nameIndex) + QLatin1String("Changed");
- seenSignals.insert(changedSigName);
+ QString changedSigName = stringAt(a->nameIndex) + QLatin1String("Changed");
+ seenSignals.insert(changedSigName);
- cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
- }
+ cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
}
// Dynamic signals
@@ -751,8 +762,6 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
}
}
- ((QQmlVMEMetaData *)dynamicData.data())->signalCount++;
-
quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
QQmlPropertyData::IsVMESignal;
if (paramCount)
@@ -794,14 +803,10 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
}
- // Dynamic properties (except var and aliases)
+ // Dynamic properties
int effectiveSignalIndex = cache->signalHandlerIndexCacheStart;
int propertyIdx = 0;
for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next, ++propertyIdx) {
-
- if (p->type == QV4::CompiledData::Property::Alias)
- continue;
-
int propertyType = 0;
int vmePropertyType = 0;
quint32 propertyFlags = 0;
@@ -863,24 +868,17 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
QString propertyName = stringAt(p->nameIndex);
- if (propertyIdx == obj->indexOfDefaultProperty) cache->_defaultPropertyName = propertyName;
+ if (!obj->defaultPropertyIsAlias && propertyIdx == obj->indexOfDefaultPropertyOrAlias)
+ cache->_defaultPropertyName = propertyName;
cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
propertyType, effectiveSignalIndex);
effectiveSignalIndex++;
VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
- (vmd->propertyData() + vmd->propertyCount)->propertyType = vmePropertyType;
- vmd->propertyCount++;
+ (vmd->propertyData() + propertyIdx)->propertyType = vmePropertyType;
}
- // Alias property count. Actual data is setup in buildDynamicMetaAliases
- ((QQmlVMEMetaData *)dynamicData.data())->aliasCount = aliasCount;
-
- // Dynamic slot data - comes after the property data
- VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
- vmd->methodCount = obj->functionCount();
-
return true;
}
@@ -1301,7 +1299,7 @@ void QQmlAliasAnnotator::annotateBindingsToAliases()
const QmlIR::Object *obj = qmlObjects.at(i);
QmlIR::PropertyResolver resolver(propertyCache);
- QQmlPropertyData *defaultProperty = obj->indexOfDefaultProperty != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
+ QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
if (!binding->isValueBinding())
@@ -1333,7 +1331,7 @@ void QQmlScriptStringScanner::scan()
const QmlIR::Object *obj = qmlObjects.at(i);
QmlIR::PropertyResolver resolver(propertyCache);
- QQmlPropertyData *defaultProperty = obj->indexOfDefaultProperty != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
+ QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
if (binding->type != QV4::CompiledData::Binding::Type_Script)
@@ -1373,7 +1371,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
{
QmlIR::PropertyResolver propertyResolver(propertyCache);
- QQmlPropertyData *defaultProperty = obj->indexOfDefaultProperty != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
+ QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
if (binding->type != QV4::CompiledData::Binding::Type_Object)
@@ -1480,7 +1478,7 @@ bool QQmlComponentAndAliasResolver::resolve()
if (obj->functionCount() > 0)
COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new functions."));
- if (obj->propertyCount() > 0)
+ if (obj->propertyCount() > 0 || obj->aliasCount() > 0)
COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new properties."));
if (obj->signalCount() > 0)
COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new signals."));
@@ -1551,12 +1549,8 @@ bool QQmlComponentAndAliasResolver::collectIdsAndAliases(int objectIndex)
_objectIndexToIdInScope->insert(objectIndex, _objectIndexToIdInScope->count());
}
- for (const QmlIR::Property *property = obj->firstProperty(); property; property = property->next) {
- if (property->type == QV4::CompiledData::Property::Alias) {
- _objectsWithAliases.append(objectIndex);
- break;
- }
- }
+ if (obj->aliasCount() > 0)
+ _objectsWithAliases.append(objectIndex);
for (const QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
if (binding->type != QV4::CompiledData::Binding::Type_Object
@@ -1587,21 +1581,18 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
int effectivePropertyIndex = propertyCache->propertyIndexCacheStart + propertyCache->propertyIndexCache.count();
int effectiveAliasIndex = 0;
- const QmlIR::Property *p = obj->firstProperty();
- for (int propertyIndex = 0; propertyIndex < obj->propertyCount(); ++propertyIndex, p = p->next) {
- if (p->type != QV4::CompiledData::Property::Alias)
- continue;
-
- const int idIndex = p->aliasIdValueIndex;
+ int aliasIndex = 0;
+ for (const QmlIR::Alias *alias = obj->firstAlias(); alias; alias = alias->next, ++aliasIndex) {
+ const int idIndex = alias->idIndex;
const int targetObjectIndex = _idToObjectIndex.value(idIndex, -1);
if (targetObjectIndex == -1) {
- recordError(p->aliasLocation, tr("Invalid alias reference. Unable to find id \"%1\"").arg(stringAt(idIndex)));
+ recordError(alias->referenceLocation, tr("Invalid alias reference. Unable to find id \"%1\"").arg(stringAt(idIndex)));
return false;
}
const int targetId = _objectIndexToIdInScope->value(targetObjectIndex, -1);
Q_ASSERT(targetId != -1);
- const QString aliasPropertyValue = stringAt(p->aliasPropertyValueIndex);
+ const QString aliasPropertyValue = stringAt(alias->propertyIndex);
QStringRef property;
QStringRef subProperty;
@@ -1642,7 +1633,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
QQmlPropertyData *targetProperty = resolver.property(property.toString());
if (!targetProperty || targetProperty->coreIndex > 0x0000FFFF) {
- recordError(p->aliasLocation, tr("Invalid alias target location: %1").arg(property.toString()));
+ recordError(alias->referenceLocation, tr("Invalid alias target location: %1").arg(property.toString()));
return false;
}
@@ -1656,7 +1647,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
if (!subProperty.isEmpty()) {
const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(type);
if (!valueTypeMetaObject) {
- recordError(p->aliasLocation, tr("Invalid alias target location: %1").arg(subProperty.toString()));
+ recordError(alias->referenceLocation, tr("Invalid alias target location: %1").arg(subProperty.toString()));
return false;
}
@@ -1665,7 +1656,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
int valueTypeIndex =
valueTypeMetaObject->indexOfProperty(subProperty.toString().toUtf8().constData());
if (valueTypeIndex == -1) {
- recordError(p->aliasLocation, tr("Invalid alias target location: %1").arg(subProperty.toString()));
+ recordError(alias->referenceLocation, tr("Invalid alias target location: %1").arg(subProperty.toString()));
return false;
}
Q_ASSERT(valueTypeIndex <= 0x0000FFFF);
@@ -1702,7 +1693,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
Q_ASSERT(dynamicData.isDetached());
- if (!(p->flags & QV4::CompiledData::Property::IsReadOnly) && writable)
+ if (!(alias->flags & QV4::CompiledData::Property::IsReadOnly) && writable)
propertyFlags |= QQmlPropertyData::IsWritable;
else
propertyFlags &= ~QQmlPropertyData::IsWritable;
@@ -1712,8 +1703,11 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
else
propertyFlags &= ~QQmlPropertyData::IsResettable;
- QString propertyName = stringAt(p->nameIndex);
- if (propertyIndex == obj->indexOfDefaultProperty) propertyCache->_defaultPropertyName = propertyName;
+ QString propertyName = stringAt(alias->nameIndex);
+
+ if (obj->defaultPropertyIsAlias && aliasIndex == obj->indexOfDefaultPropertyOrAlias)
+ propertyCache->_defaultPropertyName = propertyName;
+
propertyCache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
type, effectiveSignalIndex++);
@@ -1825,7 +1819,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
QString defaultPropertyName;
QQmlPropertyData *defaultProperty = 0;
- if (obj->indexOfDefaultProperty != -1) {
+ if (obj->indexOfDefaultPropertyOrAlias != -1) {
QQmlPropertyCache *cache = propertyCache->parent();
defaultPropertyName = cache->defaultPropertyName();
defaultProperty = cache->defaultProperty();
@@ -2545,7 +2539,7 @@ void QQmlDefaultPropertyMerger::mergeDefaultProperties(int objectIndex)
QmlIR::Object *object = qmlObjects.at(objectIndex);
- QString defaultProperty = object->indexOfDefaultProperty != -1 ? propertyCache->parent()->defaultPropertyName() : propertyCache->defaultPropertyName();
+ QString defaultProperty = object->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultPropertyName() : propertyCache->defaultPropertyName();
QmlIR::Binding *bindingsToReinsert = 0;
QmlIR::Binding *tail = 0;
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index ac27124d70..27debc0ce8 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -351,7 +351,7 @@ struct Property
enum Type { Var = 0, Variant, Int, Bool, Real, String, Url, Color,
Font, Time, Date, DateTime, Rect, Point, Size,
Vector2D, Vector3D, Vector4D, Matrix4x4, Quaternion,
- Alias, Custom, CustomList };
+ Custom, CustomList };
enum Flags {
IsReadOnly = 0x1
@@ -360,13 +360,20 @@ struct Property
quint32 nameIndex;
quint32 type : 31;
quint32 flags : 1; // readonly
- union {
- quint32 customTypeNameIndex; // If type >= Custom
- quint32 aliasIdValueIndex; // If type == Alias
+ quint32 customTypeNameIndex; // If type >= Custom
+ Location location;
+};
+
+struct Alias {
+ enum Flags {
+ IsReadOnly = 0x1
};
- quint32 aliasPropertyValueIndex;
+ quint32 nameIndex;
+ quint32 idIndex;
+ quint32 propertyIndex : 31;
+ quint32 flags : 1;
Location location;
- Location aliasLocation; // If type == Alias
+ Location referenceLocation;
};
struct Object
@@ -376,11 +383,14 @@ struct Object
// it will be the name of the attached type.
quint32 inheritedTypeNameIndex;
quint32 idIndex;
- qint32 indexOfDefaultProperty; // -1 means no default property declared in this object
+ qint32 indexOfDefaultPropertyOrAlias : 31; // -1 means no default property declared in this object
+ quint32 defaultPropertyIsAlias : 1;
quint32 nFunctions;
quint32 offsetToFunctions;
quint32 nProperties;
quint32 offsetToProperties;
+ quint32 nAliases;
+ quint32 offsetToAliases;
quint32 nSignals;
quint32 offsetToSignals; // which in turn will be a table with offsets to variable-sized Signal objects
quint32 nBindings;
@@ -392,11 +402,12 @@ struct Object
// Signal[]
// Binding[]
- static int calculateSizeExcludingSignals(int nFunctions, int nProperties, int nSignals, int nBindings)
+ static int calculateSizeExcludingSignals(int nFunctions, int nProperties, int nAliases, int nSignals, int nBindings)
{
return ( sizeof(Object)
+ nFunctions * sizeof(quint32)
+ nProperties * sizeof(Property)
+ + nAliases * sizeof(Alias)
+ nSignals * sizeof(quint32)
+ nBindings * sizeof(Binding)
+ 0x7
@@ -413,6 +424,11 @@ struct Object
return reinterpret_cast<const Property*>(reinterpret_cast<const char *>(this) + offsetToProperties);
}
+ const Alias *aliasTable() const
+ {
+ return reinterpret_cast<const Alias*>(reinterpret_cast<const char *>(this) + offsetToAliases);
+ }
+
const Binding *bindingTable() const
{
return reinterpret_cast<const Binding*>(reinterpret_cast<const char *>(this) + offsetToBindings);
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 2ffb1596f5..b8c12f70d1 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -664,7 +664,7 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
if (qmlTypeForObject(_bindingTarget)) {
quint32 bindingSkipList = 0;
- QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultProperty != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
+ QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultPropertyOrAlias != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {