diff options
Diffstat (limited to 'src/qml/compiler/qqmlirbuilder.cpp')
-rw-r--r-- | src/qml/compiler/qqmlirbuilder.cpp | 407 |
1 files changed, 246 insertions, 161 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index eaf0e72296..f736e04b88 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -49,7 +49,6 @@ #include <private/qqmlglobal_p.h> #include <private/qqmltypeloader_p.h> #include <private/qqmlengine_p.h> -#include <private/qqmlcompiler_p.h> #endif #ifdef CONST @@ -72,21 +71,24 @@ using namespace QmlIR; return false; \ } -void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int id, const QQmlJS::AST::SourceLocation &loc) +void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, const QQmlJS::AST::SourceLocation &loc) { inheritedTypeNameIndex = typeNameIndex; location.line = loc.startLine; location.column = loc.startColumn; - idIndex = id; - indexOfDefaultProperty = -1; + idNameIndex = idIndex; + id = -1; + indexOfDefaultPropertyOrAlias = -1; + defaultPropertyIsAlias = false; + flags = QV4::CompiledData::Object::NoFlag; 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> >(); functionsAndExpressions = pool->New<PoolList<CompiledFunctionOrExpression> >(); - runtimeFunctionIndices = 0; declarationsOverride = 0; } @@ -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; @@ -164,7 +193,7 @@ void Object::appendFunction(QmlIR::Function *f) QString Object::appendBinding(Binding *b, bool isListBinding) { - const bool bindingToDefaultProperty = (b->propertyNameIndex == 0); + const bool bindingToDefaultProperty = (b->propertyNameIndex == quint32(0)); if (!isListBinding && !bindingToDefaultProperty && b->type != QV4::CompiledData::Binding::Type_GroupProperty && b->type != QV4::CompiledData::Binding::Type_AttachedProperty @@ -190,7 +219,7 @@ Binding *Object::findBinding(quint32 nameIndex) const void Object::insertSorted(Binding *b) { - Binding *insertionPoint = bindings->findSortedInsertionPoint<QV4::CompiledData::Location, QV4::CompiledData::Binding, &QV4::CompiledData::Binding::valueLocation>(b); + Binding *insertionPoint = bindings->findSortedInsertionPoint<quint32, Binding, &Binding::offset>(b); bindings->insertAfter(insertionPoint, b); } @@ -222,32 +251,6 @@ static void replaceWithSpace(QString &str, int idx, int n) *data++ = space; } -void Document::collectTypeReferences() -{ - foreach (Object *obj, objects) { - if (obj->inheritedTypeNameIndex != emptyStringIndex) { - QV4::CompiledData::TypeReference &r = typeReferences.add(obj->inheritedTypeNameIndex, obj->location); - r.needsCreation = true; - r.errorWhenNotFound = true; - } - - for (const Property *prop = obj->firstProperty(); prop; prop = prop->next) { - if (prop->type >= QV4::CompiledData::Property::Custom) { - // ### FIXME: We could report the more accurate location here by using prop->location, but the old - // compiler can't and the tests expect it to be the object location right now. - QV4::CompiledData::TypeReference &r = typeReferences.add(prop->customTypeNameIndex, obj->location); - r.needsCreation = true; - r.errorWhenNotFound = true; - } - } - - for (const Binding *binding = obj->firstBinding(); binding; binding = binding->next) { - if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) - typeReferences.add(binding->propertyNameIndex, binding->location); - } - } -} - void Document::removeScriptPragmas(QString &script) { const QLatin1String pragma("pragma"); @@ -637,7 +640,10 @@ bool IRBuilder::visit(QQmlJS::AST::UiImport *node) } if (node->versionToken.isValid()) { - extractVersion(textRefAt(node->versionToken), &import->majorVersion, &import->minorVersion); + int major, minor; + extractVersion(textRefAt(node->versionToken), &major, &minor); + import->majorVersion = major; + import->minorVersion = minor; } else if (import->type == QV4::CompiledData::Import::ImportLibrary) { recordError(node->importIdToken, QCoreApplication::translate("QQmlParser","Library import requires a version")); return false; @@ -807,130 +813,87 @@ 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('.'); - propertyValue += 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) { + if (!isRedundantNullInitializerForPropertyDeclaration(_propertyDeclaration, node->statement)) + appendBinding(node->identifierToken, node->identifierToken, _propertyDeclaration->nameIndex, node->statement); + } + qSwap(_propertyDeclaration, property); } - qSwap(_propertyDeclaration, property); } return false; @@ -952,6 +915,16 @@ bool IRBuilder::visit(QQmlJS::AST::UiSourceElement *node) f->location.column = loc.startColumn; f->index = index; f->nameIndex = registerString(funDecl->name.toString()); + + int formalsCount = 0; + for (QQmlJS::AST::FormalParameterList *it = funDecl->formals; it; it = it->next) + ++formalsCount; + f->formals.allocate(pool, formalsCount); + + int i = 0; + for (QQmlJS::AST::FormalParameterList *it = funDecl->formals; it; it = it->next, ++i) + f->formals[i] = registerString(it->name.toString()); + _object->appendFunction(f); } else { recordError(node->firstSourceLocation(), QCoreApplication::translate("QQmlParser","JavaScript declaration outside Script element")); @@ -1027,13 +1000,13 @@ void IRBuilder::setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST binding->value.b = false; } else if (QQmlJS::AST::NumericLiteral *lit = QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(expr)) { binding->type = QV4::CompiledData::Binding::Type_Number; - binding->value.d = lit->value; + binding->setNumberValueInternal(lit->value); } else { if (QQmlJS::AST::UnaryMinusExpression *unaryMinus = QQmlJS::AST::cast<QQmlJS::AST::UnaryMinusExpression *>(expr)) { if (QQmlJS::AST::NumericLiteral *lit = QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(unaryMinus->expression)) { binding->type = QV4::CompiledData::Binding::Type_Number; - binding->value.d = -lit->value; + binding->setNumberValueInternal(-lit->value); } } } @@ -1085,6 +1058,7 @@ void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLo { Binding *binding = New<Binding>(); binding->propertyNameIndex = propertyNameIndex; + binding->offset = nameLocation.offset; binding->location.line = nameLocation.startLine; binding->location.column = nameLocation.startColumn; binding->flags = 0; @@ -1104,6 +1078,7 @@ void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLo Binding *binding = New<Binding>(); binding->propertyNameIndex = propertyNameIndex; + binding->offset = nameLocation.offset; binding->location.line = nameLocation.startLine; binding->location.column = nameLocation.startColumn; @@ -1133,6 +1108,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->propertyNameIndex = 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->propertyNameIndex = 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) @@ -1178,10 +1226,10 @@ bool IRBuilder::setId(const QQmlJS::AST::SourceLocation &idLocation, QQmlJS::AST if (illegalNames.contains(idQString)) COMPILE_EXCEPTION(loc, tr( "ID illegally masks global JavaScript property")); - if (_object->idIndex != emptyStringIndex) + if (_object->idNameIndex != emptyStringIndex) COMPILE_EXCEPTION(idLocation, tr("Property value set multiple times")); - _object->idIndex = registerString(idQString); + _object->idNameIndex = registerString(idQString); _object->locationOfIdProperty.line = idLocation.startLine; _object->locationOfIdProperty.column = idLocation.startColumn; @@ -1202,8 +1250,7 @@ bool IRBuilder::resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, O if (import->qualifierIndex != emptyStringIndex && stringAt(import->qualifierIndex) == currentName) { qualifiedIdElement = qualifiedIdElement->next; - currentName += QLatin1Char('.'); - currentName += qualifiedIdElement->name; + currentName += QLatin1Char('.') + qualifiedIdElement->name; if (!qualifiedIdElement->name.unicode()->isUpper()) COMPILE_EXCEPTION(qualifiedIdElement->firstSourceLocation(), tr("Expected type name")); @@ -1229,6 +1276,7 @@ bool IRBuilder::resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, O if (!binding) { binding = New<Binding>(); binding->propertyNameIndex = propertyNameIndex; + binding->offset = qualifiedIdElement->identifierToken.offset; binding->location.line = qualifiedIdElement->identifierToken.startLine; binding->location.column = qualifiedIdElement->identifierToken.startColumn; binding->valueLocation.line = qualifiedIdElement->next->identifierToken.startLine; @@ -1300,6 +1348,17 @@ bool IRBuilder::isStatementNodeScript(QQmlJS::AST::Statement *statement) return true; } +bool IRBuilder::isRedundantNullInitializerForPropertyDeclaration(Property *property, QQmlJS::AST::Statement *statement) +{ + if (property->type != QV4::CompiledData::Property::Custom) + return false; + QQmlJS::AST::ExpressionStatement *exprStmt = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement *>(statement); + if (!exprStmt) + return false; + QQmlJS::AST::ExpressionNode * const expr = exprStmt->expression; + return QQmlJS::AST::cast<QQmlJS::AST::NullExpression *>(expr); +} + QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output) { QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = output.javaScriptCompilationUnit; @@ -1309,12 +1368,12 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output) const int importSize = sizeof(QV4::CompiledData::Import) * output.imports.count(); const int objectOffsetTableSize = output.objects.count() * sizeof(quint32); - QHash<Object*, quint32> objectOffsets; + QHash<const Object*, quint32> objectOffsets; 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(), o->namedObjectsInComponent.count); int signalTableSize = 0; for (const Signal *s = o->firstSignal(); s; s = s->next) @@ -1354,13 +1413,17 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output) // write objects quint32 *objectTable = reinterpret_cast<quint32*>(data + qmlUnit->offsetToObjects); char *objectPtr = data + qmlUnit->offsetToObjects + objectOffsetTableSize; - foreach (Object *o, output.objects) { + for (int i = 0; i < output.objects.count(); ++i) { + const Object *o = output.objects.at(i); *objectTable++ = objectOffsets.value(o); QV4::CompiledData::Object *objectToWrite = reinterpret_cast<QV4::CompiledData::Object*>(objectPtr); objectToWrite->inheritedTypeNameIndex = o->inheritedTypeNameIndex; - objectToWrite->indexOfDefaultProperty = o->indexOfDefaultProperty; - objectToWrite->idIndex = o->idIndex; + objectToWrite->indexOfDefaultPropertyOrAlias = o->indexOfDefaultPropertyOrAlias; + objectToWrite->defaultPropertyIsAlias = o->defaultPropertyIsAlias; + objectToWrite->flags = o->flags; + objectToWrite->idNameIndex = o->idNameIndex; + objectToWrite->id = o->id; objectToWrite->location = o->location; objectToWrite->locationOfIdProperty = o->locationOfIdProperty; @@ -1374,6 +1437,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); @@ -1382,9 +1449,13 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output) objectToWrite->offsetToBindings = nextOffset; nextOffset += objectToWrite->nBindings * sizeof(QV4::CompiledData::Binding); + objectToWrite->nNamedObjectsInComponent = o->namedObjectsInComponent.count; + objectToWrite->offsetToNamedObjectsInComponent = nextOffset; + nextOffset += objectToWrite->nNamedObjectsInComponent * sizeof(quint32); + quint32 *functionsTable = reinterpret_cast<quint32*>(objectPtr + objectToWrite->offsetToFunctions); for (const Function *f = o->firstFunction(); f; f = f->next) - *functionsTable++ = o->runtimeFunctionIndices->at(f->index); + *functionsTable++ = o->runtimeFunctionIndices.at(f->index); char *propertiesPtr = objectPtr + objectToWrite->offsetToProperties; for (const Property *p = o->firstProperty(); p; p = p->next) { @@ -1393,6 +1464,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); @@ -1421,7 +1499,12 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output) signalPtr += size; } - objectPtr += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->signalCount(), o->bindingCount()); + quint32 *namedObjectInComponentPtr = reinterpret_cast<quint32*>(objectPtr + objectToWrite->offsetToNamedObjectsInComponent); + for (int i = 0; i < o->namedObjectsInComponent.count; ++i) { + *namedObjectInComponentPtr++ = o->namedObjectsInComponent.at(i); + } + + objectPtr += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->aliasCount(), o->signalCount(), o->bindingCount(), o->namedObjectsInComponent.count); objectPtr += signalTableSize; } @@ -1438,7 +1521,7 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output) return qmlUnit; } -char *QmlUnitGenerator::writeBindings(char *bindingPtr, Object *o, BindingFilter filter) const +char *QmlUnitGenerator::writeBindings(char *bindingPtr, const Object *o, BindingFilter filter) const { for (const Binding *b = o->firstBinding(); b; b = b->next) { if (!(b->*(filter))()) @@ -1446,7 +1529,7 @@ char *QmlUnitGenerator::writeBindings(char *bindingPtr, Object *o, BindingFilter QV4::CompiledData::Binding *bindingToWrite = reinterpret_cast<QV4::CompiledData::Binding*>(bindingPtr); *bindingToWrite = *b; if (b->type == QV4::CompiledData::Binding::Type_Script) - bindingToWrite->value.compiledScriptIndex = o->runtimeFunctionIndices->at(b->value.compiledScriptIndex); + bindingToWrite->value.compiledScriptIndex = o->runtimeFunctionIndices.at(b->value.compiledScriptIndex); bindingPtr += sizeof(QV4::CompiledData::Binding); } return bindingPtr; @@ -1614,7 +1697,7 @@ static QV4::IR::DiscoveredType resolveQmlType(QQmlEnginePrivate *qmlEngine, if (tdata->isComplete()) { auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>(); newResolver->owner = resolver->owner; - initMetaObjectResolver(newResolver, qmlEngine->propertyCacheForType(tdata->compiledData()->metaTypeId)); + initMetaObjectResolver(newResolver, qmlEngine->propertyCacheForType(tdata->compilationUnit()->metaTypeId)); newResolver->flags |= AllPropertiesAreFinal; return newResolver->resolveMember(qmlEngine, newResolver, member); } @@ -1822,7 +1905,9 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int // Look for IDs first. foreach (const IdMapping &mapping, _idObjects) if (name == mapping.name) { - _function->idObjectDependencies.insert(mapping.idIndex); + if (_function->isQmlBinding) + _function->idObjectDependencies.insert(mapping.idIndex); + QV4::IR::Expr *s = _block->MEMBER(_block->TEMP(_qmlContextTemp), _function->newString(name), 0, QV4::IR::Member::MemberOfIdObjectsArray, mapping.idIndex); QV4::IR::Temp *result = _block->TEMP(_block->newTemp()); _block->MOVE(result, s); @@ -1907,7 +1992,7 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int #ifndef V4_BOOTSTRAP -QQmlPropertyData *PropertyResolver::property(const QString &name, bool *notInRevision, RevisionCheck check) +QQmlPropertyData *PropertyResolver::property(const QString &name, bool *notInRevision, RevisionCheck check) const { if (notInRevision) *notInRevision = false; @@ -1926,7 +2011,7 @@ QQmlPropertyData *PropertyResolver::property(const QString &name, bool *notInRev } -QQmlPropertyData *PropertyResolver::signal(const QString &name, bool *notInRevision) +QQmlPropertyData *PropertyResolver::signal(const QString &name, bool *notInRevision) const { if (notInRevision) *notInRevision = false; |