Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativecompiler.cpp
index e7d9b80..6c018c7 100644 (file)
@@ -1,8 +1,7 @@
 /****************************************************************************
 **
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
 **
 ** This file is part of the QtDeclarative module of the Qt Toolkit.
 **
@@ -35,6 +34,7 @@
 **
 **
 **
+**
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
 #include <QtCore/qdebug.h>
 #include <QtCore/qdatetime.h>
 
+Q_DECLARE_METATYPE(QList<int>)
+Q_DECLARE_METATYPE(QList<qreal>)
+Q_DECLARE_METATYPE(QList<bool>)
+Q_DECLARE_METATYPE(QList<QString>)
+Q_DECLARE_METATYPE(QList<QUrl>)
+
 QT_BEGIN_NAMESPACE
 
 DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP);
 DEFINE_BOOL_CONFIG_OPTION(compilerStatDump, QML_COMPILER_STATS);
 
+using namespace QDeclarativeJS;
 using namespace QDeclarativeScript;
 using namespace QDeclarativeCompilerTypes;
 
@@ -84,12 +91,16 @@ static QString id_string(QLatin1String("id"));
 static QString on_string(QLatin1String("on"));
 static QString Changed_string(QLatin1String("Changed"));
 static QString Component_string(QLatin1String("Component"));
+static QString Component_import_string(QLatin1String("QML/Component"));
+static QString qsTr_string(QLatin1String("qsTr"));
+static QString qsTrId_string(QLatin1String("qsTrId"));
 
 /*!
     Instantiate a new QDeclarativeCompiler.
 */
 QDeclarativeCompiler::QDeclarativeCompiler(QDeclarativePool *pool)
-: pool(pool), output(0), engine(0), unitRoot(0), unit(0), componentStats(0)
+: pool(pool), output(0), engine(0), unitRoot(0), unit(0), cachedComponentTypeRef(-1),
+  cachedTranslationContextIndex(-1), componentStats(0)
 {
     if (compilerStatDump()) 
         componentStats = pool->New<ComponentStats>();
@@ -174,18 +185,20 @@ bool QDeclarativeCompiler::isSignalPropertyName(const QHashedStringRef &name)
     COMPILE_EXCEPTION(property, tr("Error for property \"%1\"").arg(property->name));
     \endcode
 */
-#define COMPILE_EXCEPTION(token, desc) \
+#define COMPILE_EXCEPTION_LOCATION(line, column, desc) \
     {  \
-        QString exceptionDescription; \
         QDeclarativeError error; \
         error.setUrl(output->url); \
-        error.setLine((token)->location.start.line); \
-        error.setColumn((token)->location.start.column); \
+        error.setLine(line); \
+        error.setColumn(column); \
         error.setDescription(desc.trimmed()); \
         exceptions << error; \
         return false; \
     }
 
+#define COMPILE_EXCEPTION(token, desc) \
+    COMPILE_EXCEPTION_LOCATION((token)->location.start.line, (token)->location.start.column, desc)
+
 /*!
     \macro COMPILE_CHECK
     \internal
@@ -235,12 +248,18 @@ bool QDeclarativeCompiler::testLiteralAssignment(QDeclarativeScript::Property *p
         case QVariant::String:
             if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: string expected"));
             break;
+        case QVariant::StringList: // we expect a string literal.  A string list is not a literal assignment.
+            if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: string or string list expected"));
+            break;
         case QVariant::ByteArray:
             if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: byte array expected"));
             break;
         case QVariant::Url:
             if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: url expected"));
             break;
+        case QVariant::RegExp:
+            COMPILE_EXCEPTION(v, tr("Invalid property assignment: regular expression expected; use /pattern/ syntax"));
+            break;
         case QVariant::UInt:
             {
             bool ok = v->value.isNumber();
@@ -344,6 +363,41 @@ bool QDeclarativeCompiler::testLiteralAssignment(QDeclarativeScript::Property *p
             break;
         default:
             {
+            // check if assigning a literal value to a list property.
+            // in each case, check the singular, since an Array of the specified type
+            // will not go via this literal assignment codepath.
+            if (type == qMetaTypeId<QList<qreal> >()) {
+                if (!v->value.isNumber()) {
+                    COMPILE_EXCEPTION(v, tr("Invalid property assignment: real or array of reals expected"));
+                }
+                break;
+            } else if (type == qMetaTypeId<QList<int> >()) {
+                bool ok = v->value.isNumber();
+                if (ok) {
+                    double n = v->value.asNumber();
+                    if (double(int(n)) != n)
+                        ok = false;
+                }
+                if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: int or array of ints expected"));
+                break;
+            } else if (type == qMetaTypeId<QList<bool> >()) {
+                if (!v->value.isBoolean()) {
+                    COMPILE_EXCEPTION(v, tr("Invalid property assignment: bool or array of bools expected"));
+                }
+                break;
+            } else if (type == qMetaTypeId<QList<QString> >()) { // we expect a string literal.  A string list is not a literal assignment.
+                if (!v->value.isString()) {
+                    COMPILE_EXCEPTION(v, tr("Invalid property assignment: string or array of strings expected"));
+                }
+                break;
+            } else if (type == qMetaTypeId<QList<QUrl> >()) {
+                if (!v->value.isString()) {
+                    COMPILE_EXCEPTION(v, tr("Invalid property assignment: url or array of urls expected"));
+                }
+                break;
+            }
+
+            // otherwise, check for existence of string converter to custom type
             QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(type);
             if (!converter)
                 COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QVariant::typeToName((QVariant::Type)type))));
@@ -353,6 +407,14 @@ bool QDeclarativeCompiler::testLiteralAssignment(QDeclarativeScript::Property *p
     return true;
 }
 
+static QUrl urlFromUserString(const QString &data)
+{
+    QUrl u;
+    // Preserve any valid percent-encoded octets supplied by the source
+    u.setEncodedUrl(data.toUtf8(), QUrl::TolerantMode);
+    return u;
+}
+
 /*!
     Generate a store instruction for assigning literal \a v to property \a prop.
 
@@ -440,6 +502,14 @@ void QDeclarativeCompiler::genLiteralAssignment(QDeclarativeScript::Property *pr
             output->addInstruction(instr);
             }
             break;
+        case QVariant::StringList:
+            {
+            Instruction::StoreStringList instr;
+            instr.propertyIndex = prop->index;
+            instr.value = output->indexForString(v->value.asString());
+            output->addInstruction(instr);
+            }
+            break;
         case QVariant::ByteArray:
             {
             Instruction::StoreByteArray instr;
@@ -452,7 +522,7 @@ void QDeclarativeCompiler::genLiteralAssignment(QDeclarativeScript::Property *pr
             {
             Instruction::StoreUrl instr;
             QString string = v->value.asString();
-            QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(QUrl(string));
+            QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(urlFromUserString(string));
             instr.propertyIndex = prop->index;
             instr.value = output->indexForUrl(u);
             output->addInstruction(instr);
@@ -638,6 +708,43 @@ void QDeclarativeCompiler::genLiteralAssignment(QDeclarativeScript::Property *pr
             break;
         default:
             {
+            // generate single literal value assignment to a list property if required
+            if (type == qMetaTypeId<QList<qreal> >()) {
+                Instruction::StoreDoubleQList instr;
+                instr.propertyIndex = prop->index;
+                instr.value = v->value.asNumber();
+                output->addInstruction(instr);
+                break;
+            } else if (type == qMetaTypeId<QList<int> >()) {
+                Instruction::StoreIntegerQList instr;
+                instr.propertyIndex = prop->index;
+                instr.value = int(v->value.asNumber());
+                output->addInstruction(instr);
+                break;
+            } else if (type == qMetaTypeId<QList<bool> >()) {
+                Instruction::StoreBoolQList instr;
+                bool b = v->value.asBoolean();
+                instr.propertyIndex = prop->index;
+                instr.value = b;
+                output->addInstruction(instr);
+                break;
+            } else if (type == qMetaTypeId<QList<QUrl> >()) {
+                Instruction::StoreUrlQList instr;
+                QString string = v->value.asString();
+                QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(urlFromUserString(string));
+                instr.propertyIndex = prop->index;
+                instr.value = output->indexForUrl(u);
+                output->addInstruction(instr);
+                break;
+            } else if (type == qMetaTypeId<QList<QString> >()) {
+                Instruction::StoreStringQList instr;
+                instr.propertyIndex = prop->index;
+                instr.value = output->indexForString(v->value.asString());
+                output->addInstruction(instr);
+                break;
+            }
+
+            // otherwise, generate custom type literal assignment
             Instruction::AssignCustomType instr;
             instr.propertyIndex = prop->index;
             instr.primitive = output->indexForString(v->value.asString());
@@ -740,6 +847,8 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine,
     this->engine = 0;
     this->enginePrivate = 0;
     this->unit = 0;
+    this->cachedComponentTypeRef = -1;
+    this->cachedTranslationContextIndex = -1;
     this->unitRoot = 0;
 
     return !isError();
@@ -753,19 +862,28 @@ void QDeclarativeCompiler::compileTree(QDeclarativeScript::Object *tree)
     if (componentStats)
         componentStats->componentStat.lineNumber = tree->location.start.line;
 
-    // Build global import scripts
-    QStringList importedScriptIndexes;
-
-    foreach (const QDeclarativeTypeData::ScriptReference &script, unit->resolvedScripts()) {
-        importedScriptIndexes.append(script.qualifier);
-    }
-
     // We generate the importCache before we build the tree so that
     // it can be used in the binding compiler.  Given we "expect" the
     // QML compilation to succeed, this isn't a waste.
     output->importCache = new QDeclarativeTypeNameCache();
-    for (int ii = 0; ii < importedScriptIndexes.count(); ++ii) 
-        output->importCache->add(importedScriptIndexes.at(ii), ii);
+    foreach (const QString &ns, unit->namespaces()) {
+        output->importCache->add(ns);
+    }
+
+    int scriptIndex = 0;
+    foreach (const QDeclarativeTypeData::ScriptReference &script, unit->resolvedScripts()) {
+        QString qualifier = script.qualifier;
+        QString enclosingNamespace;
+
+        const int lastDotIndex = qualifier.lastIndexOf(QLatin1Char('.'));
+        if (lastDotIndex != -1) {
+            enclosingNamespace = qualifier.left(lastDotIndex);
+            qualifier = qualifier.mid(lastDotIndex+1);
+        }
+
+        output->importCache->add(qualifier, scriptIndex++, enclosingNamespace);
+    }
+
     unit->imports().populateCache(output->importCache, engine);
 
     if (!buildObject(tree, BindingContext()) || !completeComponentBuild())
@@ -1170,8 +1288,9 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeScript::Object *obj)
         ss.value = output->indexForString(script);
         ss.scope = prop->scriptStringScope;
 //        ss.bindingId = rewriteBinding(script, prop->name());
-        ss.bindingId = rewriteBinding(script, QString()); // XXX
+        ss.bindingId = rewriteBinding(prop->values.first()->value, QString()); // XXX
         ss.line = prop->location.start.line;
+        ss.column = prop->location.start.column;
         output->addInstruction(ss);
     }
 
@@ -1233,6 +1352,7 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeScript::Object *obj)
             store.value = output->indexForString(rewrite);
             store.context = v->signalExpressionContextStack;
             store.line = v->location.start.line;
+            store.column = v->location.start.column;
             output->addInstruction(store);
 
         }
@@ -1497,16 +1617,35 @@ bool QDeclarativeCompiler::buildSubObject(QDeclarativeScript::Object *obj, const
 
 int QDeclarativeCompiler::componentTypeRef()
 {
-    QDeclarativeType *t = QDeclarativeMetaType::qmlType(QLatin1String("QtQuick/Component"),2,0);
-    for (int ii = output->types.count() - 1; ii >= 0; --ii) {
-        if (output->types.at(ii).type == t)
-            return ii;
+    if (cachedComponentTypeRef == -1) {
+        QDeclarativeType *t = QDeclarativeMetaType::qmlType(Component_import_string,1,0);
+        for (int ii = output->types.count() - 1; ii >= 0; --ii) {
+            if (output->types.at(ii).type == t) {
+                cachedComponentTypeRef = ii;
+                return ii;
+            }
+        }
+        QDeclarativeCompiledData::TypeReference ref;
+        ref.className = Component_string;
+        ref.type = t;
+        output->types << ref;
+        cachedComponentTypeRef = output->types.count() - 1;
+    }
+    return cachedComponentTypeRef;
+}
+
+int QDeclarativeCompiler::translationContextIndex()
+{
+    if (cachedTranslationContextIndex == -1) {
+        // This code must match that in the qsTr() implementation
+        QString path = output->url.toString();
+        int lastSlash = path.lastIndexOf(QLatin1Char('/'));
+        QString context = (lastSlash > -1) ? path.mid(lastSlash + 1, path.length()-lastSlash-5) :
+                                             QString();
+        QByteArray contextUtf8 = context.toUtf8();
+        cachedTranslationContextIndex = output->indexForByteArray(contextUtf8);
     }
-    QDeclarativeCompiledData::TypeReference ref;
-    ref.className = Component_string;
-    ref.type = t;
-    output->types << ref;
-    return output->types.count() - 1;
+    return cachedTranslationContextIndex;
 }
 
 bool QDeclarativeCompiler::buildSignal(QDeclarativeScript::Property *prop, QDeclarativeScript::Object *obj,
@@ -1931,7 +2070,7 @@ void QDeclarativeCompiler::addId(const QString &id, QDeclarativeScript::Object *
     compileState->ids.append(obj);
 }
 
-void QDeclarativeCompiler::addBindingReference(BindingReference *ref)
+void QDeclarativeCompiler::addBindingReference(JSBindingReference *ref)
 {
     Q_ASSERT(ref->value && !ref->value->bindingReference);
     ref->value->bindingReference = ref;
@@ -2088,7 +2227,7 @@ bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type,
                 if (isEnumAssignment) {
                     value->type = Value::Literal;
                 } else {
-                    BindingReference *reference = pool->New<BindingReference>();
+                    JSBindingReference *reference = pool->New<JSBindingReference>();
                     reference->expression = value->value;
                     reference->property = prop;
                     reference->value = value;
@@ -2359,7 +2498,9 @@ bool QDeclarativeCompiler::buildPropertyLiteralAssignment(QDeclarativeScript::Pr
             }
         }
 
-        COMPILE_CHECK(buildBinding(v, prop, ctxt));
+        // Test for other binding optimizations
+        if (!buildLiteralBinding(v, prop, ctxt))
+            COMPILE_CHECK(buildBinding(v, prop, ctxt));
 
         v->type = Value::PropertyBinding;
 
@@ -2484,16 +2625,22 @@ const QMetaObject *QDeclarativeCompiler::resolveType(const QString& name) const
 
 // similar to logic of completeComponentBuild, but also sticks data
 // into primitives at the end
-int QDeclarativeCompiler::rewriteBinding(const QString& expression, const QString& name)
+int QDeclarativeCompiler::rewriteBinding(const QDeclarativeScript::Variant& value, const QString& name)
 {
     QDeclarativeRewrite::RewriteBinding rewriteBinding;
     rewriteBinding.setName(QLatin1Char('$') + name.mid(name.lastIndexOf(QLatin1Char('.')) + 1));
 
-    QString rewrite = rewriteBinding(expression, 0, 0);
+    QString rewrite = rewriteBinding(value.asAST(), value.asScript(), 0);
 
     return output->indexForString(rewrite);
 }
 
+QString QDeclarativeCompiler::rewriteSignalHandler(const QString &handler, const QString &name)
+{
+    QDeclarativeRewrite::RewriteSignalHandler rewriteSignalHandler;
+    return rewriteSignalHandler(handler, name);
+}
+
 // Ensures that the dynamic meta specification on obj is valid
 bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeScript::Object *obj)
 {
@@ -2518,16 +2665,25 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeScript::Object *obj)
         if (propNames.testAndSet(prop.name.hash())) {
             for (Object::DynamicProperty *p2 = obj->dynamicProperties.first(); p2 != p; 
                  p2 = obj->dynamicProperties.next(p2)) {
-                if (p2->name == prop.name)
-                    COMPILE_EXCEPTION(&prop, tr("Duplicate property name"));
+                if (p2->name == prop.name) {
+                    COMPILE_EXCEPTION_LOCATION(prop.nameLocation.line,
+                                               prop.nameLocation.column,
+                                               tr("Duplicate property name"));
+                }
             }
         }
 
-        if (prop.name.at(0).isUpper())
-            COMPILE_EXCEPTION(&prop, tr("Property names cannot begin with an upper case letter"));
+        if (prop.name.at(0).isUpper()) {
+            COMPILE_EXCEPTION_LOCATION(prop.nameLocation.line,
+                                       prop.nameLocation.column,
+                                       tr("Property names cannot begin with an upper case letter"));
+        }
 
-        if (enginePrivate->v8engine()->illegalNames().contains(prop.name))
-            COMPILE_EXCEPTION(&prop, tr("Illegal property name"));
+        if (enginePrivate->v8engine()->illegalNames().contains(prop.name)) {
+            COMPILE_EXCEPTION_LOCATION(prop.nameLocation.line,
+                                       prop.nameLocation.column,
+                                       tr("Illegal property name"));
+        }
     }
 
     for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
@@ -2680,8 +2836,8 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeScript::Object *obj, Dyn
         int metaType;
         const char *cppType;
     } builtinTypes[] = {
-        { Object::DynamicProperty::Var, 0, "QVariant" },
-        { Object::DynamicProperty::Variant, 0, "QVariant" },
+        { Object::DynamicProperty::Var, QMetaType::QVariant, "QVariant" },
+        { Object::DynamicProperty::Variant, QMetaType::QVariant, "QVariant" },
         { Object::DynamicProperty::Int, QMetaType::Int, "int" },
         { Object::DynamicProperty::Bool, QMetaType::Bool, "bool" },
         { Object::DynamicProperty::Real, QMetaType::Double, "double" },
@@ -2717,8 +2873,6 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeScript::Object *obj, Dyn
                 if (typeRefs[p->type].isEmpty()) 
                     typeRefs[p->type] = builder.newString(strlen(builtinTypes[p->type].cppType));
                 typeRef = typeRefs[p->type];
-                if (p->type == Object::DynamicProperty::Variant)
-                    propertyType = -1;
 
             } else {
                 Q_ASSERT(p->type == Object::DynamicProperty::CustomList ||
@@ -2797,11 +2951,11 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeScript::Object *obj, Dyn
                     QFastMetaBuilder::StringRef typeRef = typeRefs[p->type];
                     if (buildData) {
                         vmd->propertyCount++;
-                        (vmd->propertyData() + effectivePropertyIndex)->propertyType = -1;
+                        (vmd->propertyData() + effectivePropertyIndex)->propertyType = QMetaType::QVariant;
                     }
 
                     builder.setProperty(effectivePropertyIndex, p->nameRef, typeRef,
-                                        (QMetaType::Type)-1,
+                                        QMetaType::QVariant,
                                         p->isReadOnly?QFastMetaBuilder::None:QFastMetaBuilder::Writable,
                                         effectivePropertyIndex);
 
@@ -2998,11 +3152,12 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeScript::Object *obj, Dyn
     }
 
     if (obj->type != -1) {
-        QDeclarativePropertyCache *cache = output->types[obj->type].createPropertyCache(engine)->copy();
-        cache->append(engine, &obj->extObject,
-                      QDeclarativePropertyData::NoFlags,
-                      QDeclarativePropertyData::IsVMEFunction,
-                      QDeclarativePropertyData::IsVMESignal);
+        QDeclarativePropertyCache *superCache = output->types[obj->type].createPropertyCache(engine);
+        QDeclarativePropertyCache *cache =
+            superCache->copyAndAppend(engine, &obj->extObject,
+                                      QDeclarativePropertyData::NoFlags,
+                                      QDeclarativePropertyData::IsVMEFunction,
+                                      QDeclarativePropertyData::IsVMESignal);
 
         // now we modify the flags appropriately for var properties.
         int propertyOffset = obj->extObject.propertyOffset();
@@ -3113,8 +3268,8 @@ bool QDeclarativeCompiler::compileAlias(QFastMetaBuilder &builder,
         writable = aliasProperty.isWritable() && !prop.isReadOnly;
         resettable = aliasProperty.isResettable() && !prop.isReadOnly;
 
-        if (aliasProperty.type() < QVariant::UserType ||
-            aliasProperty.type() == QVariant::LastType /* for QVariant */ )
+        if (aliasProperty.type() < QVariant::UserType
+            || uint(aliasProperty.type()) == QMetaType::QVariant)
             type = aliasProperty.type();
 
         if (alias.count() == 3) {
@@ -3191,7 +3346,7 @@ bool QDeclarativeCompiler::buildBinding(QDeclarativeScript::Value *value,
     if (!prop->core.isWritable() && !prop->core.isQList() && !prop->isReadOnlyDeclaration)
         COMPILE_EXCEPTION(prop, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
 
-    BindingReference *reference = pool->New<BindingReference>();
+    JSBindingReference *reference = pool->New<JSBindingReference>();
     reference->expression = value->value;
     reference->property = prop;
     reference->value = value;
@@ -3201,6 +3356,79 @@ bool QDeclarativeCompiler::buildBinding(QDeclarativeScript::Value *value,
     return true;
 }
 
+bool QDeclarativeCompiler::buildLiteralBinding(QDeclarativeScript::Value *v,
+                                               QDeclarativeScript::Property *prop,
+                                               const QDeclarativeCompilerTypes::BindingContext &)
+{
+    Q_ASSERT(v->value.isScript());
+
+    if (!prop->core.isWritable())
+        return false;
+
+    AST::Node *binding = v->value.asAST();
+
+    if (prop->type == QVariant::String) {
+        if (AST::CallExpression *e = AST::cast<AST::CallExpression *>(binding)) {
+            if (AST::IdentifierExpression *i = AST::cast<AST::IdentifierExpression *>(e->base)) {
+                if (i->name == qsTrId_string) {
+                    AST::ArgumentList *arg1 = e->arguments?e->arguments:0;
+                    AST::ArgumentList *arg2 = arg1?arg1->next:0;
+
+                    if (arg1 && arg1->expression->kind == AST::Node::Kind_StringLiteral &&
+                        (!arg2 || arg2->expression->kind == AST::Node::Kind_NumericLiteral) &&
+                        (!arg2 || !arg2->next)) {
+
+                        QStringRef text;
+                        int n = -1;
+
+                        text = AST::cast<AST::StringLiteral *>(arg1->expression)->value;
+                        if (arg2) n = (int)AST::cast<AST::NumericLiteral *>(arg2->expression)->value;
+
+                        TrBindingReference *reference = pool->New<TrBindingReference>();
+                        reference->dataType = BindingReference::TrId;
+                        reference->text = text;
+                        reference->n = n;
+                        v->bindingReference = reference;
+                        return true;
+                    }
+
+                } else if (i->name == qsTr_string) {
+
+                    AST::ArgumentList *arg1 = e->arguments?e->arguments:0;
+                    AST::ArgumentList *arg2 = arg1?arg1->next:0;
+                    AST::ArgumentList *arg3 = arg2?arg2->next:0;
+
+                    if (arg1 && arg1->expression->kind == AST::Node::Kind_StringLiteral &&
+                        (!arg2 || arg2->expression->kind == AST::Node::Kind_StringLiteral) &&
+                        (!arg3 || arg3->expression->kind == AST::Node::Kind_NumericLiteral) &&
+                        (!arg3 || !arg3->next)) {
+
+                        QStringRef text;
+                        QStringRef comment;
+                        int n = -1;
+
+                        text = AST::cast<AST::StringLiteral *>(arg1->expression)->value;
+                        if (arg2) comment = AST::cast<AST::StringLiteral *>(arg2->expression)->value;
+                        if (arg3) n = (int)AST::cast<AST::NumericLiteral *>(arg3->expression)->value;
+
+                        TrBindingReference *reference = pool->New<TrBindingReference>();
+                        reference->dataType = BindingReference::Tr;
+                        reference->text = text;
+                        reference->comment = comment;
+                        reference->n = n;
+                        v->bindingReference = reference;
+                        return true;
+                    }
+
+                }
+            }
+        }
+
+    }
+
+    return false;
+}
+
 void QDeclarativeCompiler::genBindingAssignment(QDeclarativeScript::Value *binding,
                                                 QDeclarativeScript::Property *prop,
                                                 QDeclarativeScript::Object *obj,
@@ -3210,11 +3438,31 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeScript::Value *bindi
     Q_ASSERT(binding->bindingReference);
 
     const BindingReference &ref = *binding->bindingReference;
-    if (ref.dataType == BindingReference::V4) {
+    if (ref.dataType == BindingReference::TrId) {
+        const TrBindingReference &tr = static_cast<const TrBindingReference &>(ref);
+
+        Instruction::StoreTrIdString store;
+        store.propertyIndex = prop->core.coreIndex;
+        store.text = output->indexForByteArray(tr.text.toUtf8());
+        store.n = tr.n;
+        output->addInstruction(store);
+    } else if (ref.dataType == BindingReference::Tr) {
+        const TrBindingReference &tr = static_cast<const TrBindingReference &>(ref);
+
+        Instruction::StoreTrString store;
+        store.propertyIndex = prop->core.coreIndex;
+        store.context = translationContextIndex();
+        store.text = output->indexForByteArray(tr.text.toUtf8());
+        store.comment = output->indexForByteArray(tr.comment.toUtf8());
+        store.n = tr.n;
+        output->addInstruction(store);
+    } else if (ref.dataType == BindingReference::V4) {
+        const JSBindingReference &js = static_cast<const JSBindingReference &>(ref);
+
         Instruction::StoreV4Binding store;
-        store.value = ref.compiledIndex;
-        store.context = ref.bindingContext.stack;
-        store.owner = ref.bindingContext.owner;
+        store.value = js.compiledIndex;
+        store.context = js.bindingContext.stack;
+        store.owner = js.bindingContext.owner;
         if (valueTypeProperty) {
             store.property = (valueTypeProperty->index & 0xFFFF) |
                              ((valueTypeProperty->type & 0xFF)) << 16 |
@@ -3225,34 +3473,41 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeScript::Value *bindi
             store.isRoot = (compileState->root == obj);
         }
         store.line = binding->location.start.line;
+        store.column = binding->location.start.column;
         output->addInstruction(store);
     } else if (ref.dataType == BindingReference::V8) {
+        const JSBindingReference &js = static_cast<const JSBindingReference &>(ref);
+
         Instruction::StoreV8Binding store;
-        store.value = ref.compiledIndex;
-        store.context = ref.bindingContext.stack;
-        store.owner = ref.bindingContext.owner;
+        store.value = js.compiledIndex;
+        store.context = js.bindingContext.stack;
+        store.owner = js.bindingContext.owner;
         if (valueTypeProperty) {
             store.isRoot = (compileState->root == valueTypeProperty->parent);
         } else {
             store.isRoot = (compileState->root == obj);
         }
         store.line = binding->location.start.line;
+        store.column = binding->location.start.column;
 
-        Q_ASSERT(ref.bindingContext.owner == 0 ||
-                 (ref.bindingContext.owner != 0 && valueTypeProperty));
-        if (ref.bindingContext.owner) {
+        Q_ASSERT(js.bindingContext.owner == 0 ||
+                 (js.bindingContext.owner != 0 && valueTypeProperty));
+        if (js.bindingContext.owner) {
             store.property = genValueTypeData(prop, valueTypeProperty);
         } else {
             store.property = prop->core;
         }
 
         output->addInstruction(store);
-    } else {
+    } else if (ref.dataType == BindingReference::QtScript) {
+        const JSBindingReference &js = static_cast<const JSBindingReference &>(ref);
+
         QDeclarativeInstruction store;
-        store.assignBinding.value = output->indexForString(ref.rewrittenExpression);
-        store.assignBinding.context = ref.bindingContext.stack;
-        store.assignBinding.owner = ref.bindingContext.owner;
+        store.assignBinding.value = output->indexForString(js.rewrittenExpression);
+        store.assignBinding.context = js.bindingContext.stack;
+        store.assignBinding.owner = js.bindingContext.owner;
         store.assignBinding.line = binding->location.start.line;
+        store.assignBinding.column = binding->location.start.column;
 
         if (valueTypeProperty) {
             store.assignBinding.isRoot = (compileState->root == valueTypeProperty->parent);
@@ -3260,9 +3515,9 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeScript::Value *bindi
             store.assignBinding.isRoot = (compileState->root == obj);
         }
 
-        Q_ASSERT(ref.bindingContext.owner == 0 ||
-                 (ref.bindingContext.owner != 0 && valueTypeProperty));
-        if (ref.bindingContext.owner) {
+        Q_ASSERT(js.bindingContext.owner == 0 ||
+                 (js.bindingContext.owner != 0 && valueTypeProperty));
+        if (js.bindingContext.owner) {
             store.assignBinding.property = genValueTypeData(prop, valueTypeProperty);
         } else {
             store.assignBinding.property = prop->core;
@@ -3271,6 +3526,8 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeScript::Value *bindi
             !prop->isAlias ? QDeclarativeInstruction::StoreBinding
                            : QDeclarativeInstruction::StoreBindingOnAlias
             , store);
+    } else {
+        Q_ASSERT(!"Unhandled BindingReference::DataType type");
     }
 }
 
@@ -3314,11 +3571,11 @@ bool QDeclarativeCompiler::completeComponentBuild()
 
     QV4Compiler bindingCompiler;
 
-    QList<BindingReference*> sharedBindings;
+    QList<JSBindingReference*> sharedBindings;
 
-    for (BindingReference *b = compileState->bindings.first(); b; b = b->nextReference) {
+    for (JSBindingReference *b = compileState->bindings.first(); b; b = b->nextReference) {
 
-        BindingReference &binding = *b;
+        JSBindingReference &binding = *b;
 
         // ### We don't currently optimize for bindings on alias's - because 
         // of the solution to QTBUG-13719
@@ -3359,7 +3616,7 @@ bool QDeclarativeCompiler::completeComponentBuild()
 
     if (!sharedBindings.isEmpty()) {
         struct Sort {
-            static bool lt(const BindingReference *lhs, const BindingReference *rhs)
+            static bool lt(const JSBindingReference *lhs, const JSBindingReference *rhs)
             {
                 return lhs->value->location.start.line < rhs->value->location.start.line;
             }
@@ -3372,7 +3629,7 @@ bool QDeclarativeCompiler::completeComponentBuild()
 
         QString functionArray(QLatin1String("["));
         for (int ii = 0; ii < sharedBindings.count(); ++ii) {
-            BindingReference *reference = sharedBindings.at(ii);
+            JSBindingReference *reference = sharedBindings.at(ii);
             QDeclarativeScript::Value *value = reference->value;
             const QString &expression = reference->rewrittenExpression;
 
@@ -3384,6 +3641,7 @@ bool QDeclarativeCompiler::completeComponentBuild()
             }
 
             functionArray += expression;
+            lineNumber += expression.count(QLatin1Char('\n'));
             reference->compiledIndex = ii;
         }
         functionArray += QLatin1String("]");