diff options
Diffstat (limited to 'src/qml/compiler/qqmlcodegenerator.cpp')
-rw-r--r-- | src/qml/compiler/qqmlcodegenerator.cpp | 108 |
1 files changed, 61 insertions, 47 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp index 13b23fde68..22ae1228c7 100644 --- a/src/qml/compiler/qqmlcodegenerator.cpp +++ b/src/qml/compiler/qqmlcodegenerator.cpp @@ -64,6 +64,21 @@ using namespace QtQml; return false; \ } +void QmlObject::init(MemoryPool *pool, int typeNameIndex, int id, const AST::SourceLocation &loc) +{ + inheritedTypeNameIndex = typeNameIndex; + + location.line = loc.startLine; + location.column = loc.startColumn; + + idIndex = id; + indexOfDefaultProperty = -1; + properties = pool->New<PoolList<QmlProperty> >(); + qmlSignals = pool->New<PoolList<Signal> >(); + bindings = pool->New<PoolList<Binding> >(); + functions = pool->New<PoolList<Function> >(); +} + void QmlObject::dump(DebugStream &out) { out << inheritedTypeNameIndex << " {" << endl; @@ -82,8 +97,9 @@ QStringList Signal::parameterStringList(const QStringList &stringPool) const return result; } -QQmlCodeGenerator::QQmlCodeGenerator() - : _object(0) +QQmlCodeGenerator::QQmlCodeGenerator(const QSet<QString> &illegalNames) + : illegalNames(illegalNames) + , _object(0) , jsGenerator(0) { } @@ -214,7 +230,7 @@ bool QQmlCodeGenerator::visit(AST::UiObjectDefinition *node) bool QQmlCodeGenerator::visit(AST::UiObjectBinding *node) { int idx = defineQMLObject(node->qualifiedTypeNameId, node->initializer); - appendBinding(node->qualifiedId, idx); + appendBinding(node->qualifiedId, idx, node->hasOnToken); return false; } @@ -292,10 +308,8 @@ bool QQmlCodeGenerator::sanityCheckFunctionNames() if (name.at(0).isUpper()) COMPILE_EXCEPTION(function->identifierToken, tr("Method names cannot begin with an upper case letter")); -#if 0 // ### - if (enginePrivate->v8engine()->illegalNames().contains(currSlot.name.toString())) - COMPILE_EXCEPTION(&currSlot, tr("Illegal method name")); -#endif + if (illegalNames.contains(name)) + COMPILE_EXCEPTION(function->identifierToken, tr("Illegal method name")); } return true; } @@ -307,20 +321,10 @@ int QQmlCodeGenerator::defineQMLObject(AST::UiQualifiedId *qualifiedTypeNameId, const int objectIndex = _objects.size() - 1; qSwap(_object, obj); - _object->inheritedTypeNameIndex = registerString(asString(qualifiedTypeNameId)); - AST::SourceLocation loc; if (qualifiedTypeNameId) loc = qualifiedTypeNameId->firstSourceLocation(); - _object->location.line = loc.startLine; - _object->location.column = loc.startColumn; - - _object->idIndex = emptyStringIndex; - _object->indexOfDefaultProperty = -1; - _object->properties = New<PoolList<QmlProperty> >(); - _object->qmlSignals = New<PoolList<Signal> >(); - _object->bindings = New<PoolList<Binding> >(); - _object->functions = New<PoolList<Function> >(); + _object->init(pool, registerString(asString(qualifiedTypeNameId)), emptyStringIndex, loc); QSet<QString> propertyNames; qSwap(_propertyNames, propertyNames); @@ -589,10 +593,8 @@ bool QQmlCodeGenerator::visit(AST::UiPublicMember *node) if (signalName.at(0).isUpper()) COMPILE_EXCEPTION(node->identifierToken, tr("Signal names cannot begin with an upper case letter")); -#if 0 // ### cannot access identifier table from separate thread - if (enginePrivate->v8engine()->illegalNames().contains(currSig.name.toString())) - COMPILE_EXCEPTION(&currSig, tr("Illegal signal name")); -#endif + if (illegalNames.contains(signalName)) + COMPILE_EXCEPTION(node->identifierToken, tr("Illegal signal name")); _object->qmlSignals->append(signal); } else { @@ -739,6 +741,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 { @@ -844,13 +850,13 @@ void QQmlCodeGenerator::appendBinding(AST::UiQualifiedId *name, AST::Statement * qSwap(_object, object); } -void QQmlCodeGenerator::appendBinding(AST::UiQualifiedId *name, int objectIndex) +void QQmlCodeGenerator::appendBinding(AST::UiQualifiedId *name, int objectIndex, bool isOnAssignment) { QmlObject *object = 0; if (!resolveQualifiedId(&name, &object)) return; qSwap(_object, object); - appendBinding(name->identifierToken, registerString(name->name.toString()), objectIndex); + appendBinding(name->identifierToken, registerString(name->name.toString()), objectIndex, /*isListItem*/false, isOnAssignment); qSwap(_object, object); } @@ -873,9 +879,9 @@ void QQmlCodeGenerator::appendBinding(const AST::SourceLocation &nameLocation, i _object->bindings->append(binding); } -void QQmlCodeGenerator::appendBinding(const AST::SourceLocation &nameLocation, int propertyNameIndex, int objectIndex, bool isListItem) +void QQmlCodeGenerator::appendBinding(const AST::SourceLocation &nameLocation, int propertyNameIndex, int objectIndex, bool isListItem, bool isOnAssignment) { - if (!sanityCheckPropertyName(nameLocation, propertyNameIndex, isListItem)) + if (!sanityCheckPropertyName(nameLocation, propertyNameIndex, isListItem | isOnAssignment)) return; if (stringAt(propertyNameIndex) == QStringLiteral("id")) { @@ -888,7 +894,16 @@ void QQmlCodeGenerator::appendBinding(const AST::SourceLocation &nameLocation, i binding->location.line = nameLocation.startLine; binding->location.column = nameLocation.startColumn; binding->flags = 0; - binding->type = QV4::CompiledData::Binding::Type_Object; + + // No type name on the initializer means it must be a group property + if (stringAt(_objects.at(objectIndex)->inheritedTypeNameIndex).isEmpty()) + binding->type = QV4::CompiledData::Binding::Type_GroupProperty; + else + binding->type = QV4::CompiledData::Binding::Type_Object; + + if (isOnAssignment) + binding->flags |= QV4::CompiledData::Binding::IsOnAssignment; + binding->value.objectIndex = objectIndex; _object->bindings->append(binding); } @@ -926,12 +941,11 @@ bool QQmlCodeGenerator::setId(AST::Statement *value) COMPILE_EXCEPTION(loc, tr( "IDs must contain only letters, numbers, and underscores")); } -#if 0 // ### - if (enginePrivate->v8engine()->illegalNames().contains(str)) - COMPILE_EXCEPTION(v, tr( "ID illegally masks global JavaScript property")); -#endif + QString idQString(str.toString()); + if (illegalNames.contains(idQString)) + COMPILE_EXCEPTION(loc, tr( "ID illegally masks global JavaScript property")); - _object->idIndex = registerString(str.toString()); + _object->idIndex = registerString(idQString); _object->locationOfIdProperty.line = loc.startLine; _object->locationOfIdProperty.column = loc.startColumn; @@ -970,14 +984,14 @@ bool QQmlCodeGenerator::resolveQualifiedId(AST::UiQualifiedId **nameToResolve, Q return true; } -bool QQmlCodeGenerator::sanityCheckPropertyName(const AST::SourceLocation &nameLocation, int nameIndex, bool isListItem) +bool QQmlCodeGenerator::sanityCheckPropertyName(const AST::SourceLocation &nameLocation, int nameIndex, bool isListItemOnOrAssignment) { const QString &name = jsGenerator->strings.at(nameIndex); if (name.isEmpty()) return true; // List items are implement by multiple bindings to the same name, so allow duplicates. - if (!isListItem) { + if (!isListItemOnOrAssignment) { if (_propertyNames.contains(name)) COMPILE_EXCEPTION(nameLocation, tr("Duplicate property name")); @@ -987,13 +1001,8 @@ bool QQmlCodeGenerator::sanityCheckPropertyName(const AST::SourceLocation &nameL if (name.at(0).isUpper()) COMPILE_EXCEPTION(nameLocation, tr("Property names cannot begin with an upper case letter")); -#if 0 // ### how to check against illegalNames when in separate thread? - if (enginePrivate->v8engine()->illegalNames().contains(prop.name.toString())) { - COMPILE_EXCEPTION_LOCATION(prop.nameLocation.line, - prop.nameLocation.column, - tr("Illegal property name")); - } -#endif + if (illegalNames.contains(name)) + COMPILE_EXCEPTION(nameLocation, tr("Illegal property name")); return true; } @@ -1625,11 +1634,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; - QQmlPropertyCache *cache = unit->resolvedTypes[obj->inheritedTypeNameIndex].createPropertyCache(QQmlEnginePrivate::get(enginePrivate)); + QQmlCompiledData::TypeReference &tr = unit->resolvedTypes[obj->inheritedTypeNameIndex]; + if (tr.type && tr.type->customParser()) + continue; + QQmlPropertyCache *cache = unit->propertyCaches.value(objectIndex); + Q_ASSERT(cache); if (!convertSignalHandlerExpressionsToFunctionDeclarations(obj, elementName, cache)) return false; } @@ -1659,10 +1673,6 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio if (!QQmlCodeGenerator::isSignalPropertyName(propertyName)) continue; - if (binding->type != QV4::CompiledData::Binding::Type_Script) { - COMPILE_EXCEPTION(binding->location, tr("Incorrectly specified signal assignment")); - } - PropertyResolver resolver(propertyCache); Q_ASSERT(propertyName.startsWith(QStringLiteral("on"))); @@ -1731,6 +1741,10 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio parameters = entry.value(); } + if (binding->type != QV4::CompiledData::Binding::Type_Script) { + COMPILE_EXCEPTION(binding->location, tr("Incorrectly specified signal assignment")); + } + QQmlJS::Engine &jsEngine = parsedQML->jsParserEngine; QQmlJS::MemoryPool *pool = jsEngine.pool(); |