/****************************************************************************
**
-** 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.
**
**
**
**
+**
** $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;
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>();
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
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();
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))));
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.
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;
{
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);
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());
this->engine = 0;
this->enginePrivate = 0;
this->unit = 0;
+ this->cachedComponentTypeRef = -1;
+ this->cachedTranslationContextIndex = -1;
this->unitRoot = 0;
return !isError();
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())
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);
}
store.value = output->indexForString(rewrite);
store.context = v->signalExpressionContextStack;
store.line = v->location.start.line;
+ store.column = v->location.start.column;
output->addInstruction(store);
}
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,
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;
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;
}
}
- 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;
// 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)
{
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)) {
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" },
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 ||
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);
}
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();
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) {
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;
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,
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 |
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);
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;
!prop->isAlias ? QDeclarativeInstruction::StoreBinding
: QDeclarativeInstruction::StoreBindingOnAlias
, store);
+ } else {
+ Q_ASSERT(!"Unhandled BindingReference::DataType type");
}
}
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
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;
}
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;
}
functionArray += expression;
+ lineNumber += expression.count(QLatin1Char('\n'));
reference->compiledIndex = ii;
}
functionArray += QLatin1String("]");