aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-03-06 16:55:09 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-07 15:33:19 +0100
commit99efe4309379482fce5c231885883e359bf85290 (patch)
treedbb9333a547fa1939bd63bd64136611e9fe82968 /src/qml
parent9fc17c08e5635cf112c6194e6c24af2a9c7caf00 (diff)
Remove old compiler and VME
This removes the bulk of the code. A few smaller cleanups remain, to be done in smaller changes as they move code around. Additionally the "optimize" option of qqmlbundle was removed. It called QQmlScript::Parser::preparseData, which however was not implemented and always returned an empty QByteArray. Therefore "optimize" would not do anything and the class is gone now :) Change-Id: I0c265e756704cb53c5250be1f69e4a3e1b6e64d5 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/qml/qml.pri4
-rw-r--r--src/qml/qml/qqmlcompileddata.cpp102
-rw-r--r--src/qml/qml/qqmlcompiler.cpp3922
-rw-r--r--src/qml/qml/qqmlcompiler_p.h348
-rw-r--r--src/qml/qml/qqmlcomponent.cpp51
-rw-r--r--src/qml/qml/qqmlcomponent_p.h4
-rw-r--r--src/qml/qml/qqmlcustomparser.cpp189
-rw-r--r--src/qml/qml/qqmlcustomparser_p.h60
-rw-r--r--src/qml/qml/qqmlcustomparser_p_p.h89
-rw-r--r--src/qml/qml/qqmlengine.cpp6
-rw-r--r--src/qml/qml/qqmlengine_p.h5
-rw-r--r--src/qml/qml/qqmlincubator.cpp28
-rw-r--r--src/qml/qml/qqmlincubator_p.h4
-rw-r--r--src/qml/qml/qqmlinstruction.cpp283
-rw-r--r--src/qml/qml/qqmlinstruction_p.h560
-rw-r--r--src/qml/qml/qqmlscript.cpp1415
-rw-r--r--src/qml/qml/qqmlscript_p.h365
-rw-r--r--src/qml/qml/qqmlstringconverters.cpp1
-rw-r--r--src/qml/qml/qqmltypeloader.cpp113
-rw-r--r--src/qml/qml/qqmltypeloader_p.h15
-rw-r--r--src/qml/qml/qqmlvme.cpp1217
-rw-r--r--src/qml/qml/qqmlvme_p.h57
-rw-r--r--src/qml/types/qqmlconnections.cpp48
-rw-r--r--src/qml/types/qqmlconnections_p.h1
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp12
-rw-r--r--src/qml/types/qqmllistmodel.cpp191
-rw-r--r--src/qml/types/qqmllistmodel_p.h11
27 files changed, 83 insertions, 9018 deletions
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index 3bba6f8e83..33d8be37d1 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -1,5 +1,4 @@
SOURCES += \
- $$PWD/qqmlinstruction.cpp \
$$PWD/qqmlopenmetaobject.cpp \
$$PWD/qqmlvmemetaobject.cpp \
$$PWD/qqmlengine.cpp \
@@ -13,7 +12,6 @@ SOURCES += \
$$PWD/qqmlpropertyvalueinterceptor.cpp \
$$PWD/qqmlproxymetaobject.cpp \
$$PWD/qqmlvme.cpp \
- $$PWD/qqmlcompiler.cpp \
$$PWD/qqmlcompileddata.cpp \
$$PWD/qqmlboundsignal.cpp \
$$PWD/qqmlmetatype.cpp \
@@ -60,7 +58,6 @@ SOURCES += \
HEADERS += \
$$PWD/qqmlglobal_p.h \
- $$PWD/qqmlinstruction_p.h \
$$PWD/qqmlopenmetaobject_p.h \
$$PWD/qqmlvmemetaobject_p.h \
$$PWD/qqml.h \
@@ -70,7 +67,6 @@ HEADERS += \
$$PWD/qqmlincubator.h \
$$PWD/qqmlincubator_p.h \
$$PWD/qqmlcustomparser_p.h \
- $$PWD/qqmlcustomparser_p_p.h \
$$PWD/qqmlpropertyvaluesource.h \
$$PWD/qqmlpropertyvalueinterceptor_p.h \
$$PWD/qqmlboundsignal_p.h \
diff --git a/src/qml/qml/qqmlcompileddata.cpp b/src/qml/qml/qqmlcompileddata.cpp
index d20215c78a..59c56bf513 100644
--- a/src/qml/qml/qqmlcompileddata.cpp
+++ b/src/qml/qml/qqmlcompileddata.cpp
@@ -56,36 +56,6 @@
QT_BEGIN_NAMESPACE
-int QQmlCompiledData::indexForString(const QString &data)
-{
- int idx = primitives.indexOf(data);
- if (idx == -1) {
- idx = primitives.count();
- primitives << data;
- }
- return idx;
-}
-
-int QQmlCompiledData::indexForByteArray(const QByteArray &data)
-{
- int idx = datas.indexOf(data);
- if (idx == -1) {
- idx = datas.count();
- datas << data;
- }
- return idx;
-}
-
-int QQmlCompiledData::indexForUrl(const QUrl &data)
-{
- int idx = urls.indexOf(data);
- if (idx == -1) {
- idx = urls.count();
- urls << data;
- }
- return idx;
-}
-
QQmlCompiledData::QQmlCompiledData(QQmlEngine *engine)
: engine(engine), importCache(0), metaTypeId(-1), listMetaTypeId(-1), isRegisteredWithEngine(false),
rootPropertyCache(0), compilationUnit(0), qmlUnit(0), totalBindingsCount(0), totalParserStatusCount(0)
@@ -110,13 +80,6 @@ QQmlCompiledData::~QQmlCompiledData()
clear();
- for (int ii = 0; ii < types.count(); ++ii) {
- if (types.at(ii).component)
- types.at(ii).component->release();
- if (types.at(ii).typePropertyCache)
- types.at(ii).typePropertyCache->release();
- }
-
for (QHash<int, TypeReference*>::Iterator resolvedType = resolvedTypes.begin(), end = resolvedTypes.end();
resolvedType != end; ++resolvedType) {
if ((*resolvedType)->component)
@@ -199,71 +162,6 @@ void QQmlCompiledData::TypeReference::doDynamicTypeCheck()
isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
}
-void QQmlCompiledData::dumpInstructions()
-{
- if (!name.isEmpty())
- qWarning() << name;
- qWarning().nospace() << "Index\tOperation\t\tData1\tData2\tData3\tComments";
- qWarning().nospace() << "-------------------------------------------------------------------------------";
-
- const char *instructionStream = bytecode.constData();
- const char *endInstructionStream = bytecode.constData() + bytecode.size();
-
- int instructionCount = 0;
- while (instructionStream < endInstructionStream) {
- QQmlInstruction *instr = (QQmlInstruction *)instructionStream;
- dump(instr, instructionCount);
- instructionStream += QQmlInstruction::size(instructionType(instr));
- instructionCount++;
- }
-
- qWarning().nospace() << "-------------------------------------------------------------------------------";
-}
-
-int QQmlCompiledData::addInstructionHelper(QQmlInstruction::Type type, QQmlInstruction &instr)
-{
-#ifdef QML_THREADED_VME_INTERPRETER
- instr.common.code = QQmlVME::instructionJumpTable()[static_cast<int>(type)];
-#else
- instr.common.instructionType = type;
-#endif
- int ptrOffset = bytecode.size();
- int size = QQmlInstruction::size(type);
- if (bytecode.capacity() <= bytecode.size() + size)
- bytecode.reserve(bytecode.size() + size + 512);
- bytecode.append(reinterpret_cast<const char *>(&instr), size);
- return ptrOffset;
-}
-
-int QQmlCompiledData::nextInstructionIndex()
-{
- return bytecode.size();
-}
-
-QQmlInstruction *QQmlCompiledData::instruction(int index)
-{
- return (QQmlInstruction *)(bytecode.constData() + index);
-}
-
-QQmlInstruction::Type QQmlCompiledData::instructionType(const QQmlInstruction *instr)
-{
-#ifdef QML_THREADED_VME_INTERPRETER
- void *const *jumpTable = QQmlVME::instructionJumpTable();
- void *code = instr->common.code;
-
-# define QML_CHECK_INSTR_CODE(I, FMT) \
- if (jumpTable[static_cast<int>(QQmlInstruction::I)] == code) \
- return QQmlInstruction::I;
-
- FOR_EACH_QML_INSTR(QML_CHECK_INSTR_CODE)
- Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid instruction address");
- return static_cast<QQmlInstruction::Type>(0);
-# undef QML_CHECK_INSTR_CODE
-#else
- return static_cast<QQmlInstruction::Type>(instr->common.instructionType);
-#endif
-}
-
void QQmlCompiledData::initialize(QQmlEngine *engine)
{
Q_ASSERT(!hasEngine());
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
deleted file mode 100644
index aefd3018c9..0000000000
--- a/src/qml/qml/qqmlcompiler.cpp
+++ /dev/null
@@ -1,3922 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlcompiler_p.h"
-
-#include "qqmlpropertyvaluesource.h"
-#include "qqmlcomponent.h"
-#include <private/qmetaobjectbuilder_p.h>
-#include "qqmlstringconverters_p.h"
-#include "qqmlengine_p.h"
-#include "qqmlengine.h"
-#include "qqmlcontext.h"
-#include "qqmlmetatype_p.h"
-#include "qqmlcustomparser_p_p.h"
-#include "qqmlcontext_p.h"
-#include "qqmlcomponent_p.h"
-#include <private/qqmljsast_p.h>
-#include <private/qqmljsparser_p.h>
-#include <private/qqmljsmemorypool_p.h>
-#include "qqmlvmemetaobject_p.h"
-#include "qqmlexpression_p.h"
-#include "qqmlproperty_p.h"
-#include "qqmlscriptstring.h"
-#include "qqmlglobal_p.h"
-#include "qqmlbinding_p.h"
-#include "qqmlabstracturlinterceptor.h"
-
-#include <QDebug>
-#include <QPointF>
-#include <QSizeF>
-#include <QRectF>
-#include <QAtomicInt>
-#include <QtCore/qdebug.h>
-#include <QtCore/qdatetime.h>
-#include <QtCore/qvarlengtharray.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 QQmlJS;
-using namespace QQmlScript;
-using namespace QQmlCompilerTypes;
-
-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_module_string(QLatin1String("QML"));
-static QString qsTr_string(QLatin1String("qsTr"));
-static QString qsTrId_string(QLatin1String("qsTrId"));
-
-/*!
- Instantiate a new QQmlCompiler.
-*/
-QQmlCompiler::QQmlCompiler(QQmlPool *pool)
-: compileState(0), pool(pool), output(0), engine(0), enginePrivate(0), unitRoot(0), unit(0), cachedComponentTypeRef(-1),
- cachedTranslationContextIndex(-1), componentStats(0)
-{
- if (compilerStatDump())
- componentStats = pool->New<ComponentStats>();
-}
-
-/*!
- Returns true if the last call to compile() caused errors.
-
- \sa errors()
-*/
-bool QQmlCompiler::isError() const
-{
- return !exceptions.isEmpty();
-}
-
-/*!
- Return the list of errors from the last call to compile(), or an empty list
- if there were no errors.
-*/
-QList<QQmlError> QQmlCompiler::errors() const
-{
- return exceptions;
-}
-
-/*!
- Returns true if \a name refers to an attached property, false otherwise.
-
- Attached property names are those that start with a capital letter.
-*/
-bool QQmlCompiler::isAttachedPropertyName(const QString &name)
-{
- return isAttachedPropertyName(QHashedStringRef(&name));
-}
-
-bool QQmlCompiler::isAttachedPropertyName(const QHashedStringRef &name)
-{
- return !name.isEmpty() && name.at(0).isUpper();
-}
-
-/*!
- Returns true if \a name refers to a signal property, false otherwise.
-
- Signal property names are those that start with "on", followed by a first
- character which is either a capital letter or one or more underscores followed
- by a capital letter, which is then followed by other allowed characters.
-
- Note that although ECMA-262r3 supports dollarsigns and escaped unicode
- character codes in property names, for simplicity and performance reasons
- QML only supports letters, numbers and underscores.
-*/
-bool QQmlCompiler::isSignalPropertyName(const QString &name)
-{
- return isSignalPropertyName(QStringRef(&name));
-}
-
-bool QQmlCompiler::isSignalPropertyName(const QHashedStringRef &name)
-{
- if (name.length() < 3) return false;
- if (!name.startsWith(on_string)) return false;
- int ns = name.length();
- for (int i = 2; i < ns; ++i) {
- const QChar curr = name.at(i);
- if (curr.unicode() == '_') continue;
- if (curr.isUpper()) return true;
- return false;
- }
- return false; // consists solely of underscores - invalid.
-}
-
-/*!
- \macro COMPILE_EXCEPTION
- \internal
- Inserts an error into the QQmlCompiler error list, and returns false
- (failure).
-
- \a token is used to source the error line and column, and \a desc is the
- error itself. \a desc can be an expression that can be piped into QDebug.
-
- For example:
-
- \code
- COMPILE_EXCEPTION(property, tr("Error for property \"%1\"").arg(property->name));
- \endcode
-*/
-#define COMPILE_EXCEPTION_LOCATION(line, column, desc) \
- { \
- QQmlError error; \
- error.setUrl(output->url); \
- 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
- Returns false if \a is false, otherwise does nothing.
-*/
-#define COMPILE_CHECK(a) \
- { \
- if (!a) return false; \
- }
-
-/*!
- Returns true if literal \a v can be assigned to property \a prop, otherwise
- false.
-
- This test corresponds to action taken by genLiteralAssignment(). Any change
- made here, must have a corresponding action in genLiteralAssigment().
-*/
-bool QQmlCompiler::testLiteralAssignment(QQmlScript::Property *prop, QQmlScript::Value *v)
-{
- const QQmlScript::Variant &value = v->value;
-
- if (!prop->core.isWritable() && !prop->isReadOnlyDeclaration)
- COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
-
- if (prop->core.isEnum()) {
- QMetaProperty p = prop->parent->metatype->firstCppMetaObject()->property(prop->index);
- int enumValue;
- bool ok;
- if (p.isFlagType()) {
- enumValue = p.enumerator().keysToValue(value.asString().toUtf8().constData(), &ok);
- } else
- enumValue = p.enumerator().keyToValue(value.asString().toUtf8().constData(), &ok);
-
- if (!ok)
- COMPILE_EXCEPTION(v, tr("Invalid property assignment: unknown enumeration"));
-
- v->value = QQmlScript::Variant((double)enumValue);
- return true;
- }
-
- int type = prop->type;
-
- switch(type) {
- case QMetaType::QVariant:
- break;
- 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();
- if (ok) {
- double n = v->value.asNumber();
- if (double(uint(n)) != n)
- ok = false;
- }
- if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsigned int expected"));
- }
- break;
- case QVariant::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 expected"));
- }
- break;
- case QMetaType::Float:
- if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: number expected"));
- break;
- case QVariant::Double:
- if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: number expected"));
- break;
- case QVariant::Color:
- {
- bool ok;
- QQmlStringConverters::colorFromString(value.asString(), &ok);
- if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: color expected"));
- }
- break;
-#ifndef QT_NO_DATESTRING
- case QVariant::Date:
- {
- bool ok;
- QQmlStringConverters::dateFromString(value.asString(), &ok);
- if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: date expected"));
- }
- break;
- case QVariant::Time:
- {
- bool ok;
- QQmlStringConverters::timeFromString(value.asString(), &ok);
- if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: time expected"));
- }
- break;
- case QVariant::DateTime:
- {
- bool ok;
- QQmlStringConverters::dateTimeFromString(value.asString(), &ok);
- if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: datetime expected"));
- }
- break;
-#endif // QT_NO_DATESTRING
- case QVariant::Point:
- case QVariant::PointF:
- {
- bool ok;
- QQmlStringConverters::pointFFromString(value.asString(), &ok);
- if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: point expected"));
- }
- break;
- case QVariant::Size:
- case QVariant::SizeF:
- {
- bool ok;
- QQmlStringConverters::sizeFFromString(value.asString(), &ok);
- if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: size expected"));
- }
- break;
- case QVariant::Rect:
- case QVariant::RectF:
- {
- bool ok;
- QQmlStringConverters::rectFFromString(value.asString(), &ok);
- if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: rect expected"));
- }
- break;
- case QVariant::Bool:
- {
- if (!v->value.isBoolean()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: boolean expected"));
- }
- break;
- case QVariant::Vector3D:
- {
- QQmlInstruction::instr_storeVector3D::QVector3D v3;
- if (!QQmlStringConverters::createFromString(QMetaType::QVector3D, value.asString(), &v3, sizeof(v3)))
- COMPILE_EXCEPTION(v, tr("Invalid property assignment: 3D vector expected"));
- }
- break;
- case QVariant::Vector4D:
- {
- QQmlInstruction::instr_storeVector4D::QVector4D v4;
- if (!QQmlStringConverters::createFromString(QMetaType::QVector4D, value.asString(), &v4, sizeof(v4)))
- COMPILE_EXCEPTION(v, tr("Invalid property assignment: 4D vector expected"));
- }
- 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;
- } else if (type == qMetaTypeId<QJSValue>()) {
- break;
- }
-
- // otherwise, check for existence of string converter to custom type
- QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(type);
- if (!converter)
- COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QMetaType::typeName(type))));
- }
- break;
- }
- return true;
-}
-
-/*!
- Generate a store instruction for assigning literal \a v to property \a prop.
-
- Any literal assignment that is approved in testLiteralAssignment() must have
- a corresponding action in this method.
-*/
-void QQmlCompiler::genLiteralAssignment(QQmlScript::Property *prop,
- QQmlScript::Value *v)
-{
- if (prop->core.isEnum()) {
- Q_ASSERT(v->value.isNumber());
- // Preresolved value
- int value = (int)v->value.asNumber();
-
- Instruction::StoreInteger instr;
- instr.propertyIndex = prop->index;
- instr.value = value;
- output->addInstruction(instr);
- return;
- }
-
- int type = prop->type;
- switch(type) {
- case QMetaType::QVariant:
- {
- if (v->value.isNumber()) {
- double n = v->value.asNumber();
- if (double(int(n)) == n) {
- if (prop->core.isVarProperty()) {
- Instruction::StoreVarInteger instr;
- instr.propertyIndex = prop->index;
- instr.value = int(n);
- output->addInstruction(instr);
- } else {
- Instruction::StoreVariantInteger instr;
- instr.propertyIndex = prop->index;
- instr.value = int(n);
- output->addInstruction(instr);
- }
- } else {
- if (prop->core.isVarProperty()) {
- Instruction::StoreVarDouble instr;
- instr.propertyIndex = prop->index;
- instr.value = n;
- output->addInstruction(instr);
- } else {
- Instruction::StoreVariantDouble instr;
- instr.propertyIndex = prop->index;
- instr.value = n;
- output->addInstruction(instr);
- }
- }
- } else if (v->value.isBoolean()) {
- if (prop->core.isVarProperty()) {
- Instruction::StoreVarBool instr;
- instr.propertyIndex = prop->index;
- instr.value = v->value.asBoolean();
- output->addInstruction(instr);
- } else {
- Instruction::StoreVariantBool instr;
- instr.propertyIndex = prop->index;
- instr.value = v->value.asBoolean();
- output->addInstruction(instr);
- }
- } else {
- if (prop->core.isVarProperty()) {
- Instruction::StoreVar instr;
- instr.propertyIndex = prop->index;
- instr.value = output->indexForString(v->value.asString());
- output->addInstruction(instr);
- } else {
- Instruction::StoreVariant instr;
- instr.propertyIndex = prop->index;
- instr.value = output->indexForString(v->value.asString());
- output->addInstruction(instr);
- }
- }
- }
- break;
- case QVariant::String:
- {
- Instruction::StoreString instr;
- instr.propertyIndex = prop->index;
- instr.value = output->indexForString(v->value.asString());
- 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;
- instr.propertyIndex = prop->index;
- instr.value = output->indexForByteArray(v->value.asString().toLatin1());
- output->addInstruction(instr);
- }
- break;
- case QVariant::Url:
- {
- Instruction::StoreUrl instr;
- QString string = v->value.asString();
- // Encoded dir-separators defeat QUrl processing - decode them first
- string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
- QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(QUrl(string));
- // Apply URL interceptor
- if (engine->urlInterceptor())
- u = engine->urlInterceptor()->intercept(u,
- QQmlAbstractUrlInterceptor::UrlString);
- instr.propertyIndex = prop->index;
- instr.value = output->indexForUrl(u);
- output->addInstruction(instr);
- }
- break;
- case QVariant::UInt:
- {
- Instruction::StoreInteger instr;
- instr.propertyIndex = prop->index;
- instr.value = uint(v->value.asNumber());
- output->addInstruction(instr);
- }
- break;
- case QVariant::Int:
- {
- Instruction::StoreInteger instr;
- instr.propertyIndex = prop->index;
- instr.value = int(v->value.asNumber());
- output->addInstruction(instr);
- }
- break;
- case QMetaType::Float:
- {
- Instruction::StoreFloat instr;
- instr.propertyIndex = prop->index;
- instr.value = float(v->value.asNumber());
- output->addInstruction(instr);
- }
- break;
- case QVariant::Double:
- {
- Instruction::StoreDouble instr;
- instr.propertyIndex = prop->index;
- instr.value = v->value.asNumber();
- output->addInstruction(instr);
- }
- break;
- case QVariant::Color:
- {
- Instruction::StoreColor instr;
- instr.propertyIndex = prop->index;
- instr.value = QQmlStringConverters::rgbaFromString(v->value.asString());
- output->addInstruction(instr);
- }
- break;
-#ifndef QT_NO_DATESTRING
- case QVariant::Date:
- {
- Instruction::StoreDate instr;
- QDate d = QQmlStringConverters::dateFromString(v->value.asString());
- instr.propertyIndex = prop->index;
- instr.value = d.toJulianDay();
- output->addInstruction(instr);
- }
- break;
- case QVariant::Time:
- {
- Instruction::StoreTime instr;
- QTime time = QQmlStringConverters::timeFromString(v->value.asString());
- instr.propertyIndex = prop->index;
- instr.time = time.msecsSinceStartOfDay();
- output->addInstruction(instr);
- }
- break;
- case QVariant::DateTime:
- {
- Instruction::StoreDateTime instr;
- QDateTime dateTime = QQmlStringConverters::dateTimeFromString(v->value.asString());
- QTime time = dateTime.time();
- instr.propertyIndex = prop->index;
- instr.date = dateTime.date().toJulianDay();
- instr.time = time.msecsSinceStartOfDay();
- output->addInstruction(instr);
- }
- break;
-#endif // QT_NO_DATESTRING
- case QVariant::Point:
- {
- Instruction::StorePoint instr;
- bool ok;
- QPoint point = QQmlStringConverters::pointFFromString(v->value.asString(), &ok).toPoint();
- instr.propertyIndex = prop->index;
- instr.point.xp = point.x();
- instr.point.yp = point.y();
- output->addInstruction(instr);
- }
- break;
- case QVariant::PointF:
- {
- Instruction::StorePointF instr;
- bool ok;
- QPointF point = QQmlStringConverters::pointFFromString(v->value.asString(), &ok);
- instr.propertyIndex = prop->index;
- instr.point.xp = point.x();
- instr.point.yp = point.y();
- output->addInstruction(instr);
- }
- break;
- case QVariant::Size:
- {
- Instruction::StoreSize instr;
- bool ok;
- QSize size = QQmlStringConverters::sizeFFromString(v->value.asString(), &ok).toSize();
- instr.propertyIndex = prop->index;
- instr.size.wd = size.width();
- instr.size.ht = size.height();
- output->addInstruction(instr);
- }
- break;
- case QVariant::SizeF:
- {
- Instruction::StoreSizeF instr;
- bool ok;
- QSizeF size = QQmlStringConverters::sizeFFromString(v->value.asString(), &ok);
- instr.propertyIndex = prop->index;
- instr.size.wd = size.width();
- instr.size.ht = size.height();
- output->addInstruction(instr);
- }
- break;
- case QVariant::Rect:
- {
- Instruction::StoreRect instr;
- bool ok;
- QRect rect = QQmlStringConverters::rectFFromString(v->value.asString(), &ok).toRect();
- instr.propertyIndex = prop->index;
- instr.rect.x1 = rect.left();
- instr.rect.y1 = rect.top();
- instr.rect.x2 = rect.right();
- instr.rect.y2 = rect.bottom();
- output->addInstruction(instr);
- }
- break;
- case QVariant::RectF:
- {
- Instruction::StoreRectF instr;
- bool ok;
- QRectF rect = QQmlStringConverters::rectFFromString(v->value.asString(), &ok);
- instr.propertyIndex = prop->index;
- instr.rect.xp = rect.left();
- instr.rect.yp = rect.top();
- instr.rect.w = rect.width();
- instr.rect.h = rect.height();
- output->addInstruction(instr);
- }
- break;
- case QVariant::Bool:
- {
- Instruction::StoreBool instr;
- bool b = v->value.asBoolean();
- instr.propertyIndex = prop->index;
- instr.value = b;
- output->addInstruction(instr);
- }
- break;
- case QVariant::Vector3D:
- {
- Instruction::StoreVector3D instr;
- instr.propertyIndex = prop->index;
- QQmlStringConverters::createFromString(QMetaType::QVector3D, v->value.asString(), &instr.vector, sizeof(instr.vector));
- output->addInstruction(instr);
- }
- break;
- case QVariant::Vector4D:
- {
- Instruction::StoreVector4D instr;
- instr.propertyIndex = prop->index;
- QQmlStringConverters::createFromString(QMetaType::QVector4D, v->value.asString(), &instr.vector, sizeof(instr.vector));
- 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(QUrl(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;
- } else if (type == qMetaTypeId<QJSValue>()) {
- if (v->value.isBoolean()) {
- Instruction::StoreJSValueBool instr;
- instr.propertyIndex = prop->index;
- instr.value = v->value.asBoolean();
- output->addInstruction(instr);
- } else if (v->value.isNumber()) {
- double n = v->value.asNumber();
- if (double(int(n)) == n) {
- Instruction::StoreJSValueInteger instr;
- instr.propertyIndex = prop->index;
- instr.value = int(n);
- output->addInstruction(instr);
- } else {
- Instruction::StoreJSValueDouble instr;
- instr.propertyIndex = prop->index;
- instr.value = n;
- output->addInstruction(instr);
- }
- } else {
- Instruction::StoreJSValueString 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());
- instr.type = type;
- output->addInstruction(instr);
- }
- break;
- }
-}
-
-/*!
- Resets data by clearing the lists that the QQmlCompiler modifies.
-*/
-void QQmlCompiler::reset(QQmlCompiledData *data)
-{
- data->types.clear();
- data->primitives.clear();
- data->datas.clear();
- data->bytecode.resize(0);
-}
-
-/*!
- Compile \a unit, and store the output in \a out. \a engine is the QQmlEngine
- with which the QQmlCompiledData will be associated.
-
- Returns true on success, false on failure. On failure, the compile errors
- are available from errors().
-
- If the environment variant QML_COMPILER_DUMP is set
- (eg. QML_COMPILER_DUMP=1) the compiled instructions will be dumped to stderr
- on a successful compiler.
-*/
-bool QQmlCompiler::compile(QQmlEngine *engine,
- QQmlTypeData *unit,
- QQmlCompiledData *out)
-{
- exceptions.clear();
-
- Q_ASSERT(out);
- reset(out);
-
- QQmlScript::Object *root = unit->parser().tree();
- Q_ASSERT(root);
-
- this->engine = engine;
- this->enginePrivate = QQmlEnginePrivate::get(engine);
- this->unit = unit;
- this->unitRoot = root;
- this->output = out;
- this->jsModule.reset(new IR::Module(enginePrivate->v4engine()->debugger));
- this->jsModule->isQmlModule = true;
-
- // Compile types
- const QList<QQmlTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes();
- QList<QQmlScript::TypeReference *> referencedTypes = unit->parser().referencedTypes();
-
- for (int ii = 0; ii < resolvedTypes.count(); ++ii) {
- QQmlCompiledData::TypeReference ref;
-
- const QQmlTypeData::TypeReference &tref = resolvedTypes.at(ii);
- QQmlScript::TypeReference *parserRef = referencedTypes.at(ii);
-
- if (tref.typeData) { //QML-based type
- if (tref.type->isCompositeSingleton()) {
- QString err = tr( "Composite Singleton Type %1 is not creatable.").arg(tref.type->qmlTypeName());
- COMPILE_EXCEPTION(parserRef->firstUse, err);
- }
- ref.component = tref.typeData->compiledData();
- ref.component->addref();
- } else if (tref.type) {//C++-based type
- ref.type = tref.type;
- if (!ref.type->isCreatable()) {
- QString err = ref.type->noCreationReason();
- if (err.isEmpty())
- err = tr( "Element is not creatable.");
- COMPILE_EXCEPTION(parserRef->firstUse, err);
- }
-
- if (ref.type->containsRevisionedAttributes()) {
- QQmlError cacheError;
- ref.typePropertyCache = enginePrivate->cache(ref.type,
- resolvedTypes.at(ii).minorVersion,
- cacheError);
- if (!ref.typePropertyCache)
- COMPILE_EXCEPTION(parserRef->firstUse, cacheError.description());
- ref.typePropertyCache->addref();
- }
- }
-
- ref.doDynamicTypeCheck();
-
- out->types << ref;
- }
-
- compileTree(root);
-
- if (!isError()) {
- if (compilerDump())
- out->dumpInstructions();
- if (componentStats)
- dumpStats();
- Q_ASSERT(out->rootPropertyCache);
-
- // Any QQmlPropertyMap instances for example need to have their property cache removed,
- // because the class is too dynamic and allows adding properties at any point at run-time.
- for (int i = 0; i < output->types.count(); ++i) {
- QQmlCompiledData::TypeReference &tr = output->types[i];
- if (!tr.typePropertyCache)
- continue;
-
- if (tr.isFullyDynamicType) {
- tr.typePropertyCache->release();
- tr.typePropertyCache = 0;
- }
- }
- } else {
- reset(out);
- }
-
- compileState = 0;
- output = 0;
- this->engine = 0;
- this->enginePrivate = 0;
- this->unit = 0;
- this->cachedComponentTypeRef = -1;
- this->cachedTranslationContextIndex = -1;
- this->unitRoot = 0;
-
- return !isError();
-}
-
-void QQmlCompiler::compileTree(QQmlScript::Object *tree)
-{
- compileState = pool->New<ComponentCompileState>();
-
- compileState->root = tree;
- if (componentStats)
- componentStats->componentStat.lineNumber = tree->location.start.line;
-
- // 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 QQmlTypeNameCache();
- foreach (const QString &ns, unit->namespaces()) {
- output->importCache->add(ns);
- }
-
- // Add any Composite Singletons that were used to the import cache
- for (int i = 0; i < unit->compositeSingletons().count(); ++i) {
- output->importCache->add(unit->compositeSingletons().at(i).type->qmlTypeName(),
- unit->compositeSingletons().at(i).type->sourceUrl(), unit->compositeSingletons().at(i).prefix);
- }
-
- int scriptIndex = 0;
- foreach (const QQmlTypeData::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);
-
- if (!buildObject(tree, BindingContext()) || !completeComponentBuild())
- return;
-
- if (!jsModule->functions.isEmpty()) {
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
- QV4::Compiler::JSUnitGenerator jsUnitGenerator(jsModule.data());
- QScopedPointer<EvalInstructionSelection> isel(v4->iselFactory->create(enginePrivate, v4->executableAllocator, jsModule.data(), &jsUnitGenerator));
- isel->setUseFastLookups(false);
- QV4::CompiledData::CompilationUnit *jsUnit = isel->compile(/*generated unit data*/true);
- output->compilationUnit = jsUnit;
- output->compilationUnit->ref();
- }
-
- Instruction::Init init;
- init.bindingsSize = compileState->totalBindingsCount;
- init.parserStatusSize = compileState->parserStatusCount;
- init.contextCache = genContextCache();
- init.objectStackSize = compileState->objectDepth.maxDepth();
- init.listStackSize = compileState->listDepth.maxDepth();
- if (compileState->compiledBindingData.isEmpty())
- init.compiledBinding = -1;
- else
- init.compiledBinding = output->indexForByteArray(compileState->compiledBindingData);
- output->addInstruction(init);
-
- foreach (const QQmlTypeData::ScriptReference &script, unit->resolvedScripts()) {
- Instruction::StoreImportedScript import;
- import.value = output->scripts.count();
-
- QQmlScriptData *scriptData = script.script->scriptData();
- scriptData->addref();
- output->scripts << scriptData;
- output->addInstruction(import);
- }
-
- genObject(tree);
-
- Instruction::SetDefault def;
- output->addInstruction(def);
-
- Instruction::Done done;
- output->addInstruction(done);
-
- Q_ASSERT(tree->metatype);
- if (!tree->synthdata.isEmpty()) {
- enginePrivate->registerInternalCompositeType(output);
- } else if (output->types.at(tree->type).component) {
- output->metaTypeId = output->types.at(tree->type).component->metaTypeId;
- output->listMetaTypeId = output->types.at(tree->type).component->listMetaTypeId;
- } else {
- Q_ASSERT(output->types.at(tree->type).type);
- output->metaTypeId = output->types.at(tree->type).type->typeId();
- output->listMetaTypeId = output->types.at(tree->type).type->qListTypeId();
- }
- if (!tree->synthdata.isEmpty())
- enginePrivate->registerInternalCompositeType(output);
-}
-
-static bool QStringList_contains(const QStringList &list, const QHashedStringRef &string)
-{
- for (int ii = 0; ii < list.count(); ++ii)
- if (string == list.at(ii))
- return true;
-
- return false;
-}
-
-bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ctxt)
-{
- if (componentStats)
- componentStats->componentStat.objects++;
-
- Q_ASSERT (obj->type != -1);
- QQmlCompiledData::TypeReference &tr = output->types[obj->type];
- obj->metatype = tr.createPropertyCache(engine);
-
- // This object is a "Component" element.
- if (tr.type && obj->metatype->metaObject() == &QQmlComponent::staticMetaObject) {
- COMPILE_CHECK(buildComponent(obj, ctxt));
- return true;
- }
-
- if (tr.component) {
- typedef QQmlInstruction I;
- const I *init = ((const I *)tr.component->bytecode.constData());
- Q_ASSERT(init && tr.component->instructionType(init) == QQmlInstruction::Init);
-
- // Adjust stack depths to include nested components
- compileState->objectDepth.pushPop(init->init.objectStackSize);
- compileState->listDepth.pushPop(init->init.listStackSize);
- compileState->parserStatusCount += init->init.parserStatusSize;
- compileState->totalBindingsCount += init->init.bindingsSize;
- }
-
- compileState->objectDepth.push();
-
- // Object instantiations reset the binding context
- BindingContext objCtxt(obj);
-
- // Create the synthesized meta object, ignoring aliases
- COMPILE_CHECK(checkDynamicMeta(obj));
- COMPILE_CHECK(mergeDynamicMetaProperties(obj));
- COMPILE_CHECK(buildDynamicMeta(obj, Normal));
-
- // Find the native type and check for the QQmlParserStatus interface
- QQmlType *type = toQmlType(obj);
- Q_ASSERT(type);
- obj->parserStatusCast = type->parserStatusCast();
- if (obj->parserStatusCast != -1)
- compileState->parserStatusCount++;
-
- // Check if this is a custom parser type. Custom parser types allow
- // assignments to non-existent properties. These assignments are then
- // compiled by the type.
- bool isCustomParser = output->types.at(obj->type).type &&
- output->types.at(obj->type).type->customParser() != 0;
- QList<QQmlCustomParserProperty> customProps;
-
- // Fetch the list of deferred properties
- QStringList deferredList = deferredProperties(obj);
-
- // Must do id property first. This is to ensure that the id given to any
- // id reference created matches the order in which the objects are
- // instantiated
- for (QQmlScript::Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
- if (prop->name() == id_string) {
- COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
- break;
- }
- }
-
- // Merge
- QQmlScript::Property *defaultProperty = 0;
- QQmlScript::Property *skipProperty = 0;
- if (obj->defaultProperty) {
- defaultProperty = obj->defaultProperty;
-
- QQmlScript::Property *explicitProperty = 0;
-
- QString defaultPropertyName = obj->metatype->defaultPropertyName();
- if (!defaultPropertyName.isEmpty()) {
- QString *s = pool->NewString(defaultPropertyName);
- QHashedStringRef r(*s);
-
- if (obj->propertiesHashField.test(r.hash())) {
- for (QQmlScript::Property *ep = obj->properties.first(); ep; ep = obj->properties.next(ep)) {
- if (ep->name() == r) {
- explicitProperty = ep;
- break;
- }
- }
- }
-
- if (!explicitProperty)
- defaultProperty->setName(r);
- }
-
- if (explicitProperty && !explicitProperty->value && !explicitProperty->values.isEmpty()) {
-
- skipProperty = explicitProperty; // We merge the values into defaultProperty
-
- // Find the correct insertion point
- QQmlScript::Value *insertPos = 0;
-
- for (QQmlScript::Value *v = defaultProperty->values.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
- if (!(v->location.start < explicitProperty->values.first()->location.start))
- break;
- insertPos = v;
- }
-
- defaultProperty->values.insertAfter(insertPos, explicitProperty->values);
- }
- }
-
- QQmlCustomParser *cp = 0;
- if (isCustomParser)
- cp = output->types.at(obj->type).type->customParser();
-
- // Build all explicit properties specified
- for (QQmlScript::Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
-
- if (prop == skipProperty)
- continue;
- if (prop->name() == id_string)
- continue;
-
- bool canDefer = false;
- if (isCustomParser) {
- if (doesPropertyExist(prop, obj) &&
- (!(cp->flags() & QQmlCustomParser::AcceptsAttachedProperties) ||
- !isAttachedPropertyName(prop->name()))) {
- int ids = compileState->ids.count();
- COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
- canDefer = ids == compileState->ids.count();
- } else if (isSignalPropertyName(prop->name()) &&
- (cp->flags() & QQmlCustomParser::AcceptsSignalHandlers)) {
- COMPILE_CHECK(buildSignal(prop,obj,objCtxt));
- } else {
- customProps << QQmlCustomParserNodePrivate::fromProperty(prop);
- }
- } else {
- if (isSignalPropertyName(prop->name())) {
- COMPILE_CHECK(buildSignal(prop,obj,objCtxt));
- } else {
- int ids = compileState->ids.count();
- COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
- canDefer = ids == compileState->ids.count();
- }
- }
-
- if (canDefer && !deferredList.isEmpty() && QStringList_contains(deferredList, prop->name()))
- prop->isDeferred = true;
-
- }
-
- // Build the default property
- if (defaultProperty) {
- QQmlScript::Property *prop = defaultProperty;
-
- bool canDefer = false;
- if (isCustomParser) {
- if (doesPropertyExist(prop, obj)) {
- int ids = compileState->ids.count();
- COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
- canDefer = ids == compileState->ids.count();
- } else {
- customProps << QQmlCustomParserNodePrivate::fromProperty(prop);
- }
- } else {
- int ids = compileState->ids.count();
- COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
- canDefer = ids == compileState->ids.count();
- }
-
- if (canDefer && !deferredList.isEmpty() && QStringList_contains(deferredList, prop->name()))
- prop->isDeferred = true;
- }
-
- // Compile custom parser parts
- if (isCustomParser && !customProps.isEmpty()) {
- cp->clearErrors();
- cp->compiler = this;
- cp->object = obj;
- obj->custom = cp->compile(customProps);
- cp->compiler = 0;
- cp->object = 0;
- foreach (QQmlError err, cp->errors()) {
- err.setUrl(output->url);
- exceptions << err;
- }
- }
-
- compileState->objectDepth.pop();
-
- return true;
-}
-
-void QQmlCompiler::genObject(QQmlScript::Object *obj, bool parentToSuper)
-{
- QQmlCompiledData::TypeReference &tr = output->types[obj->type];
- if (tr.type && obj->metatype->metaObject() == &QQmlComponent::staticMetaObject) {
- genComponent(obj);
- return;
- }
-
- // Create the object
- if (obj->custom.isEmpty() && output->types.at(obj->type).type &&
- !output->types.at(obj->type).type->isExtendedType() && obj != compileState->root) {
-
- Instruction::CreateSimpleObject create;
- create.create = output->types.at(obj->type).type->createFunction();
- create.typeSize = output->types.at(obj->type).type->createSize();
- create.type = obj->type;
- create.line = obj->location.start.line;
- create.column = obj->location.start.column;
- create.parentToSuper = parentToSuper;
- output->addInstruction(create);
-
- } else {
-
- if (output->types.at(obj->type).type) {
- Instruction::CreateCppObject create;
- create.line = obj->location.start.line;
- create.column = obj->location.start.column;
- create.data = -1;
- if (!obj->custom.isEmpty())
- create.data = output->indexForByteArray(obj->custom);
- create.type = obj->type;
- create.isRoot = (compileState->root == obj);
- create.parentToSuper = parentToSuper;
- output->addInstruction(create);
- } else {
- Instruction::CreateQMLObject create;
- create.type = obj->type;
- create.isRoot = (compileState->root == obj);
-
- if (!obj->bindingBitmask.isEmpty()) {
- Q_ASSERT(obj->bindingBitmask.size() % 4 == 0);
- create.bindingBits = output->indexForByteArray(obj->bindingBitmask);
- } else {
- create.bindingBits = -1;
- }
- output->addInstruction(create);
-
- Instruction::CompleteQMLObject complete;
- complete.line = obj->location.start.line;
- complete.column = obj->location.start.column;
- complete.isRoot = (compileState->root == obj);
- output->addInstruction(complete);
- }
- }
-
- // Setup the synthesized meta object if necessary
- if (!obj->synthdata.isEmpty()) {
- Q_ASSERT(!output->types.at(obj->type).isFullyDynamicType);
- Instruction::StoreMetaObject meta;
- meta.aliasData = output->indexForByteArray(obj->synthdata);
- meta.propertyCache = output->propertyCaches.count();
-
- QQmlPropertyCache *propertyCache = obj->synthCache;
- Q_ASSERT(propertyCache);
- propertyCache->addref();
-
- if (obj == unitRoot) {
- propertyCache->addref();
- output->rootPropertyCache = propertyCache;
- }
-
- output->propertyCaches << propertyCache;
- output->addInstruction(meta);
- } else if (obj == unitRoot) {
- output->rootPropertyCache = tr.createPropertyCache(engine);
- output->rootPropertyCache->addref();
- }
-
- // Set the object id
- if (!obj->id.isEmpty()) {
- Instruction::SetId id;
- id.value = output->indexForString(obj->id);
- id.index = obj->idIndex;
- output->addInstruction(id);
- }
-
- // Begin the class
- if (tr.type && obj->parserStatusCast != -1) {
- Instruction::BeginObject begin;
- begin.castValue = obj->parserStatusCast;
- output->addInstruction(begin);
- }
-
- genObjectBody(obj);
-}
-
-void QQmlCompiler::genObjectBody(QQmlScript::Object *obj)
-{
- for (QQmlScript::Property *prop = obj->scriptStringProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
- Q_ASSERT(prop->scriptStringScope != -1);
- const QString &script = prop->values.first()->value.asScript();
- Instruction::StoreScriptString ss;
- ss.propertyIndex = prop->index;
- ss.value = output->indexForString(script);
- ss.scope = prop->scriptStringScope;
- ss.bindingId = output->indexForString(prop->values.first()->value.asScript());
- ss.line = prop->location.start.line;
- ss.column = prop->location.start.column;
- ss.isStringLiteral = prop->values.first()->value.isString();
- ss.isNumberLiteral = prop->values.first()->value.isNumber();
- ss.numberValue = prop->values.first()->value.asNumber();
- output->addInstruction(ss);
- }
-
- bool seenDefer = false;
- for (QQmlScript::Property *prop = obj->valueProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
- if (prop->isDeferred) {
- seenDefer = true;
- continue;
- }
- if (!prop->isAlias)
- genValueProperty(prop, obj);
- }
- if (seenDefer) {
- Instruction::Defer defer;
- defer.deferCount = 0;
- int deferIdx = output->addInstruction(defer);
- int nextInstructionIndex = output->nextInstructionIndex();
-
- Instruction::DeferInit dinit;
- // XXX - these are now massive over allocations
- dinit.bindingsSize = compileState->totalBindingsCount;
- dinit.parserStatusSize = compileState->parserStatusCount;
- dinit.objectStackSize = compileState->objectDepth.maxDepth();
- dinit.listStackSize = compileState->listDepth.maxDepth();
- output->addInstruction(dinit);
-
- for (QQmlScript::Property *prop = obj->valueProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
- if (!prop->isDeferred)
- continue;
- genValueProperty(prop, obj);
- }
-
- Instruction::Done done;
- output->addInstruction(done);
-
- output->instruction(deferIdx)->defer.deferCount = output->nextInstructionIndex() - nextInstructionIndex;
- }
-
- for (QQmlScript::Property *prop = obj->signalProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
-
- QQmlScript::Value *v = prop->values.first();
-
- if (v->type == QQmlScript::Value::SignalObject) {
-
- genObject(v->object);
-
- Instruction::AssignSignalObject assign;
- assign.line = v->location.start.line;
- assign.column = v->location.start.column;
- assign.signal = output->indexForString(prop->name().toString());
- output->addInstruction(assign);
-
- } else if (v->type == QQmlScript::Value::SignalExpression) {
-
- Instruction::StoreSignal store;
- store.runtimeFunctionIndex = compileState->jsCompileData[v->signalData.signalScopeObject].runtimeFunctionIndices.at(v->signalData.functionIndex);
- store.handlerName = output->indexForString(prop->name().toString());
- store.parameters = output->indexForString(obj->metatype->signalParameterStringForJS(prop->index));
- store.signalIndex = prop->index;
- store.value = output->indexForString(v->value.asScript());
- store.context = v->signalData.signalExpressionContextStack;
- store.line = v->location.start.line;
- store.column = v->location.start.column;
- output->addInstruction(store);
-
- }
-
- }
-
- for (QQmlScript::Property *prop = obj->attachedProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
- Instruction::FetchAttached fetch;
- fetch.id = prop->index;
- fetch.line = prop->location.start.line;
- output->addInstruction(fetch);
-
- genObjectBody(prop->value);
-
- Instruction::PopFetchedObject pop;
- output->addInstruction(pop);
- }
-
- for (QQmlScript::Property *prop = obj->groupedProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
- Instruction::FetchObject fetch;
- fetch.property = prop->index;
- fetch.line = prop->location.start.line;
- fetch.column = prop->location.start.column;
- output->addInstruction(fetch);
-
- if (!prop->value->synthdata.isEmpty()) {
- Instruction::StoreMetaObject meta;
- meta.aliasData = output->indexForByteArray(prop->value->synthdata);
- meta.propertyCache = output->propertyCaches.count();
- QQmlPropertyCache *propertyCache = prop->value->synthCache;
- Q_ASSERT(propertyCache);
- propertyCache->addref();
- output->propertyCaches << propertyCache;
- output->addInstruction(meta);
- }
-
- genObjectBody(prop->value);
-
- Instruction::PopFetchedObject pop;
- output->addInstruction(pop);
- }
-
- for (QQmlScript::Property *prop = obj->valueTypeProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
- if (!prop->isAlias)
- genValueTypeProperty(obj, prop);
- }
-
- for (QQmlScript::Property *prop = obj->valueProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
- if (prop->isDeferred)
- continue;
- if (prop->isAlias)
- genValueProperty(prop, obj);
- }
-
- for (QQmlScript::Property *prop = obj->valueTypeProperties.first(); prop; prop = QQmlScript::Object::PropertyList::next(prop)) {
- if (prop->isAlias)
- genValueTypeProperty(obj, prop);
- }
-}
-
-void QQmlCompiler::genValueTypeProperty(QQmlScript::Object *obj, QQmlScript::Property *prop)
-{
- Instruction::FetchValueType fetch;
- fetch.property = prop->index;
- fetch.type = prop->type;
- fetch.bindingSkipList = 0;
-
- if (obj->type == -1 || output->types.at(obj->type).component) {
- // We only have to do this if this is a composite type. If it is a builtin
- // type it can't possibly already have bindings that need to be cleared.
- for (QQmlScript::Property *vprop = prop->value->valueProperties.first(); vprop; vprop = QQmlScript::Object::PropertyList::next(vprop)) {
- if (!vprop->values.isEmpty()) {
- Q_ASSERT(vprop->index >= 0 && vprop->index < 32);
- fetch.bindingSkipList |= (1 << vprop->index);
- }
- }
- }
-
- output->addInstruction(fetch);
-
- for (QQmlScript::Property *vprop = prop->value->valueProperties.first(); vprop; vprop = QQmlScript::Object::PropertyList::next(vprop)) {
- genPropertyAssignment(vprop, prop->value, prop);
- }
-
- Instruction::PopValueType pop;
- pop.property = prop->index;
- pop.type = prop->type;
- pop.bindingSkipList = 0;
- output->addInstruction(pop);
-
- genPropertyAssignment(prop, obj);
-}
-
-void QQmlCompiler::genComponent(QQmlScript::Object *obj)
-{
- QQmlScript::Object *root = obj->defaultProperty->values.first()->object;
- Q_ASSERT(root);
-
- Instruction::CreateComponent create;
- create.line = root->location.start.line;
- create.column = root->location.start.column;
- create.endLine = root->location.end.line;
- create.isRoot = (compileState->root == obj);
- int createInstruction = output->addInstruction(create);
- int nextInstructionIndex = output->nextInstructionIndex();
-
- ComponentCompileState *oldCompileState = compileState;
- compileState = componentState(root);
-
- Instruction::Init init;
- init.bindingsSize = compileState->totalBindingsCount;
- init.parserStatusSize = compileState->parserStatusCount;
- init.contextCache = genContextCache();
- init.objectStackSize = compileState->objectDepth.maxDepth();
- init.listStackSize = compileState->listDepth.maxDepth();
- if (compileState->compiledBindingData.isEmpty())
- init.compiledBinding = -1;
- else
- init.compiledBinding = output->indexForByteArray(compileState->compiledBindingData);
- output->addInstruction(init);
-
- genObject(root);
-
- Instruction::SetDefault def;
- output->addInstruction(def);
-
- Instruction::Done done;
- output->addInstruction(done);
-
- output->instruction(createInstruction)->createComponent.count =
- output->nextInstructionIndex() - nextInstructionIndex;
-
- compileState = oldCompileState;
-
- if (!obj->id.isEmpty()) {
- Instruction::SetId id;
- id.value = output->indexForString(obj->id);
- id.index = obj->idIndex;
- output->addInstruction(id);
- }
-
- if (obj == unitRoot) {
- output->rootPropertyCache = output->types[obj->type].createPropertyCache(engine);
- output->rootPropertyCache->addref();
- }
-}
-
-bool QQmlCompiler::buildComponent(QQmlScript::Object *obj,
- const BindingContext &ctxt)
-{
- // The special "Component" element can only have the id property and a
- // default property, that actually defines the component's tree
-
- compileState->objectDepth.push();
-
- // Find, check and set the "id" property (if any)
- QQmlScript::Property *idProp = 0;
- if (obj->properties.isMany() ||
- (obj->properties.isOne() && obj->properties.first()->name() != id_string))
- COMPILE_EXCEPTION(obj->properties.first(), tr("Component elements may not contain properties other than id"));
-
- if (!obj->properties.isEmpty())
- idProp = obj->properties.first();
-
- if (idProp) {
- if (idProp->value || idProp->values.isMany() || idProp->values.first()->object)
- COMPILE_EXCEPTION(idProp, tr("Invalid component id specification"));
- COMPILE_CHECK(checkValidId(idProp->values.first(), idProp->values.first()->primitive()))
-
- QString idVal = idProp->values.first()->primitive();
-
- if (compileState->ids.value(idVal))
- COMPILE_EXCEPTION(idProp, tr("id is not unique"));
-
- obj->id = idVal;
- addId(idVal, obj);
- }
-
- // Check the Component tree is well formed
- if (obj->defaultProperty &&
- (obj->defaultProperty->value || obj->defaultProperty->values.isMany() ||
- (obj->defaultProperty->values.isOne() && !obj->defaultProperty->values.first()->object)))
- COMPILE_EXCEPTION(obj, tr("Invalid component body specification"));
-
- if (!obj->dynamicProperties.isEmpty())
- COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new properties."));
- if (!obj->dynamicSignals.isEmpty())
- COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new signals."));
- if (!obj->dynamicSlots.isEmpty())
- COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new functions."));
-
- QQmlScript::Object *root = 0;
- if (obj->defaultProperty && !obj->defaultProperty->values.isEmpty())
- root = obj->defaultProperty->values.first()->object;
-
- if (!root)
- COMPILE_EXCEPTION(obj, tr("Cannot create empty component specification"));
-
- // Build the component tree
- COMPILE_CHECK(buildComponentFromRoot(root, ctxt));
-
- compileState->objectDepth.pop();
-
- return true;
-}
-
-bool QQmlCompiler::buildComponentFromRoot(QQmlScript::Object *obj,
- const BindingContext &ctxt)
-{
- ComponentCompileState *oldComponentCompileState = compileState;
- compileState = pool->New<ComponentCompileState>();
- compileState->root = obj;
- compileState->nested = true;
-
- if (componentStats) {
- ComponentStat oldComponentStat = componentStats->componentStat;
-
- componentStats->componentStat = ComponentStat();
- componentStats->componentStat.lineNumber = obj->location.start.line;
-
- if (obj)
- COMPILE_CHECK(buildObject(obj, ctxt));
-
- COMPILE_CHECK(completeComponentBuild());
-
- componentStats->componentStat = oldComponentStat;
- } else {
- if (obj)
- COMPILE_CHECK(buildObject(obj, ctxt));
-
- COMPILE_CHECK(completeComponentBuild());
- }
-
- compileState = oldComponentCompileState;
-
- return true;
-}
-
-
-// Build a sub-object. A sub-object is one that was not created directly by
-// QML - such as a grouped property object, or an attached object. Sub-object's
-// can't have an id, involve a custom parser, have attached properties etc.
-bool QQmlCompiler::buildSubObject(QQmlScript::Object *obj, const BindingContext &ctxt)
-{
- Q_ASSERT(obj->metatype);
- Q_ASSERT(!obj->defaultProperty);
- Q_ASSERT(ctxt.isSubContext()); // sub-objects must always be in a binding
- // sub-context
-
- for (QQmlScript::Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
- if (isSignalPropertyName(prop->name())) {
- COMPILE_CHECK(buildSignal(prop, obj, ctxt));
- } else {
- COMPILE_CHECK(buildProperty(prop, obj, ctxt));
- }
- }
-
- return true;
-}
-
-int QQmlCompiler::componentTypeRef()
-{
- if (cachedComponentTypeRef == -1) {
- QQmlType *t = QQmlMetaType::qmlType(Component_string, Component_module_string, 1, 0);
- for (int ii = output->types.count() - 1; ii >= 0; --ii) {
- if (output->types.at(ii).type == t) {
- cachedComponentTypeRef = ii;
- return ii;
- }
- }
- QQmlCompiledData::TypeReference ref;
- ref.type = t;
- output->types << ref;
- cachedComponentTypeRef = output->types.count() - 1;
- }
- return cachedComponentTypeRef;
-}
-
-int QQmlCompiler::translationContextIndex()
-{
- if (cachedTranslationContextIndex == -1) {
- // This code must match that in the qsTr() implementation
- const QString &path = output->name;
- 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);
- }
- return cachedTranslationContextIndex;
-}
-
-static AST::FunctionDeclaration *convertSignalHandlerExpressionToFunctionDeclaration(QQmlJS::Engine *jsEngine,
- AST::Node *node,
- const QString &signalName,
- const QList<QByteArray> &parameters)
-{
- QQmlJS::MemoryPool *pool = jsEngine->pool();
-
- AST::FormalParameterList *paramList = 0;
- foreach (const QByteArray &param, parameters) {
- QStringRef paramNameRef = jsEngine->newStringRef(QString::fromUtf8(param));
-
- if (paramList)
- paramList = new (pool) AST::FormalParameterList(paramList, paramNameRef);
- else
- paramList = new (pool) AST::FormalParameterList(paramNameRef);
- }
-
- if (paramList)
- paramList = paramList->finish();
-
- AST::Statement *statement = node->statementCast();
- if (!statement) {
- AST::ExpressionNode *expr = node->expressionCast();
- Q_ASSERT(expr);
- statement = new (pool) AST::ExpressionStatement(expr);
- }
- AST::SourceElement *sourceElement = new (pool) AST::StatementSourceElement(statement);
- AST::SourceElements *elements = new (pool) AST::SourceElements(sourceElement);
- elements = elements->finish();
-
- AST::FunctionBody *body = new (pool) AST::FunctionBody(elements);
-
- AST::FunctionDeclaration *functionDeclaration = new (pool) AST::FunctionDeclaration(jsEngine->newStringRef(signalName), paramList, body);
- functionDeclaration->functionToken = statement->firstSourceLocation();
- return functionDeclaration;
-}
-
-bool QQmlCompiler::buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj,
- const BindingContext &ctxt)
-{
- Q_ASSERT(obj->metatype);
-
- const QHashedStringRef &propName = prop->name();
-
- Q_ASSERT(propName.startsWith(on_string));
- QString name = propName.mid(2, -1).toString();
-
- // Note that the property name could start with any alpha or '_' or '$' character,
- // so we need to do the lower-casing of the first alpha character.
- for (int firstAlphaIndex = 0; firstAlphaIndex < name.size(); ++firstAlphaIndex) {
- if (name.at(firstAlphaIndex).isUpper()) {
- name[firstAlphaIndex] = name.at(firstAlphaIndex).toLower();
- break;
- }
- }
-
- bool notInRevision = false;
-
- QQmlPropertyData *sig = signal(obj, QStringRef(&name), &notInRevision);
-
- if (sig == 0) {
-
- if (notInRevision && 0 == property(obj, propName, 0)) {
- Q_ASSERT(obj->type != -1);
- const QList<QQmlTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes();
- const QQmlTypeData::TypeReference &type = resolvedTypes.at(obj->type);
- if (type.type) {
- COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(elementName(obj)).arg(prop->name().toString()).arg(type.type->module()).arg(type.majorVersion).arg(type.minorVersion));
- } else {
- COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(elementName(obj)).arg(prop->name().toString()));
- }
- }
-
- // If the "on<Signal>" name doesn't resolve into a signal, try it as a
- // property.
- COMPILE_CHECK(buildProperty(prop, obj, ctxt));
-
- } else {
-
- if (prop->value || !prop->values.isOne())
- COMPILE_EXCEPTION(prop, tr("Incorrectly specified signal assignment"));
-
- prop->index = propertyCacheForObject(obj)->methodIndexToSignalIndex(sig->coreIndex);
- prop->core = *sig;
-
- obj->addSignalProperty(prop);
-
- if (prop->values.first()->object) {
- COMPILE_CHECK(buildObject(prop->values.first()->object, ctxt));
- prop->values.first()->type = QQmlScript::Value::SignalObject;
- } else {
- prop->values.first()->type = QQmlScript::Value::SignalExpression;
-
- if (!prop->values.first()->value.isScript())
- COMPILE_EXCEPTION(prop, tr("Cannot assign a value to a signal (expecting a script to be run)"));
-
- QString script = prop->values.first()->value.asScript().trimmed();
- if (script.isEmpty())
- COMPILE_EXCEPTION(prop, tr("Empty signal assignment"));
-
- //all handlers should be on the original, rather than cloned signals in order
- //to ensure all parameters are available (see qqmlboundsignal constructor for more details)
- prop->index = obj->metatype->originalClone(prop->index);
- prop->values.first()->signalData.signalExpressionContextStack = ctxt.stack;
- prop->values.first()->signalData.signalScopeObject = ctxt.object;
-
- QList<QByteArray> parameters = obj->metatype->signalParameterNames(prop->index);
-
- AST::FunctionDeclaration *funcDecl = convertSignalHandlerExpressionToFunctionDeclaration(unit->parser().jsEngine(), prop->values.first()->value.asAST(), propName.toString(), parameters);
-
- ComponentCompileState::PerObjectCompileData *cd = &compileState->jsCompileData[ctxt.object];
- cd->functionsToCompile.append(funcDecl);
- prop->values.first()->signalData.functionIndex = cd->functionsToCompile.count() - 1;
-
- QString errorString;
- obj->metatype->signalParameterStringForJS(prop->index, &errorString);
- if (!errorString.isEmpty())
- COMPILE_EXCEPTION(prop, errorString);
- }
- }
-
- return true;
-}
-
-
-/*!
- Returns true if (value) property \a prop exists on obj, false otherwise.
-*/
-bool QQmlCompiler::doesPropertyExist(QQmlScript::Property *prop,
- QQmlScript::Object *obj)
-{
- if (prop->name().isEmpty())
- return false;
- if(isAttachedPropertyName(prop->name()) || prop->name() == id_string)
- return true;
-
- return property(obj, prop->name()) != 0;
-}
-
-bool QQmlCompiler::buildProperty(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- const BindingContext &ctxt)
-{
- if (prop->isEmpty())
- COMPILE_EXCEPTION(prop, tr("Empty property assignment"));
-
- if (isAttachedPropertyName(prop->name())) {
- // Setup attached property data
-
- if (ctxt.isSubContext()) {
- // Attached properties cannot be used on sub-objects. Sub-objects
- // always exist in a binding sub-context, which is what we test
- // for here.
- COMPILE_EXCEPTION(prop, tr("Attached properties cannot be used here"));
- }
-
- QQmlType *type = 0;
- QQmlImportNamespace *typeNamespace = 0;
- unit->imports().resolveType(prop->name(), &type, 0, 0, &typeNamespace);
-
- if (typeNamespace) {
- COMPILE_CHECK(buildPropertyInNamespace(typeNamespace, prop, obj,
- ctxt));
- return true;
- } else if (!type || !type->attachedPropertiesType()) {
- COMPILE_EXCEPTION(prop, tr("Non-existent attached object"));
- }
-
- if (!prop->value)
- COMPILE_EXCEPTION(prop, tr("Invalid attached object assignment"));
-
- Q_ASSERT(type->attachedPropertiesFunction());
- prop->index = type->attachedPropertiesId();
- prop->value->metatype = enginePrivate->cache(type->attachedPropertiesType());
- } else {
- // Setup regular property data
- bool notInRevision = false;
- QQmlPropertyData *d =
- prop->name().isEmpty()?0:property(obj, prop->name(), &notInRevision);
-
- if (d == 0 && notInRevision) {
- const QList<QQmlTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes();
- QQmlTypeData::TypeReference type;
- if (obj->type != -1)
- type = resolvedTypes.at(obj->type);
- if (type.type) {
- COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(elementName(obj)).arg(prop->name().toString()).arg(type.type->module()).arg(type.majorVersion).arg(type.minorVersion));
- } else {
- COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(elementName(obj)).arg(prop->name().toString()));
- }
- } else if (d) {
- prop->index = d->coreIndex;
- prop->core = *d;
- } else if (prop->isDefault) {
- QString defaultPropertyName = obj->metatype->defaultPropertyName();
-
- if (!defaultPropertyName.isEmpty()) {
- prop->setName(defaultPropertyName);
- prop->core = *obj->metatype->defaultProperty();
- prop->index = prop->core.coreIndex;
- }
- }
-
- // We can't error here as the "id" property does not require a
- // successful index resolution
- if (prop->index != -1)
- prop->type = prop->core.propType;
-
- // Check if this is an alias
- if (prop->index != -1 &&
- prop->parent &&
- prop->parent->type != -1 &&
- output->types.at(prop->parent->type).component) {
-
- QQmlPropertyCache *cache = output->types.at(prop->parent->type).component->rootPropertyCache;
- if (cache && cache->property(prop->index) && cache->property(prop->index)->isAlias())
- prop->isAlias = true;
- }
-
- if (prop->index != -1 && !prop->values.isEmpty())
- prop->parent->setBindingBit(prop->index);
- }
-
- if (!prop->isDefault && prop->name() == id_string && !ctxt.isSubContext()) {
-
- // The magic "id" behavior doesn't apply when "id" is resolved as a
- // default property or to sub-objects (which are always in binding
- // sub-contexts)
- COMPILE_CHECK(buildIdProperty(prop, obj));
- if (prop->type == QVariant::String &&
- prop->values.first()->value.isString())
- COMPILE_CHECK(buildPropertyAssignment(prop, obj, ctxt));
-
- } else if (isAttachedPropertyName(prop->name())) {
-
- COMPILE_CHECK(buildAttachedProperty(prop, obj, ctxt));
-
- } else if (prop->index == -1) {
-
- if (prop->isDefault) {
- COMPILE_EXCEPTION(prop->values.first(), tr("Cannot assign to non-existent default property"));
- } else {
- COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(prop->name().toString()));
- }
-
- } else if (prop->value) {
-
- COMPILE_CHECK(buildGroupedProperty(prop, obj, ctxt));
-
- } else if (prop->core.isQList()) {
-
- COMPILE_CHECK(buildListProperty(prop, obj, ctxt));
-
- } else if (prop->type == qMetaTypeId<QQmlScriptString>()) {
-
- COMPILE_CHECK(buildScriptStringProperty(prop, obj, ctxt));
-
- } else {
-
- COMPILE_CHECK(buildPropertyAssignment(prop, obj, ctxt));
-
- }
-
- return true;
-}
-
-bool QQmlCompiler::buildPropertyInNamespace(QQmlImportNamespace *ns,
- QQmlScript::Property *nsProp,
- QQmlScript::Object *obj,
- const BindingContext &ctxt)
-{
- if (!nsProp->value)
- COMPILE_EXCEPTION(nsProp, tr("Invalid use of namespace"));
-
- for (QQmlScript::Property *prop = nsProp->value->properties.first(); prop; prop = nsProp->value->properties.next(prop)) {
-
- if (!isAttachedPropertyName(prop->name()))
- COMPILE_EXCEPTION(prop, tr("Expected type name"));
-
- // Setup attached property data
-
- QQmlType *type = 0;
- unit->imports().resolveType(ns, prop->name(), &type, 0, 0);
-
- if (!type || !type->attachedPropertiesType())
- COMPILE_EXCEPTION(prop, tr("Non-existent attached object"));
-
- if (!prop->value)
- COMPILE_EXCEPTION(prop, tr("Invalid attached object assignment"));
-
- Q_ASSERT(type->attachedPropertiesFunction());
- prop->index = type->index();
- prop->value->metatype = enginePrivate->cache(type->attachedPropertiesType());
-
- COMPILE_CHECK(buildAttachedProperty(prop, obj, ctxt));
- }
-
- return true;
-}
-
-void QQmlCompiler::genValueProperty(QQmlScript::Property *prop,
- QQmlScript::Object *obj)
-{
- if (prop->core.isQList()) {
- genListProperty(prop, obj);
- } else {
- genPropertyAssignment(prop, obj);
- }
-}
-
-void QQmlCompiler::genListProperty(QQmlScript::Property *prop,
- QQmlScript::Object *obj)
-{
- int listType = enginePrivate->listType(prop->type);
-
- Instruction::FetchQList fetch;
- fetch.property = prop->index;
- bool listTypeIsInterface = QQmlMetaType::isInterface(listType);
- fetch.type = listType;
- output->addInstruction(fetch);
-
- for (QQmlScript::Value *v = prop->values.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
-
- if (v->type == QQmlScript::Value::CreatedObject) {
-
- genObject(v->object);
- if (listTypeIsInterface) {
- Instruction::AssignObjectList assign;
- assign.line = prop->location.start.line;
- output->addInstruction(assign);
- } else {
- Instruction::StoreObjectQList store;
- output->addInstruction(store);
- }
-
- } else if (v->type == QQmlScript::Value::PropertyBinding) {
-
- genBindingAssignment(v, prop, obj);
-
- }
-
- }
-
- Instruction::PopQList pop;
- output->addInstruction(pop);
-}
-
-void QQmlCompiler::genPropertyAssignment(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- QQmlScript::Property *valueTypeProperty)
-{
- for (QQmlScript::Value *v = prop->values.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
-
- Q_ASSERT(v->type == QQmlScript::Value::CreatedObject ||
- v->type == QQmlScript::Value::PropertyBinding ||
- v->type == QQmlScript::Value::Literal);
-
- if (v->type == QQmlScript::Value::CreatedObject) {
-
- genObject(v->object);
-
- if (QQmlMetaType::isInterface(prop->type)) {
-
- Instruction::StoreInterface store;
- store.line = v->object->location.start.line;
- store.propertyIndex = prop->index;
- output->addInstruction(store);
-
- } else if (prop->type == QMetaType::QVariant) {
-
- if (prop->core.isVarProperty()) {
- Instruction::StoreVarObject store;
- store.line = v->object->location.start.line;
- store.propertyIndex = prop->index;
- output->addInstruction(store);
- } else {
- Instruction::StoreVariantObject store;
- store.line = v->object->location.start.line;
- store.propertyIndex = prop->index;
- output->addInstruction(store);
- }
-
-
- } else {
-
- Instruction::StoreObject store;
- store.line = v->object->location.start.line;
- store.propertyIndex = prop->index;
- output->addInstruction(store);
-
- }
- } else if (v->type == QQmlScript::Value::PropertyBinding) {
-
- genBindingAssignment(v, prop, obj, valueTypeProperty);
-
- } else if (v->type == QQmlScript::Value::Literal) {
-
- genLiteralAssignment(prop, v);
-
- }
-
- }
-
- for (QQmlScript::Value *v = prop->onValues.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
-
- Q_ASSERT(v->type == QQmlScript::Value::ValueSource ||
- v->type == QQmlScript::Value::ValueInterceptor);
-
- if (v->type == QQmlScript::Value::ValueSource) {
- genObject(v->object, valueTypeProperty?true:false);
-
- Instruction::StoreValueSource store;
- if (valueTypeProperty)
- store.property = genValueTypeData(prop, valueTypeProperty);
- else
- store.property = prop->core;
- QQmlType *valueType = toQmlType(v->object);
- store.castValue = valueType->propertyValueSourceCast();
- output->addInstruction(store);
-
- } else if (v->type == QQmlScript::Value::ValueInterceptor) {
- genObject(v->object, valueTypeProperty?true:false);
-
- Instruction::StoreValueInterceptor store;
- if (valueTypeProperty)
- store.property = genValueTypeData(prop, valueTypeProperty);
- else
- store.property = prop->core;
- QQmlType *valueType = toQmlType(v->object);
- store.castValue = valueType->propertyValueInterceptorCast();
- output->addInstruction(store);
- }
-
- }
-}
-
-bool QQmlCompiler::buildIdProperty(QQmlScript::Property *prop,
- QQmlScript::Object *obj)
-{
- if (prop->value ||
- prop->values.isMany() ||
- prop->values.first()->object)
- COMPILE_EXCEPTION(prop, tr("Invalid use of id property"));
-
- QQmlScript::Value *idValue = prop->values.first();
- QString val = idValue->primitive();
-
- COMPILE_CHECK(checkValidId(idValue, val));
-
- if (compileState->ids.value(val))
- COMPILE_EXCEPTION(prop, tr("id is not unique"));
-
- prop->values.first()->type = QQmlScript::Value::Id;
-
- obj->id = val;
- addId(val, obj);
-
- return true;
-}
-
-void QQmlCompiler::addId(const QString &id, QQmlScript::Object *obj)
-{
- Q_UNUSED(id);
- Q_ASSERT(!compileState->ids.value(id));
- Q_ASSERT(obj->id == id);
- obj->idIndex = compileState->ids.count();
- compileState->ids.append(obj);
-}
-
-void QQmlCompiler::addBindingReference(JSBindingReference *ref)
-{
- Q_ASSERT(ref->value && !ref->value->bindingReference);
- ref->value->bindingReference = ref;
- compileState->totalBindingsCount++;
- compileState->bindings.prepend(ref);
-}
-
-void QQmlCompiler::saveComponentState()
-{
- Q_ASSERT(compileState->root);
- Q_ASSERT(compileState->root->componentCompileState == 0);
-
- compileState->root->componentCompileState = compileState;
-
- if (componentStats)
- componentStats->savedComponentStats.append(componentStats->componentStat);
-}
-
-QQmlCompilerTypes::ComponentCompileState *
-QQmlCompiler::componentState(QQmlScript::Object *obj)
-{
- Q_ASSERT(obj->componentCompileState);
- return obj->componentCompileState;
-}
-
-// Build attached property object. In this example,
-// Text {
-// GridView.row: 10
-// }
-// GridView is an attached property object.
-bool QQmlCompiler::buildAttachedProperty(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- const BindingContext &ctxt)
-{
- Q_ASSERT(prop->value);
- Q_ASSERT(prop->index != -1); // This is set in buildProperty()
-
- compileState->objectDepth.push();
-
- obj->addAttachedProperty(prop);
-
- COMPILE_CHECK(buildSubObject(prop->value, ctxt.incr()));
-
- compileState->objectDepth.pop();
-
- return true;
-}
-
-
-// Build "grouped" properties. In this example:
-// Text {
-// font.pointSize: 12
-// font.family: "Helvetica"
-// }
-// font is a nested property. pointSize and family are not.
-bool QQmlCompiler::buildGroupedProperty(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- const BindingContext &ctxt)
-{
- Q_ASSERT(prop->type != 0);
- Q_ASSERT(prop->index != -1);
-
- if (QQmlValueTypeFactory::isValueType(prop->type)) {
- QQmlValueType *valueType = QQmlValueTypeFactory::valueType(prop->type);
- if (prop->type >= 0 && valueType) {
- if (!prop->values.isEmpty()) {
- // Only error if we are assigning values, and not e.g. a property interceptor
- for (QQmlScript::Property *dotProp = prop->value->properties.first(); dotProp; dotProp = prop->value->properties.next(dotProp)) {
- if (!dotProp->values.isEmpty()) {
- if (prop->values.first()->location < prop->value->location) {
- COMPILE_EXCEPTION(prop->value, tr( "Property has already been assigned a value"));
- } else {
- COMPILE_EXCEPTION(prop->values.first(), tr( "Property has already been assigned a value"));
- }
- }
- }
- }
-
- if (!prop->core.isWritable() && !prop->isReadOnlyDeclaration) {
- COMPILE_EXCEPTION(prop, tr( "Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
- }
-
- if (prop->isAlias) {
- for (QQmlScript::Property *vtProp = prop->value->properties.first(); vtProp; vtProp = prop->value->properties.next(vtProp)) {
- vtProp->isAlias = true;
- }
- }
-
- COMPILE_CHECK(buildValueTypeProperty(valueType, prop->value, obj, ctxt.incr()));
-
- // When building a value type where sub components are declared, this
- // code path is followed from buildProperty, even if there is a previous
- // assignment to the value type as a whole. Therefore we need to look
- // for (and build) assignments to the entire value type before looking
- // for any onValue assignments.
- for (QQmlScript::Value *v = prop->values.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
- if (v->object) {
- COMPILE_EXCEPTION(v->object, tr("Objects cannot be assigned to value types"));
- }
- COMPILE_CHECK(buildPropertyLiteralAssignment(prop, obj, v, ctxt));
- }
-
- for (QQmlScript::Value *v = prop->onValues.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
- Q_ASSERT(v->object);
- COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, obj, v, ctxt));
- }
-
- obj->addValueTypeProperty(prop);
- } else {
- COMPILE_EXCEPTION(prop, tr("Invalid grouped property access"));
- }
- } else {
- // Load the nested property's meta type
- prop->value->metatype = enginePrivate->propertyCacheForType(prop->type);
- if (!prop->value->metatype)
- COMPILE_EXCEPTION(prop, tr("Invalid grouped property access"));
-
- if (!prop->values.isEmpty())
- COMPILE_EXCEPTION(prop->values.first(), tr( "Cannot assign a value directly to a grouped property"));
-
- obj->addGroupedProperty(prop);
-
- compileState->objectDepth.push();
-
- COMPILE_CHECK(buildSubObject(prop->value, ctxt.incr()));
-
- compileState->objectDepth.pop();
- }
-
- return true;
-}
-
-bool QQmlCompiler::buildValueTypeProperty(QObject *type,
- QQmlScript::Object *obj,
- QQmlScript::Object *baseObj,
- const BindingContext &ctxt)
-{
- compileState->objectDepth.push();
-
- if (obj->defaultProperty)
- COMPILE_EXCEPTION(obj, tr("Invalid property use"));
- obj->metatype = enginePrivate->cache(type);
-
- for (QQmlScript::Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
-
- QQmlPropertyData *d = property(obj, prop->name());
- if (d == 0)
- COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(prop->name().toString()));
-
- prop->index = d->coreIndex;
- prop->type = d->propType;
- prop->core = *d;
- prop->isValueTypeSubProperty = true;
-
- if (prop->value)
- COMPILE_EXCEPTION(prop, tr("Property assignment expected"));
-
- if (prop->values.isMany()) {
- COMPILE_EXCEPTION(prop, tr("Single property assignment expected"));
- } else if (!prop->values.isEmpty()) {
- QQmlScript::Value *value = prop->values.first();
-
- if (value->object) {
- COMPILE_EXCEPTION(prop, tr("Unexpected object assignment"));
- } else if (value->value.isScript()) {
- // ### Check for writability
-
- //optimization for <Type>.<EnumValue> enum assignments
- bool isEnumAssignment = false;
-
- if (prop->core.isEnum() || prop->core.propType == QMetaType::Int)
- COMPILE_CHECK(testQualifiedEnumAssignment(prop, obj, value, &isEnumAssignment));
-
- if (isEnumAssignment) {
- value->type = QQmlScript::Value::Literal;
- } else {
- JSBindingReference *reference = pool->New<JSBindingReference>();
- reference->expression = value->value;
- reference->property = prop;
- reference->value = value;
- reference->bindingContext = ctxt;
- reference->bindingContext.owner++;
- addBindingReference(reference);
- value->type = QQmlScript::Value::PropertyBinding;
- }
- } else {
- COMPILE_CHECK(testLiteralAssignment(prop, value));
- value->type = QQmlScript::Value::Literal;
- }
- }
-
- for (QQmlScript::Value *v = prop->onValues.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
- Q_ASSERT(v->object);
-
- COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, baseObj, v, ctxt));
- }
-
- obj->addValueProperty(prop);
- }
-
- compileState->objectDepth.pop();
-
- return true;
-}
-
-// Build assignments to QML lists. QML lists are properties of type
-// QQmlListProperty<T>. List properties can accept a list of
-// objects, or a single binding.
-bool QQmlCompiler::buildListProperty(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- const BindingContext &ctxt)
-{
- Q_ASSERT(prop->core.isQList());
-
- compileState->listDepth.push();
-
- int t = prop->type;
-
- obj->addValueProperty(prop);
-
- int listType = enginePrivate->listType(t);
- bool listTypeIsInterface = QQmlMetaType::isInterface(listType);
-
- bool assignedBinding = false;
- for (QQmlScript::Value *v = prop->values.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
- if (v->object) {
- v->type = QQmlScript::Value::CreatedObject;
- COMPILE_CHECK(buildObject(v->object, ctxt));
-
- // We check object coercian here. We check interface assignment
- // at runtime.
- if (!listTypeIsInterface) {
- if (!canCoerce(listType, v->object)) {
- COMPILE_EXCEPTION(v, tr("Cannot assign object to list"));
- }
- }
-
- } else if (v->value.isScript()) {
- if (assignedBinding)
- COMPILE_EXCEPTION(v, tr("Can only assign one binding to lists"));
-
- assignedBinding = true;
- COMPILE_CHECK(buildBinding(v, prop, ctxt));
- } else {
- COMPILE_EXCEPTION(v, tr("Cannot assign primitives to lists"));
- }
- }
-
- compileState->listDepth.pop();
-
- return true;
-}
-
-// Compiles an assignment to a QQmlScriptString property
-bool QQmlCompiler::buildScriptStringProperty(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- const BindingContext &ctxt)
-{
- if (prop->values.isMany())
- COMPILE_EXCEPTION(prop->values.first(), tr( "Cannot assign multiple values to a script property"));
-
- if (prop->values.first()->object)
- COMPILE_EXCEPTION(prop->values.first(), tr( "Invalid property assignment: script expected"));
-
- prop->scriptStringScope = ctxt.stack;
- obj->addScriptStringProperty(prop);
-
- return true;
-}
-
-// Compile regular property assignments of the form "property: <value>"
-bool QQmlCompiler::buildPropertyAssignment(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- const BindingContext &ctxt)
-{
- obj->addValueProperty(prop);
-
- if (prop->values.isMany())
- COMPILE_EXCEPTION(prop->values.first(), tr( "Cannot assign multiple values to a singular property") );
-
- for (QQmlScript::Value *v = prop->values.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
- if (v->object) {
-
- COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt));
-
- } else {
-
- COMPILE_CHECK(buildPropertyLiteralAssignment(prop, obj, v, ctxt));
-
- }
- }
-
- for (QQmlScript::Value *v = prop->onValues.first(); v; v = QQmlScript::Property::ValueList::next(v)) {
- Q_ASSERT(v->object);
- COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, obj, v, ctxt));
- }
-
- return true;
-}
-
-// Compile assigning a single object instance to a regular property
-bool QQmlCompiler::buildPropertyObjectAssignment(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- QQmlScript::Value *v,
- const BindingContext &ctxt)
-{
- Q_ASSERT(prop->index != -1);
- Q_ASSERT(v->object->type != -1);
-
- if (!prop->core.isWritable() && !prop->isReadOnlyDeclaration)
- COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
-
- if (QQmlMetaType::isInterface(prop->type)) {
-
- // Assigning an object to an interface ptr property
- COMPILE_CHECK(buildObject(v->object, ctxt));
-
- v->type = QQmlScript::Value::CreatedObject;
-
- } else if (prop->type == QMetaType::QVariant) {
-
- // Assigning an object to a QVariant
- COMPILE_CHECK(buildObject(v->object, ctxt));
-
- v->type = QQmlScript::Value::CreatedObject;
- } else {
- // Normally buildObject() will set this up, but we need the static
- // meta object earlier to test for assignability. It doesn't matter
- // that there may still be outstanding synthesized meta object changes
- // on this type, as they are not relevant for assignability testing
- v->object->metatype = output->types[v->object->type].createPropertyCache(engine);
- Q_ASSERT(v->object->metatype);
-
- // We want to raw metaObject here as the raw metaobject is the
- // actual property type before we applied any extensions that might
- // effect the properties on the type, but don't effect assignability
- QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(prop->type);
-
- // Will be true if the assgned type inherits propertyMetaObject
- bool isAssignable = false;
- // Determine isAssignable value
- if (propertyMetaObject) {
- QQmlPropertyCache *c = v->object->metatype;
- while (c && !isAssignable) {
- isAssignable |= c == propertyMetaObject;
- c = c->parent();
- }
- }
-
- if (isAssignable) {
- // Simple assignment
- COMPILE_CHECK(buildObject(v->object, ctxt));
-
- v->type = QQmlScript::Value::CreatedObject;
- } else if (propertyMetaObject && propertyMetaObject->metaObject() == &QQmlComponent::staticMetaObject) {
- // Automatic "Component" insertion
- QQmlScript::Object *root = v->object;
- QQmlScript::Object *component = pool->New<QQmlScript::Object>();
- component->type = componentTypeRef();
- component->metatype = enginePrivate->cache(&QQmlComponent::staticMetaObject);
- component->location = root->location;
- QQmlScript::Value *componentValue = pool->New<QQmlScript::Value>();
- componentValue->object = root;
- component->getDefaultProperty()->addValue(componentValue);
- v->object = component;
- COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt));
- } else {
- COMPILE_EXCEPTION(v->object, tr("Cannot assign object to property"));
- }
- }
-
- return true;
-}
-
-// Compile assigning a single object instance to a regular property using the "on" syntax.
-//
-// For example:
-// Item {
-// NumberAnimation on x { }
-// }
-bool QQmlCompiler::buildPropertyOnAssignment(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- QQmlScript::Object *baseObj,
- QQmlScript::Value *v,
- const BindingContext &ctxt)
-{
- Q_ASSERT(prop->index != -1);
- Q_ASSERT(v->object->type != -1);
-
- Q_UNUSED(obj);
-
- if (!prop->core.isWritable())
- COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
-
-
- // Normally buildObject() will set this up, but we need the static
- // meta object earlier to test for assignability. It doesn't matter
- // that there may still be outstanding synthesized meta object changes
- // on this type, as they are not relevant for assignability testing
- v->object->metatype = output->types[v->object->type].createPropertyCache(engine);
- Q_ASSERT(v->object->metatype);
-
- // Will be true if the assigned type inherits QQmlPropertyValueSource
- bool isPropertyValue = false;
- // Will be true if the assigned type inherits QQmlPropertyValueInterceptor
- bool isPropertyInterceptor = false;
- if (QQmlType *valueType = toQmlType(v->object)) {
- isPropertyValue = valueType->propertyValueSourceCast() != -1;
- isPropertyInterceptor = valueType->propertyValueInterceptorCast() != -1;
- }
-
- if (isPropertyValue || isPropertyInterceptor) {
- // Assign as a property value source
- COMPILE_CHECK(buildObject(v->object, ctxt));
-
- if (isPropertyInterceptor && baseObj->synthdata.isEmpty())
- buildDynamicMeta(baseObj, ForceCreation);
- v->type = isPropertyValue ? QQmlScript::Value::ValueSource : QQmlScript::Value::ValueInterceptor;
- } else {
- COMPILE_EXCEPTION(v, tr("\"%1\" cannot operate on \"%2\"").arg(elementName(v->object)).arg(prop->name().toString()));
- }
-
- return true;
-}
-
-// Compile assigning a literal or binding to a regular property
-bool QQmlCompiler::buildPropertyLiteralAssignment(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- QQmlScript::Value *v,
- const BindingContext &ctxt)
-{
- Q_ASSERT(prop->index != -1);
-
- if (v->value.isScript()) {
-
- //optimization for <Type>.<EnumValue> enum assignments
- if (prop->core.isEnum() || prop->core.propType == QMetaType::Int) {
- bool isEnumAssignment = false;
- COMPILE_CHECK(testQualifiedEnumAssignment(prop, obj, v, &isEnumAssignment));
- if (isEnumAssignment) {
- v->type = QQmlScript::Value::Literal;
- return true;
- }
- }
-
- // Test for other binding optimizations
- if (!buildLiteralBinding(v, prop, ctxt))
- COMPILE_CHECK(buildBinding(v, prop, ctxt));
-
- } else {
-
- COMPILE_CHECK(testLiteralAssignment(prop, v));
-
- v->type = QQmlScript::Value::Literal;
- }
-
- return true;
-}
-
-struct StaticQtMetaObject : public QObject
-{
- static const QMetaObject *get()
- { return &staticQtMetaObject; }
-};
-
-bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- QQmlScript::Value *v,
- bool *isAssignment)
-{
- bool isIntProp = (prop->core.propType == QMetaType::Int) && !prop->core.isEnum();
- *isAssignment = false;
- if (!prop->core.isEnum() && !isIntProp)
- return true;
-
- QMetaProperty mprop = obj->metatype->firstCppMetaObject()->property(prop->index);
-
- if (!prop->core.isWritable() && !prop->isReadOnlyDeclaration)
- COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
-
- QString string = v->value.asString();
- if (!string.at(0).isUpper())
- return true;
-
- int dot = string.indexOf(QLatin1Char('.'));
- if (dot == -1 || dot == string.length()-1)
- return true;
-
- if (string.indexOf(QLatin1Char('.'), dot+1) != -1)
- return true;
-
- QHashedStringRef typeName(string.constData(), dot);
- QString enumValue = string.mid(dot+1);
-
- if (isIntProp) {
- // Allow enum assignment to ints.
- bool ok;
- int enumval = evaluateEnum(typeName.toString(), enumValue.toUtf8(), &ok);
- if (ok) {
- v->type = QQmlScript::Value::Literal;
- v->value = QQmlScript::Variant((double)enumval);
- *isAssignment = true;
- }
- return true;
- }
-
- QQmlType *type = 0;
- unit->imports().resolveType(typeName, &type, 0, 0, 0);
-
- if (!type && typeName != QLatin1String("Qt"))
- return true;
- if (type && type->isComposite()) //No enums on composite (or composite singleton) types
- return true;
-
- int value = 0;
- bool ok = false;
-
- if (type && toQmlType(obj) == type) {
- // When these two match, we can short cut the search
- if (mprop.isFlagType()) {
- value = mprop.enumerator().keysToValue(enumValue.toUtf8().constData(), &ok);
- } else {
- value = mprop.enumerator().keyToValue(enumValue.toUtf8().constData(), &ok);
- }
- } else {
- // Otherwise we have to search the whole type
- if (type) {
- value = type->enumValue(QHashedStringRef(enumValue), &ok);
- } else {
- QByteArray enumName = enumValue.toUtf8();
- const QMetaObject *metaObject = StaticQtMetaObject::get();
- for (int ii = metaObject->enumeratorCount() - 1; !ok && ii >= 0; --ii) {
- QMetaEnum e = metaObject->enumerator(ii);
- value = e.keyToValue(enumName.constData(), &ok);
- }
- }
- }
-
- if (!ok)
- return true;
-
- v->type = QQmlScript::Value::Literal;
- v->value = QQmlScript::Variant((double)value);
- *isAssignment = true;
-
- return true;
-}
-
-QQmlBinding::Identifier QQmlCompiler::bindingIdentifier(const Variant &value, const QString &name, QQmlCustomParser *customParser)
-{
- JSBindingReference *reference = pool->New<JSBindingReference>();
- reference->expression = value;
- reference->property = pool->New<QQmlScript::Property>();
- reference->property->setName(name);
- reference->value = 0;
- reference->bindingContext = QQmlCompilerTypes::BindingContext(customParser->object);
- reference->bindingContext.owner++;
- // Unfortunately this is required for example for PropertyChanges where the bindings
- // will be executed in the dynamic scope of the target, so we can't resolve any lookups
- // at run-time.
- reference->disableLookupAcceleration = true;
-
- const int id = output->customParserBindings.count();
- output->customParserBindings.append(0); // Filled in later.
- reference->customParserBindingsIndex = id;
-
- compileState->totalBindingsCount++;
- compileState->bindings.prepend(reference);
-
- return id;
-}
-
-// Ensures that the dynamic meta specification on obj is valid
-bool QQmlCompiler::checkDynamicMeta(QQmlScript::Object *obj)
-{
- if (output->types[obj->type].isFullyDynamicType) {
- if (!obj->dynamicProperties.isEmpty())
- COMPILE_EXCEPTION(obj, tr("Fully dynamic types cannot declare new properties."));
- if (!obj->dynamicSignals.isEmpty())
- COMPILE_EXCEPTION(obj, tr("Fully dynamic types cannot declare new signals."));
- if (!obj->dynamicSlots.isEmpty())
- COMPILE_EXCEPTION(obj, tr("Fully Dynamic types cannot declare new functions."));
- }
-
- bool seenDefaultProperty = false;
-
- // We use a coarse grain, 31 bit hash to check if there are duplicates.
- // Calculating the hash for the names is not a waste as we have to test
- // them against the illegalNames set anyway.
- QHashField propNames;
- QHashField methodNames;
-
- // Check properties
- for (QQmlScript::Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
- const QQmlScript::Object::DynamicProperty &prop = *p;
-
- if (prop.isDefaultProperty) {
- if (seenDefaultProperty)
- COMPILE_EXCEPTION(&prop, tr("Duplicate default property"));
- seenDefaultProperty = true;
- }
-
- if (propNames.testAndSet(prop.name.hash())) {
- for (QQmlScript::Object::DynamicProperty *p2 = obj->dynamicProperties.first(); p2 != p;
- p2 = obj->dynamicProperties.next(p2)) {
- 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_LOCATION(prop.nameLocation.line,
- prop.nameLocation.column,
- tr("Property names cannot begin with an upper case letter"));
- }
-
- if (enginePrivate->v8engine()->illegalNames().contains(prop.name.toString())) {
- COMPILE_EXCEPTION_LOCATION(prop.nameLocation.line,
- prop.nameLocation.column,
- tr("Illegal property name"));
- }
- }
-
- for (QQmlScript::Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
- const QQmlScript::Object::DynamicSignal &currSig = *s;
-
- if (methodNames.testAndSet(currSig.name.hash())) {
- for (QQmlScript::Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2 != s;
- s2 = obj->dynamicSignals.next(s2)) {
- if (s2->name == currSig.name)
- COMPILE_EXCEPTION(&currSig, tr("Duplicate signal name"));
- }
- }
-
- if (currSig.name.at(0).isUpper())
- COMPILE_EXCEPTION(&currSig, tr("Signal names cannot begin with an upper case letter"));
- if (enginePrivate->v8engine()->illegalNames().contains(currSig.name.toString()))
- COMPILE_EXCEPTION(&currSig, tr("Illegal signal name"));
- }
-
- for (QQmlScript::Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
- const QQmlScript::Object::DynamicSlot &currSlot = *s;
-
- if (methodNames.testAndSet(currSlot.name.hash())) {
- for (QQmlScript::Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2;
- s2 = obj->dynamicSignals.next(s2)) {
- if (s2->name == currSlot.name)
- COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name"));
- }
- for (QQmlScript::Object::DynamicSlot *s2 = obj->dynamicSlots.first(); s2 != s;
- s2 = obj->dynamicSlots.next(s2)) {
- if (s2->name == currSlot.name)
- COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name"));
- }
- }
-
- if (currSlot.name.at(0).isUpper())
- COMPILE_EXCEPTION(&currSlot, tr("Method names cannot begin with an upper case letter"));
- if (enginePrivate->v8engine()->illegalNames().contains(currSlot.name.toString()))
- COMPILE_EXCEPTION(&currSlot, tr("Illegal method name"));
- }
-
- return true;
-}
-
-bool QQmlCompiler::mergeDynamicMetaProperties(QQmlScript::Object *obj)
-{
- for (QQmlScript::Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
- p = obj->dynamicProperties.next(p)) {
-
- if (!p->defaultValue || p->type == QQmlScript::Object::DynamicProperty::Alias)
- continue;
-
- QQmlScript::Property *property = 0;
- if (p->isDefaultProperty) {
- property = obj->getDefaultProperty();
- } else {
- property = obj->getProperty(p->name);
- if (!property->values.isEmpty())
- COMPILE_EXCEPTION(property, tr("Property value set multiple times"));
- }
-
- if (p->isReadOnly)
- property->isReadOnlyDeclaration = true;
-
- if (property->value)
- COMPILE_EXCEPTION(property, tr("Invalid property nesting"));
-
- property->values.append(p->defaultValue->values);
- }
- return true;
-}
-
-static QStringList astNodeToStringList(QQmlJS::AST::Node *node)
-{
- if (node->kind == QQmlJS::AST::Node::Kind_IdentifierExpression) {
- QString name =
- static_cast<QQmlJS::AST::IdentifierExpression *>(node)->name.toString();
- return QStringList() << name;
- } else if (node->kind == QQmlJS::AST::Node::Kind_FieldMemberExpression) {
- QQmlJS::AST::FieldMemberExpression *expr = static_cast<QQmlJS::AST::FieldMemberExpression *>(node);
-
- QStringList rv = astNodeToStringList(expr->base);
- if (rv.isEmpty())
- return rv;
- rv.append(expr->name.toString());
- return rv;
- }
- return QStringList();
-}
-
-static QAtomicInt classIndexCounter(0);
-
-bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mode)
-{
- Q_ASSERT(obj);
- Q_ASSERT(obj->metatype);
-
- if (mode != ForceCreation &&
- obj->dynamicProperties.isEmpty() &&
- obj->dynamicSignals.isEmpty() &&
- obj->dynamicSlots.isEmpty())
- return true;
-
- Q_ASSERT(obj->synthCache == 0);
-
- struct TypeData {
- QQmlScript::Object::DynamicProperty::Type dtype;
- int metaType;
- } builtinTypes[] = {
- { QQmlScript::Object::DynamicProperty::Var, qMetaTypeId<QJSValue>() },
- { QQmlScript::Object::DynamicProperty::Variant, QMetaType::QVariant },
- { QQmlScript::Object::DynamicProperty::Int, QMetaType::Int },
- { QQmlScript::Object::DynamicProperty::Bool, QMetaType::Bool },
- { QQmlScript::Object::DynamicProperty::Real, QMetaType::Double },
- { QQmlScript::Object::DynamicProperty::String, QMetaType::QString },
- { QQmlScript::Object::DynamicProperty::Url, QMetaType::QUrl },
- { QQmlScript::Object::DynamicProperty::Color, QMetaType::QColor },
- { QQmlScript::Object::DynamicProperty::Font, QMetaType::QFont },
- { QQmlScript::Object::DynamicProperty::Time, QMetaType::QTime },
- { QQmlScript::Object::DynamicProperty::Date, QMetaType::QDate },
- { QQmlScript::Object::DynamicProperty::DateTime, QMetaType::QDateTime },
- { QQmlScript::Object::DynamicProperty::Rect, QMetaType::QRectF },
- { QQmlScript::Object::DynamicProperty::Point, QMetaType::QPointF },
- { QQmlScript::Object::DynamicProperty::Size, QMetaType::QSizeF },
- { QQmlScript::Object::DynamicProperty::Vector2D, QMetaType::QVector2D },
- { QQmlScript::Object::DynamicProperty::Vector3D, QMetaType::QVector3D },
- { QQmlScript::Object::DynamicProperty::Vector4D, QMetaType::QVector4D },
- { QQmlScript::Object::DynamicProperty::Matrix4x4, QMetaType::QMatrix4x4 },
- { QQmlScript::Object::DynamicProperty::Quaternion, QMetaType::QQuaternion }
- };
- static const int builtinTypeCount = sizeof(builtinTypes) / sizeof(TypeData);
-
- QByteArray newClassName;
-
- if (compileState->root == obj && !compileState->nested) {
- QString path = output->url.path();
- int lastSlash = path.lastIndexOf(QLatin1Char('/'));
- if (lastSlash > -1) {
- QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5);
- if (!nameBase.isEmpty() && nameBase.at(0).isUpper())
- newClassName = nameBase.toUtf8() + "_QMLTYPE_" +
- QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1));
- }
- }
- if (newClassName.isEmpty()) {
- newClassName = QQmlMetaObject(obj->metatype).className();
- newClassName.append("_QML_");
- newClassName.append(QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1)));
- }
- QQmlPropertyCache *cache = obj->metatype->copyAndReserve(engine, obj->dynamicProperties.count(),
- obj->dynamicProperties.count() +
- obj->dynamicSignals.count() +
- obj->dynamicSlots.count(),
- obj->dynamicProperties.count() +
- obj->dynamicSignals.count());
-
- cache->_dynamicClassName = newClassName;
-
- int cStringNameCount = 0;
-
- int aliasCount = 0;
- int varPropCount = 0;
-
- for (QQmlScript::Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
- p = obj->dynamicProperties.next(p)) {
-
- if (p->type == QQmlScript::Object::DynamicProperty::Alias)
- aliasCount++;
- else if (p->type == QQmlScript::Object::DynamicProperty::Var)
- varPropCount++;
-
- if (p->name.isLatin1()) {
- p->nameIndex = cStringNameCount;
- cStringNameCount += p->name.length() + 7 /* strlen("Changed") */;
- }
-
- // No point doing this for both the alias and non alias cases
- QQmlPropertyData *d = property(obj, p->name);
- if (d && d->isFinal())
- COMPILE_EXCEPTION(p, tr("Cannot override FINAL property"));
- }
-
- for (QQmlScript::Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
- if (s->name.isLatin1()) {
- s->nameIndex = cStringNameCount;
- cStringNameCount += s->name.length();
- }
- }
-
- for (QQmlScript::Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
- if (s->name.isLatin1()) {
- s->nameIndex = cStringNameCount;
- cStringNameCount += s->name.length();
- }
- }
-
- char *cStringData = 0;
- if (cStringNameCount) {
- cache->_dynamicStringData.resize(cStringNameCount);
- cStringData = cache->_dynamicStringData.data();
-
- for (QQmlScript::Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
- p = obj->dynamicProperties.next(p)) {
-
- if (p->nameIndex == -1) continue;
-
- char *myData = cStringData + p->nameIndex;
- for (int ii = 0; ii < p->name.length(); ++ii)
- *myData++ = p->name.at(ii).unicode();
- *myData++ = 'C'; *myData++ = 'h'; *myData++ = 'a'; *myData++ = 'n';
- *myData++ = 'g'; *myData++ = 'e'; *myData++ = 'd';
- }
-
- for (QQmlScript::Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
-
- if (s->nameIndex == -1) continue;
-
- char *myData = cStringData + s->nameIndex;
- for (int ii = 0; ii < s->name.length(); ++ii)
- *myData++ = s->name.at(ii).unicode();
- }
-
- for (QQmlScript::Object::DynamicSignal *s = obj->dynamicSignals.first(); s;
- s = obj->dynamicSignals.next(s)) {
-
- if (s->nameIndex == -1) continue;
-
- char *myData = cStringData + s->nameIndex;
- for (int ii = 0; ii < s->name.length(); ++ii)
- *myData++ = s->name.at(ii).unicode();
- }
- }
-
- QByteArray dynamicData;
- typedef QQmlVMEMetaData VMD;
-
- dynamicData = QByteArray(sizeof(QQmlVMEMetaData) +
- obj->dynamicProperties.count() * sizeof(VMD::PropertyData) +
- obj->dynamicSlots.count() * sizeof(VMD::MethodData) +
- aliasCount * sizeof(VMD::AliasData), 0);
-
- int effectivePropertyIndex = cache->propertyIndexCacheStart;
- int effectiveMethodIndex = cache->methodIndexCacheStart;
-
- // For property change signal override detection.
- // We prepopulate a set of signal names which already exist in the object,
- // and throw an error if there is a signal/method defined as an override.
- QSet<QString> seenSignals;
- seenSignals << QStringLiteral("destroyed") << QStringLiteral("parentChanged") << QStringLiteral("objectNameChanged");
- QQmlPropertyCache *parentCache = cache;
- while ((parentCache = parentCache->parent())) {
- if (int pSigCount = parentCache->signalCount()) {
- int pSigOffset = parentCache->signalOffset();
- for (int i = pSigOffset; i < pSigCount; ++i) {
- QQmlPropertyData *currPSig = parentCache->signal(i);
- // XXX TODO: find a better way to get signal name from the property data :-/
- for (QQmlPropertyCache::StringCache::ConstIterator iter = parentCache->stringCache.begin();
- iter != parentCache->stringCache.end(); ++iter) {
- if (currPSig == (*iter).second) {
- seenSignals.insert(iter.key());
- break;
- }
- }
- }
- }
- }
-
- // First set up notify signals for properties - first normal, then var, then alias
- enum { NSS_Normal = 0, NSS_Var = 1, NSS_Alias = 2 };
- for (int ii = NSS_Normal; ii <= NSS_Alias; ++ii) { // 0 == normal, 1 == var, 2 == alias
-
- if (ii == NSS_Var && varPropCount == 0) continue;
- else if (ii == NSS_Alias && aliasCount == 0) continue;
-
- for (QQmlScript::Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
- p = obj->dynamicProperties.next(p)) {
-
- if ((ii == NSS_Normal && (p->type == QQmlScript::Object::DynamicProperty::Alias ||
- p->type == QQmlScript::Object::DynamicProperty::Var)) ||
- ((ii == NSS_Var) && (p->type != QQmlScript::Object::DynamicProperty::Var)) ||
- ((ii == NSS_Alias) && (p->type != QQmlScript::Object::DynamicProperty::Alias)))
- continue;
-
- quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
- QQmlPropertyData::IsVMESignal;
-
- QString changedSigName = p->name.toString() + QLatin1String("Changed");
- seenSignals.insert(changedSigName);
-
- if (p->nameIndex != -1) {
- QHashedCStringRef changedSignalName(cStringData + p->nameIndex,
- p->name.length() + 7 /* strlen("Changed") */);
- cache->appendSignal(changedSignalName, flags, effectiveMethodIndex++);
- } else {
- cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
- }
- }
- }
-
- // Dynamic signals
- for (QQmlScript::Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
- int paramCount = s->parameterNames.count();
-
- QList<QByteArray> names;
- QVarLengthArray<int, 10> paramTypes(paramCount?(paramCount + 1):0);
-
- if (paramCount) {
- paramTypes[0] = paramCount;
-
- for (int i = 0; i < paramCount; ++i) {
- if (s->parameterTypes.at(i) < builtinTypeCount) {
- // built-in type
- paramTypes[i + 1] = builtinTypes[s->parameterTypes.at(i)].metaType;
- names.append(s->parameterNames.at(i).toString().toUtf8());
- } else {
- // lazily resolved type
- Q_ASSERT(s->parameterTypes.at(i) == QQmlScript::Object::DynamicProperty::Custom);
- QQmlType *qmltype = 0;
- if (!unit->imports().resolveType(s->parameterTypeNames.at(i).toString(), &qmltype, 0, 0, 0))
- COMPILE_EXCEPTION(s, tr("Invalid signal parameter type: %1").arg(s->parameterTypeNames.at(i).toString()));
-
- // We dont mind even if the composite type ends up being composite singleton, here
- // we just acquire the metaTypeId.
- if (qmltype->isComposite()) {
- QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype->sourceUrl());
- Q_ASSERT(tdata);
- Q_ASSERT(tdata->isComplete());
-
- QQmlCompiledData *data = tdata->compiledData();
-
- paramTypes[i + 1] = data->metaTypeId;
-
- tdata->release();
- } else {
- paramTypes[i + 1] = qmltype->typeId();
- }
- names.append(s->parameterNames.at(i).toString().toUtf8());
- }
- }
- }
-
- ((QQmlVMEMetaData *)dynamicData.data())->signalCount++;
-
- quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
- QQmlPropertyData::IsVMESignal;
- if (paramCount)
- flags |= QQmlPropertyData::HasArguments;
-
- QString signalName = s->name.toString();
- if (seenSignals.contains(signalName)) {
- const QQmlScript::Object::DynamicSignal &currSig = *s;
- COMPILE_EXCEPTION(&currSig, tr("Duplicate signal name: invalid override of property change signal or superclass signal"));
- }
- seenSignals.insert(signalName);
-
- if (s->nameIndex != -1) {
- QHashedCStringRef name(cStringData + s->nameIndex, s->name.length(), s->name.hash());
- cache->appendSignal(name, flags, effectiveMethodIndex++,
- paramCount?paramTypes.constData():0, names);
- } else {
- cache->appendSignal(signalName, flags, effectiveMethodIndex++,
- paramCount?paramTypes.constData():0, names);
- }
- }
-
-
- // Dynamic slots
- for (QQmlScript::Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
- int paramCount = s->parameterNames.count();
-
- quint32 flags = QQmlPropertyData::IsFunction | QQmlPropertyData::IsVMEFunction;
-
- if (paramCount)
- flags |= QQmlPropertyData::HasArguments;
-
- QString slotName = s->name.toString();
- if (seenSignals.contains(slotName)) {
- const QQmlScript::Object::DynamicSlot &currSlot = *s;
- COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name: invalid override of property change signal or superclass signal"));
- }
- // Note: we don't append slotName to the seenSignals list, since we don't
- // protect against overriding change signals or methods with properties.
-
- if (s->nameIndex != -1) {
- QHashedCStringRef name(cStringData + s->nameIndex, s->name.length(), s->name.hash());
- cache->appendMethod(name, flags, effectiveMethodIndex++, s->parameterNames);
- } else {
- cache->appendMethod(slotName, flags, effectiveMethodIndex++, s->parameterNames);
- }
- }
-
-
- // Dynamic properties (except var and aliases)
- int effectiveSignalIndex = cache->signalHandlerIndexCacheStart;
- for (QQmlScript::Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
- p = obj->dynamicProperties.next(p)) {
-
- if (p->type == QQmlScript::Object::DynamicProperty::Alias ||
- p->type == QQmlScript::Object::DynamicProperty::Var)
- continue;
-
- int propertyType = 0;
- int vmePropertyType = 0;
- quint32 propertyFlags = 0;
-
- if (p->type < builtinTypeCount) {
- propertyType = builtinTypes[p->type].metaType;
- vmePropertyType = propertyType;
-
- if (p->type == QQmlScript::Object::DynamicProperty::Variant)
- propertyFlags |= QQmlPropertyData::IsQVariant;
- } else {
- Q_ASSERT(p->type == QQmlScript::Object::DynamicProperty::CustomList ||
- p->type == QQmlScript::Object::DynamicProperty::Custom);
-
- QQmlType *qmltype = 0;
- if (!unit->imports().resolveType(p->customType.toString(), &qmltype, 0, 0, 0))
- COMPILE_EXCEPTION(p, tr("Invalid property type"));
-
- Q_ASSERT(qmltype);
- if (qmltype->isComposite()) {
- QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype->sourceUrl());
- Q_ASSERT(tdata);
- Q_ASSERT(tdata->isComplete());
-
- QQmlCompiledData *data = tdata->compiledData();
-
- if (p->type == QQmlScript::Object::DynamicProperty::Custom) {
- propertyType = data->metaTypeId;
- vmePropertyType = QMetaType::QObjectStar;
- } else {
- propertyType = data->listMetaTypeId;
- vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >();
- }
-
- tdata->release();
- } else {
- if (p->type == QQmlScript::Object::DynamicProperty::Custom) {
- propertyType = qmltype->typeId();
- vmePropertyType = QMetaType::QObjectStar;
- } else {
- propertyType = qmltype->qListTypeId();
- vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >();
- }
- }
-
- if (p->type == QQmlScript::Object::DynamicProperty::Custom)
- propertyFlags |= QQmlPropertyData::IsQObjectDerived;
- else
- propertyFlags |= QQmlPropertyData::IsQList;
- }
-
- if (!p->isReadOnly && p->type != QQmlScript::Object::DynamicProperty::CustomList)
- propertyFlags |= QQmlPropertyData::IsWritable;
-
- if (p->nameIndex != -1) {
- QHashedCStringRef propertyName(cStringData + p->nameIndex, p->name.length(),
- p->name.hash());
- if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName.toUtf16();
- cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
- propertyType, effectiveSignalIndex);
- } else {
- QString propertyName = p->name.toString();
- if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName;
- cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
- propertyType, effectiveSignalIndex);
- }
-
- effectiveSignalIndex++;
-
- VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
- (vmd->propertyData() + vmd->propertyCount)->propertyType = vmePropertyType;
- vmd->propertyCount++;
- }
-
- // Now do var properties
- for (QQmlScript::Object::DynamicProperty *p = obj->dynamicProperties.first(); p && varPropCount;
- p = obj->dynamicProperties.next(p)) {
-
- if (p->type != QQmlScript::Object::DynamicProperty::Var)
- continue;
-
- quint32 propertyFlags = QQmlPropertyData::IsVarProperty;
- if (!p->isReadOnly)
- propertyFlags |= QQmlPropertyData::IsWritable;
-
- VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
- (vmd->propertyData() + vmd->propertyCount)->propertyType = QMetaType::QVariant;
- vmd->propertyCount++;
- ((QQmlVMEMetaData *)dynamicData.data())->varPropertyCount++;
-
- if (p->nameIndex != -1) {
- QHashedCStringRef propertyName(cStringData + p->nameIndex, p->name.length(),
- p->name.hash());
- if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName.toUtf16();
- cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
- QMetaType::QVariant, effectiveSignalIndex);
- } else {
- QString propertyName = p->name.toString();
- if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName;
- cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
- QMetaType::QVariant, effectiveSignalIndex);
- }
-
- effectiveSignalIndex++;
- }
-
- // Alias property count. Actual data is setup in buildDynamicMetaAliases
- ((QQmlVMEMetaData *)dynamicData.data())->aliasCount = aliasCount;
-
- // Dynamic slot data - comes after the property data
- for (QQmlScript::Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
- VMD::MethodData methodData = { /*runtimeFunctionIndex*/ 0, // To be filled in later
- s->parameterNames.count(),
- s->location.start.line };
-
- VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
- VMD::MethodData &md = *(vmd->methodData() + vmd->methodCount);
- vmd->methodCount++;
- md = methodData;
-
- ComponentCompileState::PerObjectCompileData *cd = &compileState->jsCompileData[obj];
-
- ComponentCompileState::CompiledMetaMethod cmm;
- cmm.methodIndex = vmd->methodCount - 1;
- cd->functionsToCompile.append(s->funcDecl);
- cmm.compiledFunctionIndex = cd->functionsToCompile.count() - 1;
- cd->compiledMetaMethods.append(cmm);
- }
-
- if (aliasCount)
- compileState->aliasingObjects.append(obj);
-
- obj->synthdata = dynamicData;
- obj->synthCache = cache;
- obj->metatype = cache;
-
- return true;
-}
-
-bool QQmlCompiler::buildDynamicMetaAliases(QQmlScript::Object *obj)
-{
- Q_ASSERT(obj->synthCache);
-
- QByteArray &dynamicData = obj->synthdata;
-
- QQmlPropertyCache *cache = obj->synthCache;
- char *cStringData = cache->_dynamicStringData.data();
-
- int effectiveSignalIndex = cache->signalHandlerIndexCacheStart + cache->propertyIndexCache.count();
- int effectivePropertyIndex = cache->propertyIndexCacheStart + cache->propertyIndexCache.count();
- int effectiveAliasIndex = 0;
-
- for (QQmlScript::Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
- p = obj->dynamicProperties.next(p)) {
-
- if (p->type != QQmlScript::Object::DynamicProperty::Alias)
- continue;
-
- if (!p->defaultValue)
- COMPILE_EXCEPTION(p, tr("No property alias location"));
-
- if (!p->defaultValue->values.isOne() ||
- p->defaultValue->values.first()->object ||
- !p->defaultValue->values.first()->value.isScript())
- COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias location"));
-
- QQmlJS::AST::Node *node = p->defaultValue->values.first()->value.asAST();
- Q_ASSERT(node);
-
- QStringList alias = astNodeToStringList(node);
- if (alias.count() < 1 || alias.count() > 3)
- COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
-
- QQmlScript::Object *idObject = compileState->ids.value(alias.at(0));
- if (!idObject)
- COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias reference. Unable to find id \"%1\"").arg(alias.at(0)));
-
- int propIdx = -1;
- int propType = 0;
- int notifySignal = -1;
- int flags = 0;
- int type = 0;
- bool writable = false;
- bool resettable = false;
-
- quint32 propertyFlags = QQmlPropertyData::IsAlias;
-
- if (alias.count() == 2 || alias.count() == 3) {
- QQmlPropertyData *property = this->property(idObject, alias.at(1));
-
- if (!property || property->coreIndex > 0x0000FFFF)
- COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias location"));
-
- propIdx = property->coreIndex;
- type = property->propType;
-
- writable = property->isWritable();
- resettable = property->isResettable();
- notifySignal = property->notifyIndex;
-
- if (alias.count() == 3) {
- QQmlValueType *valueType = QQmlValueTypeFactory::valueType(type);
- if (!valueType)
- COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias location"));
-
- propType = type;
-
- int valueTypeIndex =
- valueType->metaObject()->indexOfProperty(alias.at(2).toUtf8().constData());
- if (valueTypeIndex == -1)
- COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias location"));
- Q_ASSERT(valueTypeIndex <= 0x0000FFFF);
-
- propIdx |= (valueTypeIndex << 16);
- if (valueType->metaObject()->property(valueTypeIndex).isEnumType())
- type = QVariant::Int;
- else
- type = valueType->metaObject()->property(valueTypeIndex).userType();
-
- } else {
- if (property->isEnum()) {
- type = QVariant::Int;
- } else {
- // Copy type flags
- propertyFlags |= property->getFlags() & QQmlPropertyData::PropTypeFlagMask;
-
- if (property->isVarProperty())
- propertyFlags |= QQmlPropertyData::IsQVariant;
-
- if (property->isQObject())
- flags |= QML_ALIAS_FLAG_PTR;
- }
- }
- } else {
- Q_ASSERT(idObject->type != -1); // How else did it get an id?
-
- const QQmlCompiledData::TypeReference &ref = output->types.at(idObject->type);
- if (ref.type)
- type = ref.type->typeId();
- else
- type = ref.component->metaTypeId;
-
- flags |= QML_ALIAS_FLAG_PTR;
- propertyFlags |= QQmlPropertyData::IsQObjectDerived;
- }
-
- QQmlVMEMetaData::AliasData aliasData = { idObject->idIndex, propIdx, propType, flags, notifySignal };
-
- typedef QQmlVMEMetaData VMD;
- VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
- *(vmd->aliasData() + effectiveAliasIndex++) = aliasData;
-
- if (!p->isReadOnly && writable)
- propertyFlags |= QQmlPropertyData::IsWritable;
- else
- propertyFlags &= ~QQmlPropertyData::IsWritable;
-
- if (resettable)
- propertyFlags |= QQmlPropertyData::IsResettable;
- else
- propertyFlags &= ~QQmlPropertyData::IsResettable;
-
- if (p->nameIndex != -1) {
- QHashedCStringRef propertyName(cStringData + p->nameIndex, p->name.length(),
- p->name.hash());
- if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName.toUtf16();
- cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
- type, effectiveSignalIndex++);
- } else {
- QString propertyName = p->name.toString();
- if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName;
- cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
- type, effectiveSignalIndex++);
- }
- }
-
- return true;
-}
-
-bool QQmlCompiler::checkValidId(QQmlScript::Value *v, const QString &val)
-{
- if (val.isEmpty())
- COMPILE_EXCEPTION(v, tr( "Invalid empty ID"));
-
- QChar ch = val.at(0);
- if (ch.isLetter() && !ch.isLower())
- COMPILE_EXCEPTION(v, tr( "IDs cannot start with an uppercase letter"));
-
- QChar u(QLatin1Char('_'));
- if (!ch.isLetter() && ch != u)
- COMPILE_EXCEPTION(v, tr( "IDs must start with a letter or underscore"));
-
- for (int ii = 1; ii < val.count(); ++ii) {
- ch = val.at(ii);
- if (!ch.isLetterOrNumber() && ch != u)
- COMPILE_EXCEPTION(v, tr( "IDs must contain only letters, numbers, and underscores"));
- }
-
- if (enginePrivate->v8engine()->illegalNames().contains(val))
- COMPILE_EXCEPTION(v, tr( "ID illegally masks global JavaScript property"));
-
- return true;
-}
-
-bool QQmlCompiler::buildBinding(QQmlScript::Value *value,
- QQmlScript::Property *prop,
- const BindingContext &ctxt)
-{
- Q_ASSERT(prop->index != -1);
- Q_ASSERT(prop->parent);
- Q_ASSERT(prop->parent->metatype);
-
- if (!prop->core.isWritable() && !prop->core.isQList() && !prop->isReadOnlyDeclaration)
- COMPILE_EXCEPTION(value, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
-
- JSBindingReference *reference = pool->New<JSBindingReference>();
- reference->expression = value->value;
- reference->property = prop;
- reference->value = value;
- reference->bindingContext = ctxt;
- addBindingReference(reference);
- value->type = QQmlScript::Value::PropertyBinding;
-
- return true;
-}
-
-bool QQmlCompiler::buildLiteralBinding(QQmlScript::Value *v,
- QQmlScript::Property *prop,
- const QQmlCompilerTypes::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;
- v->type = QQmlScript::Value::PropertyBinding;
- 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;
- v->type = QQmlScript::Value::PropertyBinding;
- return true;
- }
-
- }
- }
- }
-
- }
-
- return false;
-}
-
-void QQmlCompiler::genBindingAssignment(QQmlScript::Value *binding,
- QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- QQmlScript::Property *valueTypeProperty)
-{
- Q_UNUSED(obj);
- Q_ASSERT(binding->bindingReference);
-
- const BindingReference &ref = *binding->bindingReference;
-#ifndef QT_NO_TRANSLATION
- 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
-#endif
- if (ref.dataType == BindingReference::QtScript) {
- const JSBindingReference &js = static_cast<const JSBindingReference &>(ref);
-
- Instruction::StoreBinding store;
- store.functionIndex = js.compiledIndex;
- store.context = js.bindingContext.stack;
- store.owner = js.bindingContext.owner;
- store.line = binding->location.start.line;
- store.column = binding->location.start.column;
- store.isAlias = prop->isAlias;
-
- if (valueTypeProperty) {
- store.isRoot = (compileState->root == valueTypeProperty->parent);
- } else {
- store.isRoot = (compileState->root == obj);
- }
- store.isFallback = false;
-
- 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 {
- Q_ASSERT(!"Unhandled BindingReference::DataType type");
- }
-}
-
-int QQmlCompiler::genContextCache()
-{
- if (compileState->ids.count() == 0)
- return -1;
-
- QVector<QQmlContextData::ObjectIdMapping> cache(compileState->ids.count());
- int i = 0;
- for (QQmlScript::Object *o = compileState->ids.first(); o; o = compileState->ids.next(o), ++i)
- cache[i] = QQmlContextData::ObjectIdMapping(o->id, o->idIndex);
-
- output->contextCaches.append(cache);
- return output->contextCaches.count() - 1;
-}
-
-QQmlPropertyData
-QQmlCompiler::genValueTypeData(QQmlScript::Property *valueTypeProp,
- QQmlScript::Property *prop)
-{
- QQmlValueType *vt = QQmlValueTypeFactory::valueType(prop->type);
- Q_ASSERT(vt);
- return QQmlPropertyPrivate::saveValueType(prop->core, vt->metaObject(), valueTypeProp->index, engine);
-}
-
-bool QQmlCompiler::completeComponentBuild()
-{
- if (componentStats)
- componentStats->componentStat.ids = compileState->ids.count();
-
- for (QQmlScript::Object *aliasObject = compileState->aliasingObjects.first(); aliasObject;
- aliasObject = compileState->aliasingObjects.next(aliasObject))
- COMPILE_CHECK(buildDynamicMetaAliases(aliasObject));
-
- const QQmlScript::Parser &parser = unit->parser();
- QQmlJS::Engine *jsEngine = parser.jsEngine();
- QQmlJS::MemoryPool *pool = jsEngine->pool();
- QStringList stringPool;
- stringPool.append(QString());
-
- for (JSBindingReference *b = compileState->bindings.first(); b; b = b->nextReference) {
-
- JSBindingReference &binding = *b;
- binding.dataType = BindingReference::QtScript;
-
- QQmlJS::AST::Node *node = binding.expression.asAST();
- // Always wrap this in an ExpressionStatement, to make sure that
- // property var foo: function() { ... } results in a closure initialization.
- if (!node->statementCast()) {
- AST::ExpressionNode *expr = node->expressionCast();
- node = new (pool) AST::ExpressionStatement(expr);
- }
-
- ComponentCompileState::PerObjectCompileData *cd = &compileState->jsCompileData[b->bindingContext.object];
- QtQml::CompiledFunctionOrExpression f;
- f.node = node;
- QString name = binding.property->name().toString().prepend(QStringLiteral("expression for "));
- stringPool.append(name);
- f.nameIndex = stringPool.count() - 1;
- f.disableAcceleratedLookups = binding.disableLookupAcceleration;
- cd->functionsToCompile.append(f);
- binding.compiledIndex = cd->functionsToCompile.count() - 1;
-
- if (componentStats && b->value)
- componentStats->componentStat.scriptBindings.append(b->value->location);
- }
-
- if (!compileState->jsCompileData.isEmpty()) {
- const QString &sourceCode = jsEngine->code();
- AST::UiProgram *qmlRoot = parser.qmlRoot();
-
- JSCodeGen jsCodeGen(unit->finalUrlString(), sourceCode, jsModule.data(), jsEngine, qmlRoot, output->importCache, stringPool);
-
- JSCodeGen::ObjectIdMapping idMapping;
- if (compileState->ids.count() > 0) {
- idMapping.reserve(compileState->ids.count());
- for (QQmlScript::Object *o = compileState->ids.first(); o; o = compileState->ids.next(o)) {
- JSCodeGen::IdMapping m;
- m.name = o->id;
- m.idIndex = o->idIndex;
- if (output->types[o->type].isFullyDynamicType)
- m.type = 0;
- else
- m.type = o->metatype;
- idMapping << m;
- }
- }
-
- jsCodeGen.beginContextScope(idMapping, compileState->root->metatype);
-
- for (QHash<QQmlScript::Object *, ComponentCompileState::PerObjectCompileData>::Iterator it = compileState->jsCompileData.begin();
- it != compileState->jsCompileData.end(); ++it) {
- QQmlScript::Object *scopeObject = it.key();
- ComponentCompileState::PerObjectCompileData *cd = &it.value();
-
- jsCodeGen.beginObjectScope(scopeObject->metatype);
-
- cd->runtimeFunctionIndices = jsCodeGen.generateJSCodeForFunctionsAndBindings(cd->functionsToCompile);
- QList<QQmlError> errors = jsCodeGen.errors();
- if (!errors.isEmpty()) {
- exceptions << errors;
- return false;
- }
-
- foreach (const QQmlCompilerTypes::ComponentCompileState::CompiledMetaMethod &cmm, cd->compiledMetaMethods) {
- typedef QQmlVMEMetaData VMD;
- VMD *vmd = (QQmlVMEMetaData *)scopeObject->synthdata.data();
- VMD::MethodData &md = *(vmd->methodData() + cmm.methodIndex);
- md.runtimeFunctionIndex = cd->runtimeFunctionIndices.at(cmm.compiledFunctionIndex);
- }
- }
-
- for (JSBindingReference *b = compileState->bindings.first(); b; b = b->nextReference) {
- JSBindingReference &binding = *b;
- binding.compiledIndex = compileState->jsCompileData[binding.bindingContext.object].runtimeFunctionIndices[binding.compiledIndex];
- if (!binding.value) { // Must be a binding requested from custom parser
- Q_ASSERT(binding.customParserBindingsIndex >= 0 && binding.customParserBindingsIndex < output->customParserBindings.count());
- output->customParserBindings[binding.customParserBindingsIndex] = binding.compiledIndex;
- }
- }
- }
-
- // Check pop()'s matched push()'s
- Q_ASSERT(compileState->objectDepth.depth() == 0);
- Q_ASSERT(compileState->listDepth.depth() == 0);
-
- saveComponentState();
-
- return true;
-}
-
-void QQmlCompiler::dumpStats()
-{
- Q_ASSERT(componentStats);
- qWarning().nospace() << "QML Document: " << output->url.toString();
- for (int ii = 0; ii < componentStats->savedComponentStats.count(); ++ii) {
- const ComponentStat &stat = componentStats->savedComponentStats.at(ii);
- qWarning().nospace() << " Component Line " << stat.lineNumber;
- qWarning().nospace() << " Total Objects: " << stat.objects;
- qWarning().nospace() << " IDs Used: " << stat.ids;
-
- qWarning().nospace() << " QScript Bindings: " << stat.scriptBindings.count();
- {
- QByteArray output;
- for (int ii = 0; ii < stat.scriptBindings.count(); ++ii) {
- if (0 == (ii % 10)) {
- if (ii) output.append('\n');
- output.append(" ");
- }
-
- output.append('(');
- output.append(QByteArray::number(stat.scriptBindings.at(ii).start.line));
- output.append(':');
- output.append(QByteArray::number(stat.scriptBindings.at(ii).start.column));
- output.append(") ");
- }
- if (!output.isEmpty())
- qWarning().nospace() << output.constData();
- }
- }
-}
-
-/*!
- Returns true if from can be assigned to a (QObject) property of type
- to.
-*/
-bool QQmlCompiler::canCoerce(int to, QQmlScript::Object *from)
-{
- QQmlPropertyCache *toMo = enginePrivate->rawPropertyCacheForType(to);
- QQmlPropertyCache *fromMo = from->metatype;
-
- while (fromMo) {
- if (fromMo == toMo)
- return true;
- fromMo = fromMo->parent();
- }
- return false;
-}
-
-/*!
- Returns the element name, as written in the QML file, for o.
-*/
-QString QQmlCompiler::elementName(QQmlScript::Object *o)
-{
- Q_ASSERT(o);
- if (o->type != -1) {
- return unit->parser().referencedTypes().at(o->type)->name;
- } else {
- return QString();
- }
-}
-
-QQmlType *QQmlCompiler::toQmlType(QQmlScript::Object *from)
-{
- if (from->type != -1 && output->types.at(from->type).type)
- return output->types.at(from->type).type;
-
- const QMetaObject *mo = from->metatype->firstCppMetaObject();
- QQmlType *type = 0;
- while (!type && mo) {
- type = QQmlMetaType::qmlType(mo);
- mo = mo->superClass();
- }
- return type;
-}
-
-QStringList QQmlCompiler::deferredProperties(QQmlScript::Object *obj)
-{
- const QMetaObject *mo = obj->metatype->firstCppMetaObject();
-
- int idx = mo->indexOfClassInfo("DeferredPropertyNames");
- if (idx == -1)
- return QStringList();
-
- QMetaClassInfo classInfo = mo->classInfo(idx);
- QStringList rv = QString::fromUtf8(classInfo.value()).split(QLatin1Char(','));
- return rv;
-}
-
-QQmlPropertyCache *
-QQmlCompiler::propertyCacheForObject(QQmlScript::Object *object)
- {
- if (object->synthCache)
- return object->synthCache;
- else if (object->type != -1)
- return output->types[object->type].createPropertyCache(engine);
- else
- return object->metatype;
-}
-
-QQmlPropertyData *
-QQmlCompiler::property(QQmlScript::Object *object, int index)
-{
- QQmlPropertyCache *cache = propertyCacheForObject(object);
-
- return cache->property(index);
-}
-
-QQmlPropertyData *
-QQmlCompiler::property(QQmlScript::Object *object, const QHashedStringRef &name, bool *notInRevision)
-{
- if (notInRevision) *notInRevision = false;
-
- QQmlPropertyCache *cache = propertyCacheForObject(object);
-
- QQmlPropertyData *d = cache->property(name, 0, 0);
-
- // Find the first property
- while (d && d->isFunction())
- d = cache->overrideData(d);
-
- if (d && !cache->isAllowedInRevision(d)) {
- if (notInRevision) *notInRevision = true;
- return 0;
- } else {
- return d;
- }
-}
-
-// This code must match the semantics of QQmlPropertyPrivate::findSignalByName
-QQmlPropertyData *
-QQmlCompiler::signal(QQmlScript::Object *object, const QHashedStringRef &name, bool *notInRevision)
-{
- if (notInRevision) *notInRevision = false;
-
- QQmlPropertyCache *cache = propertyCacheForObject(object);
-
-
- QQmlPropertyData *d = cache->property(name, 0, 0);
- if (notInRevision) *notInRevision = false;
-
- while (d && !(d->isFunction()))
- d = cache->overrideData(d);
-
- if (d && !cache->isAllowedInRevision(d)) {
- if (notInRevision) *notInRevision = true;
- return 0;
- } else if (d && d->isSignal()) {
- return d;
- }
-
- if (name.endsWith(Changed_string)) {
- QHashedStringRef propName = name.mid(0, name.length() - Changed_string.length());
-
- d = property(object, propName, notInRevision);
- if (d)
- return cache->signal(d->notifyIndex);
- }
-
- return 0;
-}
-
-// This code must match the semantics of QQmlPropertyPrivate::findSignalByName
-int QQmlCompiler::indexOfSignal(QQmlScript::Object *object, const QString &name,
- bool *notInRevision)
-{
- QQmlPropertyData *d = signal(object, QStringRef(&name), notInRevision);
- return d?d->coreIndex:-1;
-}
-
-int QQmlCompiler::indexOfProperty(QQmlScript::Object *object, const QString &name,
- bool *notInRevision)
-{
- return indexOfProperty(object, QStringRef(&name), notInRevision);
-}
-
-int QQmlCompiler::indexOfProperty(QQmlScript::Object *object, const QHashedStringRef &name,
- bool *notInRevision)
-{
- QQmlPropertyData *d = property(object, name, notInRevision);
- return d?d->coreIndex:-1;
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h
index 03134091f0..98d308aa5c 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlcompiler_p.h
@@ -55,7 +55,6 @@
#include "qqml.h"
#include "qqmlerror.h"
-#include "qqmlinstruction_p.h"
#include "qqmlscript_p.h"
#include "qqmlengine_p.h"
#include <private/qbitfield_p.h>
@@ -126,23 +125,8 @@ public:
void doDynamicTypeCheck();
};
- // --- old compiler:
- QList<TypeReference> types;
- // --- new compiler:
// map from name index
QHash<int, TypeReference*> resolvedTypes;
- // ---
-
- struct V8Program {
- V8Program(const QByteArray &p, QQmlCompiledData *c)
- : program(p), cdata(c) {}
-
- QByteArray program;
- QV4::PersistentValue bindings;
- QQmlCompiledData *cdata;
- };
-
- QList<V8Program> programs;
QQmlPropertyCache *rootPropertyCache;
QList<QString> primitives;
@@ -173,28 +157,6 @@ public:
bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); }
bool isCompositeType() const { return !datas.at(qmlUnit->indexOfRootObject).isEmpty(); }
- // ---
-
- struct Instruction {
-#define QML_INSTR_DATA_TYPEDEF(I, FMT) typedef QQmlInstructionData<QQmlInstruction::I> I;
- FOR_EACH_QML_INSTR(QML_INSTR_DATA_TYPEDEF)
-#undef QML_INSTR_DATA_TYPEDEF
- private:
- Instruction();
- };
-
- void dumpInstructions();
-
- template <int Instr>
- int addInstruction(const QQmlInstructionData<Instr> &data)
- {
- QQmlInstruction genericInstr;
- QQmlInstructionMeta<Instr>::setDataNoCommon(genericInstr, data);
- return addInstructionHelper(static_cast<QQmlInstruction::Type>(Instr), genericInstr);
- }
- int nextInstructionIndex();
- QQmlInstruction *instruction(int index);
- QQmlInstruction::Type instructionType(const QQmlInstruction *instr);
bool isInitialized() const { return hasEngine(); }
void initialize(QQmlEngine *);
@@ -204,318 +166,8 @@ protected:
virtual void clear(); // From QQmlCleanup
private:
- friend class QQmlCompiler;
-
- int addInstructionHelper(QQmlInstruction::Type type, QQmlInstruction &instr);
- void dump(QQmlInstruction *, int idx = -1);
QQmlCompiledData(const QQmlCompiledData &other);
QQmlCompiledData &operator=(const QQmlCompiledData &other);
-
- int indexForString(const QString &);
- int indexForByteArray(const QByteArray &);
- int indexForUrl(const QUrl &);
-};
-
-namespace QQmlCompilerTypes {
- struct BindingContext
- {
- BindingContext()
- : stack(0), owner(0), object(0) {}
- BindingContext(QQmlScript::Object *o)
- : stack(0), owner(0), object(o) {}
- BindingContext incr() const {
- BindingContext rv(object);
- rv.stack = stack + 1;
- return rv;
- }
- bool isSubContext() const { return stack != 0; }
- int stack;
- int owner;
- QQmlScript::Object *object;
- };
-
- struct BindingReference
- {
- enum DataType { QtScript,
- Tr, TrId };
- DataType dataType;
- };
-
- struct JSBindingReference : public QQmlPool::Class,
- public BindingReference
- {
- JSBindingReference() : disableLookupAcceleration(false), nextReference(0) {}
-
- QQmlScript::Variant expression;
- QQmlScript::Property *property;
- QQmlScript::Value *value;
-
- int compiledIndex : 16;
- int customParserBindingsIndex : 15;
- int disableLookupAcceleration: 1;
-
- BindingContext bindingContext;
-
- JSBindingReference *nextReference;
- };
-
- struct TrBindingReference : public QQmlPool::POD,
- public BindingReference
- {
- QStringRef text;
- QStringRef comment;
- int n;
- };
-
- struct IdList : public QFieldList<QQmlScript::Object,
- &QQmlScript::Object::nextIdObject>
- {
- QQmlScript::Object *value(const QString &id) const {
- for (QQmlScript::Object *o = first(); o; o = next(o)) {
- if (o->id == id)
- return o;
- }
- return 0;
- }
- };
-
- struct DepthStack {
- DepthStack() : _depth(0), _maxDepth(0) {}
- DepthStack(const DepthStack &o) : _depth(o._depth), _maxDepth(o._maxDepth) {}
- DepthStack &operator=(const DepthStack &o) { _depth = o._depth; _maxDepth = o._maxDepth; return *this; }
-
- int depth() const { return _depth; }
- int maxDepth() const { return _maxDepth; }
-
- void push() { ++_depth; _maxDepth = qMax(_depth, _maxDepth); }
- void pop() { --_depth; Q_ASSERT(_depth >= 0); Q_ASSERT(_maxDepth > _depth); }
-
- void pushPop(int count) { _maxDepth = qMax(_depth + count, _maxDepth); }
- private:
- int _depth;
- int _maxDepth;
- };
-
- // Contains all the incremental compiler state about a component. As
- // a single QML file can have multiple components defined, there may be
- // more than one of these for each compile
- struct ComponentCompileState : public QQmlPool::Class
- {
- ComponentCompileState()
- : parserStatusCount(0), totalBindingsCount(0), pushedProperties(0), nested(false),
- root(0) {}
-
- IdList ids;
- int parserStatusCount;
- int totalBindingsCount;
- int pushedProperties;
- bool nested;
-
- QByteArray compiledBindingData;
-
- DepthStack objectDepth;
- DepthStack listDepth;
-
- typedef QQmlCompilerTypes::JSBindingReference B;
- typedef QFieldList<B, &B::nextReference> JSBindingReferenceList;
- JSBindingReferenceList bindings;
- typedef QQmlScript::Object O;
- typedef QFieldList<O, &O::nextAliasingObject> AliasingObjectsList;
- AliasingObjectsList aliasingObjects;
- QQmlScript::Object *root;
-
- struct CompiledMetaMethod
- {
- int methodIndex;
- int compiledFunctionIndex; // index in functionToCompile
- };
-
- QList<CompiledMetaMethod> compiledMetaMethods;
- struct PerObjectCompileData
- {
- QList<QtQml::CompiledFunctionOrExpression> functionsToCompile;
- QVector<int> runtimeFunctionIndices;
- QVector<CompiledMetaMethod> compiledMetaMethods;
- };
- QHash<QQmlScript::Object *, PerObjectCompileData> jsCompileData;
- };
-};
-
-class QMetaObjectBuilder;
-class Q_AUTOTEST_EXPORT QQmlCompiler : public QQmlCustomParserCompilerBackend
-{
- Q_DECLARE_TR_FUNCTIONS(QQmlCompiler)
-public:
- QQmlCompiler(QQmlPool *);
-
- bool compile(QQmlEngine *, QQmlTypeData *, QQmlCompiledData *);
-
- bool isError() const;
- QList<QQmlError> errors() const;
-
- static bool isAttachedPropertyName(const QString &);
- static bool isSignalPropertyName(const QString &);
- static bool isAttachedPropertyName(const QHashedStringRef &);
- static bool isSignalPropertyName(const QHashedStringRef &);
-
- virtual QQmlBinding::Identifier bindingIdentifier(const QQmlScript::Variant&value, const QString&name, QQmlCustomParser *customParser);
-
- virtual const QQmlImports &imports() const { return unit->imports(); }
-
-private:
- typedef QQmlCompiledData::Instruction Instruction;
-
- static void reset(QQmlCompiledData *);
-
- void compileTree(QQmlScript::Object *tree);
-
-
- bool buildObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
- bool buildComponent(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
- bool buildSubObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
- bool buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj,
- const QQmlCompilerTypes::BindingContext &);
- bool buildProperty(QQmlScript::Property *prop, QQmlScript::Object *obj,
- const QQmlCompilerTypes::BindingContext &);
- bool buildPropertyInNamespace(QQmlImportNamespace *ns,
- QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- const QQmlCompilerTypes::BindingContext &);
- bool buildIdProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
- bool buildAttachedProperty(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- const QQmlCompilerTypes::BindingContext &ctxt);
- bool buildGroupedProperty(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- const QQmlCompilerTypes::BindingContext &ctxt);
- bool buildValueTypeProperty(QObject *type,
- QQmlScript::Object *obj,
- QQmlScript::Object *baseObj,
- const QQmlCompilerTypes::BindingContext &ctxt);
- bool buildListProperty(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- const QQmlCompilerTypes::BindingContext &ctxt);
- bool buildScriptStringProperty(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- const QQmlCompilerTypes::BindingContext &ctxt);
- bool buildPropertyAssignment(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- const QQmlCompilerTypes::BindingContext &ctxt);
- bool buildPropertyObjectAssignment(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- QQmlScript::Value *value,
- const QQmlCompilerTypes::BindingContext &ctxt);
- bool buildPropertyOnAssignment(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- QQmlScript::Object *baseObj,
- QQmlScript::Value *value,
- const QQmlCompilerTypes::BindingContext &ctxt);
- bool buildPropertyLiteralAssignment(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- QQmlScript::Value *value,
- const QQmlCompilerTypes::BindingContext &ctxt);
- bool doesPropertyExist(QQmlScript::Property *prop, QQmlScript::Object *obj);
- bool testLiteralAssignment(QQmlScript::Property *prop,
- QQmlScript::Value *value);
- bool testQualifiedEnumAssignment(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- QQmlScript::Value *value,
- bool *isAssignment);
- enum DynamicMetaMode { Normal, ForceCreation };
- bool mergeDynamicMetaProperties(QQmlScript::Object *obj);
- bool buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mode);
- bool buildDynamicMetaAliases(QQmlScript::Object *obj);
- bool checkDynamicMeta(QQmlScript::Object *obj);
- bool buildBinding(QQmlScript::Value *, QQmlScript::Property *prop,
- const QQmlCompilerTypes::BindingContext &ctxt);
- bool buildLiteralBinding(QQmlScript::Value *, QQmlScript::Property *prop,
- const QQmlCompilerTypes::BindingContext &ctxt);
- bool buildComponentFromRoot(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
- bool completeComponentBuild();
- bool checkValidId(QQmlScript::Value *, const QString &);
-
-
- void genObject(QQmlScript::Object *obj, bool parentToSuper = false);
- void genObjectBody(QQmlScript::Object *obj);
- void genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Property *);
- void genComponent(QQmlScript::Object *obj);
- void genValueProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
- void genListProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
- void genPropertyAssignment(QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- QQmlScript::Property *valueTypeProperty = 0);
- void genLiteralAssignment(QQmlScript::Property *prop,
- QQmlScript::Value *value);
- void genBindingAssignment(QQmlScript::Value *binding,
- QQmlScript::Property *prop,
- QQmlScript::Object *obj,
- QQmlScript::Property *valueTypeProperty = 0);
- int genContextCache();
-
- QQmlPropertyData genValueTypeData(QQmlScript::Property *prop,
- QQmlScript::Property *valueTypeProp);
-
- int componentTypeRef();
- int translationContextIndex();
-
- QQmlType *toQmlType(QQmlScript::Object *from);
- bool canCoerce(int to, QQmlScript::Object *from);
-
- QString elementName(QQmlScript::Object *);
-
- QStringList deferredProperties(QQmlScript::Object *);
-
- QQmlPropertyCache *propertyCacheForObject(QQmlScript::Object *);
- QQmlPropertyData *property(QQmlScript::Object *, int);
- QQmlPropertyData *property(QQmlScript::Object *, const QHashedStringRef &,
- bool *notInRevision = 0);
- QQmlPropertyData *signal(QQmlScript::Object *, const QHashedStringRef &,
- bool *notInRevision = 0);
- int indexOfProperty(QQmlScript::Object *, const QHashedStringRef &, bool *notInRevision = 0);
- int indexOfProperty(QQmlScript::Object *, const QString &, bool *notInRevision = 0);
- int indexOfSignal(QQmlScript::Object *, const QString &, bool *notInRevision = 0);
-
- void addId(const QString &, QQmlScript::Object *);
-
- void dumpStats();
-
- void addBindingReference(QQmlCompilerTypes::JSBindingReference *);
-
- QQmlCompilerTypes::ComponentCompileState *compileState;
-
- QQmlPool *pool;
-
- QQmlCompilerTypes::ComponentCompileState *componentState(QQmlScript::Object *);
- void saveComponentState();
-
- QList<QQmlError> exceptions;
- QQmlCompiledData *output;
- QQmlEngine *engine;
- QQmlEnginePrivate *enginePrivate;
- QQmlScript::Object *unitRoot;
- QQmlTypeData *unit;
- int cachedComponentTypeRef;
- int cachedTranslationContextIndex;
-
- QScopedPointer<IR::Module> jsModule;
-
- // Compiler component statistics. Only collected if QML_COMPILER_STATS=1
- struct ComponentStat
- {
- ComponentStat() : lineNumber(0), ids(0), objects(0) {}
-
- quint16 lineNumber;
-
- int ids;
- QList<QQmlScript::LocationSpan> scriptBindings;
- int objects;
- };
- struct ComponentStats : public QQmlPool::Class
- {
- ComponentStat componentStat;
- QList<ComponentStat> savedComponentStats;
- };
- ComponentStats *componentStats;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index feeb42b7ed..77d02e071f 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -881,15 +881,10 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
enginePriv->referenceScarceResources();
QObject *rv = 0;
- if (enginePriv->useNewCompiler) {
- state.creator = new QQmlObjectCreator(context, cc, creationContext);
- rv = state.creator->create(start);
- if (!rv)
- state.errors = state.creator->errors;
- } else {
- state.vme.init(context, cc, start, creationContext);
- rv = state.vme.execute(&state.errors);
- }
+ state.creator = new QQmlObjectCreator(context, cc, creationContext);
+ rv = state.creator->create(start);
+ if (!rv)
+ state.errors = state.creator->errors;
enginePriv->dereferenceScarceResources();
if (rv) {
@@ -922,29 +917,20 @@ void QQmlComponentPrivate::beginDeferred(QQmlEnginePrivate *enginePriv,
state->errors.clear();
state->completePending = true;
- if (enginePriv->useNewCompiler) {
- QQmlData *ddata = QQmlData::get(object);
- Q_ASSERT(ddata->deferredData);
- QQmlData::DeferredData *deferredData = ddata->deferredData;
- QQmlContextData *creationContext = 0;
- state->creator = new QQmlObjectCreator(deferredData->context->parent, deferredData->compiledData, creationContext);
- if (!state->creator->populateDeferredProperties(object))
- state->errors << state->creator->errors;
- } else {
- state->vme.initDeferred(object);
- state->vme.execute(&state->errors);
- }
+ QQmlData *ddata = QQmlData::get(object);
+ Q_ASSERT(ddata->deferredData);
+ QQmlData::DeferredData *deferredData = ddata->deferredData;
+ QQmlContextData *creationContext = 0;
+ state->creator = new QQmlObjectCreator(deferredData->context->parent, deferredData->compiledData, creationContext);
+ if (!state->creator->populateDeferredProperties(object))
+ state->errors << state->creator->errors;
}
void QQmlComponentPrivate::complete(QQmlEnginePrivate *enginePriv, ConstructionState *state)
{
if (state->completePending) {
- if (enginePriv->useNewCompiler) {
- QQmlInstantiationInterrupt interrupt;
- state->creator->finalize(interrupt);
- } else {
- state->vme.complete();
- }
+ QQmlInstantiationInterrupt interrupt;
+ state->creator->finalize(interrupt);
state->completePending = false;
@@ -1015,9 +1001,7 @@ QQmlComponentAttached *QQmlComponent::qmlAttachedProperties(QObject *obj)
return a;
QQmlEnginePrivate *p = QQmlEnginePrivate::get(engine);
- if (p->activeVME) { // XXX should only be allowed during begin
- a->add(&p->activeVME->componentAttached);
- } else if (p->activeObjectCreator) {
+ if (p->activeObjectCreator) { // XXX should only be allowed during begin
a->add(p->activeObjectCreator->componentAttachment());
} else {
QQmlData *d = QQmlData::get(obj);
@@ -1083,11 +1067,8 @@ void QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context,
p->compiledData = d->cc;
p->compiledData->addref();
- if (enginePriv->useNewCompiler) {
- p->creator.reset(new QQmlObjectCreator(contextData, d->cc, d->creationContext, p.data()));
- p->subComponentToCreate = d->start;
- } else
- p->vme.init(contextData, d->cc, d->start, d->creationContext);
+ p->creator.reset(new QQmlObjectCreator(contextData, d->cc, d->creationContext, p.data()));
+ p->subComponentToCreate = d->start;
enginePriv->incubate(incubator, forContextData);
}
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index 9bccb0be7b..e8ae540148 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -114,11 +114,7 @@ public:
delete creator;
}
- // --- new compiler
QQmlObjectCreator *creator;
- // --- old compiler
- QQmlVME vme;
- // ---
QList<QQmlError> errors;
bool completePending;
};
diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp
index f661317794..16e3abf3a0 100644
--- a/src/qml/qml/qqmlcustomparser.cpp
+++ b/src/qml/qml/qqmlcustomparser.cpp
@@ -40,7 +40,6 @@
****************************************************************************/
#include "qqmlcustomparser_p.h"
-#include "qqmlcustomparser_p_p.h"
#include "qqmlcompiler_p.h"
@@ -93,138 +92,6 @@ using namespace QQmlScript;
The \a object will be an instance of the TypeClass specified by QML_REGISTER_CUSTOM_TYPE.
*/
-QQmlCustomParserNode
-QQmlCustomParserNodePrivate::fromObject(QQmlScript::Object *root)
-{
- QQmlCustomParserNode rootNode;
- if (root->typeReference)
- rootNode.d->name = root->typeReference->name;
- rootNode.d->location = root->location.start;
-
- for (QQmlScript::Property *p = root->properties.first(); p; p = root->properties.next(p)) {
- rootNode.d->properties << fromProperty(p);
- }
-
- if (root->defaultProperty)
- rootNode.d->properties << fromProperty(root->defaultProperty);
-
- return rootNode;
-}
-
-QQmlCustomParserProperty
-QQmlCustomParserNodePrivate::fromProperty(QQmlScript::Property *p)
-{
- QQmlCustomParserProperty prop;
- prop.d->name = p->name().toString();
- prop.d->isList = p->values.isMany();
- prop.d->location = p->location.start;
-
- if (p->value) {
- QQmlCustomParserNode node = fromObject(p->value);
- QList<QQmlCustomParserProperty> props = node.properties();
- for (int ii = 0; ii < props.count(); ++ii)
- prop.d->values << QVariant::fromValue(props.at(ii));
- } else {
- for (QQmlScript::Value *v = p->values.first(); v; v = p->values.next(v)) {
- v->type = QQmlScript::Value::Literal;
-
- if(v->object) {
- QQmlCustomParserNode node = fromObject(v->object);
- prop.d->values << QVariant::fromValue(node);
- } else {
- prop.d->values << QVariant::fromValue(v->value);
- }
-
- }
- }
-
- return prop;
-}
-
-QQmlCustomParserNode::QQmlCustomParserNode()
-: d(new QQmlCustomParserNodePrivate)
-{
-}
-
-QQmlCustomParserNode::QQmlCustomParserNode(const QQmlCustomParserNode &other)
-: d(new QQmlCustomParserNodePrivate)
-{
- *this = other;
-}
-
-QQmlCustomParserNode &QQmlCustomParserNode::operator=(const QQmlCustomParserNode &other)
-{
- d->name = other.d->name;
- d->properties = other.d->properties;
- d->location = other.d->location;
- return *this;
-}
-
-QQmlCustomParserNode::~QQmlCustomParserNode()
-{
- delete d; d = 0;
-}
-
-QString QQmlCustomParserNode::name() const
-{
- return d->name;
-}
-
-QList<QQmlCustomParserProperty> QQmlCustomParserNode::properties() const
-{
- return d->properties;
-}
-
-QQmlScript::Location QQmlCustomParserNode::location() const
-{
- return d->location;
-}
-
-QQmlCustomParserProperty::QQmlCustomParserProperty()
-: d(new QQmlCustomParserPropertyPrivate)
-{
-}
-
-QQmlCustomParserProperty::QQmlCustomParserProperty(const QQmlCustomParserProperty &other)
-: d(new QQmlCustomParserPropertyPrivate)
-{
- *this = other;
-}
-
-QQmlCustomParserProperty &QQmlCustomParserProperty::operator=(const QQmlCustomParserProperty &other)
-{
- d->name = other.d->name;
- d->isList = other.d->isList;
- d->values = other.d->values;
- d->location = other.d->location;
- return *this;
-}
-
-QQmlCustomParserProperty::~QQmlCustomParserProperty()
-{
- delete d; d = 0;
-}
-
-QString QQmlCustomParserProperty::name() const
-{
- return d->name;
-}
-
-bool QQmlCustomParserProperty::isList() const
-{
- return d->isList;
-}
-
-QQmlScript::Location QQmlCustomParserProperty::location() const
-{
- return d->location;
-}
-
-QList<QVariant> QQmlCustomParserProperty::assignedValues() const
-{
- return d->values;
-}
-
void QQmlCustomParser::clearErrors()
{
exceptions.clear();
@@ -233,52 +100,6 @@ void QQmlCustomParser::clearErrors()
/*!
Reports an error with the given \a description.
- This can only be used during the compile() step. For errors during setCustomData(), use qmlInfo().
-
- An error is generated referring to the position of the element in the source file.
-*/
-void QQmlCustomParser::error(const QString& description)
-{
- Q_ASSERT(object);
- QQmlError error;
- QString exceptionDescription;
- error.setLine(object->location.start.line);
- error.setColumn(object->location.start.column);
- error.setDescription(description);
- exceptions << error;
-}
-
-/*!
- Reports an error in parsing \a prop, with the given \a description.
-
- An error is generated referring to the position of \a node in the source file.
-*/
-void QQmlCustomParser::error(const QQmlCustomParserProperty& prop, const QString& description)
-{
- QQmlError error;
- error.setLine(prop.location().line);
- error.setColumn(prop.location().column);
- error.setDescription(description);
- exceptions << error;
-}
-
-/*!
- Reports an error in parsing \a node, with the given \a description.
-
- An error is generated referring to the position of \a node in the source file.
-*/
-void QQmlCustomParser::error(const QQmlCustomParserNode& node, const QString& description)
-{
- QQmlError error;
- error.setLine(node.location().line);
- error.setColumn(node.location().column);
- error.setDescription(description);
- exceptions << error;
-}
-
-/*!
- Reports an error with the given \a description.
-
An error is generated referring to the \a location in the source file.
*/
void QQmlCustomParser::error(const CompiledData::Location &location, const QString &description)
@@ -318,16 +139,6 @@ const QMetaObject *QQmlCustomParser::resolveType(const QString& name) const
return compiler->resolveType(name);
}
-/*!
- Rewrites \a value and returns an identifier that can be
- used to construct the binding later. \a name
- is used as the name of the rewritten function.
-*/
-QQmlBinding::Identifier QQmlCustomParser::bindingIdentifier(const QQmlScript::Variant &value, const QString& name)
-{
- return compiler->bindingIdentifier(value, name, this);
-}
-
QQmlBinding::Identifier QQmlCustomParser::bindingIdentifier(const QV4::CompiledData::Binding *binding)
{
return compiler->bindingIdentifier(binding, this);
diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h
index 4861456c3d..8d98cf6423 100644
--- a/src/qml/qml/qqmlcustomparser_p.h
+++ b/src/qml/qml/qqmlcustomparser_p.h
@@ -63,51 +63,6 @@
QT_BEGIN_NAMESPACE
-
-class QQmlCompiler;
-
-class QQmlCustomParserPropertyPrivate;
-class Q_QML_PRIVATE_EXPORT QQmlCustomParserProperty
-{
-public:
- QQmlCustomParserProperty();
- QQmlCustomParserProperty(const QQmlCustomParserProperty &);
- QQmlCustomParserProperty &operator=(const QQmlCustomParserProperty &);
- ~QQmlCustomParserProperty();
-
- QString name() const;
- QQmlScript::Location location() const;
-
- bool isList() const;
- // Will be one of QQmlScript::Variant, QQmlCustomParserProperty or
- // QQmlCustomParserNode
- QList<QVariant> assignedValues() const;
-
-private:
- friend class QQmlCustomParserNodePrivate;
- friend class QQmlCustomParserPropertyPrivate;
- QQmlCustomParserPropertyPrivate *d;
-};
-
-class QQmlCustomParserNodePrivate;
-class Q_QML_PRIVATE_EXPORT QQmlCustomParserNode
-{
-public:
- QQmlCustomParserNode();
- QQmlCustomParserNode(const QQmlCustomParserNode &);
- QQmlCustomParserNode &operator=(const QQmlCustomParserNode &);
- ~QQmlCustomParserNode();
-
- QString name() const;
- QQmlScript::Location location() const;
-
- QList<QQmlCustomParserProperty> properties() const;
-
-private:
- friend class QQmlCustomParserNodePrivate;
- QQmlCustomParserNodePrivate *d;
-};
-
struct QQmlCustomParserCompilerBackend
{
virtual ~QQmlCustomParserCompilerBackend() {}
@@ -116,7 +71,6 @@ struct QQmlCustomParserCompilerBackend
int evaluateEnum(const QString &scope, const QByteArray& enumValue, bool *ok) const;
const QMetaObject *resolveType(const QString& name) const;
- virtual QQmlBinding::Identifier bindingIdentifier(const QQmlScript::Variant&, const QString&, QQmlCustomParser *) { return QQmlBinding::Invalid; }
virtual QQmlBinding::Identifier bindingIdentifier(const QV4::CompiledData::Binding *, QQmlCustomParser *) { return QQmlBinding::Invalid; }
virtual QQmlJS::AST::Node *astForBinding(int, int) const { return 0; }
@@ -132,23 +86,19 @@ public:
};
Q_DECLARE_FLAGS(Flags, Flag)
- QQmlCustomParser() : compiler(0), object(0), m_flags(NoFlag) {}
- QQmlCustomParser(Flags f) : compiler(0), object(0), m_flags(f) {}
+ QQmlCustomParser() : compiler(0), m_flags(NoFlag) {}
+ QQmlCustomParser(Flags f) : compiler(0), m_flags(f) {}
virtual ~QQmlCustomParser() {}
void clearErrors();
Flags flags() const { return m_flags; }
- virtual QByteArray compile(const QList<QQmlCustomParserProperty> &)=0;
virtual QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, int objectIndex, const QList<const QV4::CompiledData::Binding *> &bindings) = 0;
virtual void setCustomData(QObject *, const QByteArray &)=0;
QList<QQmlError> errors() const { return exceptions; }
protected:
- void error(const QString& description);
- void error(const QQmlCustomParserProperty&, const QString& description);
- void error(const QQmlCustomParserNode&, const QString& description);
void error(const QV4::CompiledData::Binding *binding, const QString& description)
{ error(binding->location, description); }
void error(const QV4::CompiledData::Object *object, const QString& description)
@@ -159,7 +109,6 @@ protected:
const QMetaObject *resolveType(const QString&) const;
- QQmlBinding::Identifier bindingIdentifier(const QQmlScript::Variant&, const QString&);
QQmlBinding::Identifier bindingIdentifier(const QV4::CompiledData::Binding *binding);
QQmlJS::AST::Node *astForBinding(int objectIndex, int scriptIndex) const;
@@ -167,9 +116,7 @@ protected:
private:
QList<QQmlError> exceptions;
QQmlCustomParserCompilerBackend *compiler;
- QQmlScript::Object *object;
Flags m_flags;
- friend class QQmlCompiler;
friend class QQmlPropertyValidator;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlCustomParser::Flags)
@@ -181,7 +128,4 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlCustomParser::Flags)
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QQmlCustomParserProperty)
-Q_DECLARE_METATYPE(QQmlCustomParserNode)
-
#endif
diff --git a/src/qml/qml/qqmlcustomparser_p_p.h b/src/qml/qml/qqmlcustomparser_p_p.h
deleted file mode 100644
index a6b64c6505..0000000000
--- a/src/qml/qml/qqmlcustomparser_p_p.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLCUSTOMPARSER_P_H
-#define QQMLCUSTOMPARSER_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qqmlcustomparser_p.h"
-
-#include "qqmlscript_p.h"
-
-#include <QtCore/qglobal.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQmlCustomParserNodePrivate
-{
-public:
- QString name;
- QList<QQmlCustomParserProperty> properties;
- QQmlScript::Location location;
-
- static QQmlCustomParserNode fromObject(QQmlScript::Object *);
- static QQmlCustomParserProperty fromProperty(QQmlScript::Property *);
-};
-
-class QQmlCustomParserPropertyPrivate
-{
-public:
- QQmlCustomParserPropertyPrivate()
- : isList(false) {}
-
- QString name;
- bool isList;
- QQmlScript::Location location;
- QList<QVariant> values;
-};
-
-QT_END_NAMESPACE
-
-#endif // QQMLCUSTOMPARSER_P_H
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index c344c3e069..72de9845c8 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -556,7 +556,7 @@ QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
: propertyCapture(0), rootContext(0), isDebugging(false),
profiler(0), outputWarningsToStdErr(true),
cleanup(0), erroredBindings(0), inProgressCreations(0),
- workerScriptEngine(0), activeVME(0),
+ workerScriptEngine(0),
activeObjectCreator(0),
networkAccessManager(0), networkAccessManagerFactory(0), urlInterceptor(0),
scarceResourcesRefCount(0), importDatabase(e), typeLoader(e), uniqueId(1),
@@ -1045,9 +1045,7 @@ QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
{
- if (activeVME) {
- activeVME->finalizeCallbacks.append(qMakePair(QPointer<QObject>(obj), index));
- } else if (activeObjectCreator) {
+ if (activeObjectCreator) {
activeObjectCreator->finalizeCallbacks()->append(qMakePair(QPointer<QObject>(obj), index));
} else {
void *args[] = { 0 };
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index e00e55f157..56c80dc2cd 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -98,7 +98,6 @@ class QQmlComponentAttached;
class QQmlCleanup;
class QQmlDelayedError;
class QQuickWorkerScriptEngine;
-class QQmlVME;
class QQmlObjectCreator;
class QDir;
class QQmlIncubator;
@@ -170,11 +169,7 @@ public:
typedef QPair<QPointer<QObject>,int> FinalizeCallback;
void registerFinalizeCallback(QObject *obj, int index);
- // --- old compiler:
- QQmlVME *activeVME;
- // --- new compiler:
QQmlObjectCreator *activeObjectCreator;
- // ---
QNetworkAccessManager *createNetworkAccessManager(QObject *parent) const;
QNetworkAccessManager *getNetworkAccessManager() const;
diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp
index da4de338ee..4c9c99f1f6 100644
--- a/src/qml/qml/qqmlincubator.cpp
+++ b/src/qml/qml/qqmlincubator.cpp
@@ -98,10 +98,7 @@ void QQmlEnginePrivate::incubate(QQmlIncubator &i, QQmlContextData *forContext)
incubatorList.insert(p.data());
incubatorCount++;
- if (useNewCompiler)
- p->vmeGuard.guard(p->creator.data());
- else
- p->vmeGuard.guard(&p->vme);
+ p->vmeGuard.guard(p->creator.data());
p->changeStatus(QQmlIncubator::Loading);
if (incubationController)
@@ -137,7 +134,7 @@ QQmlIncubationController *QQmlEngine::incubationController() const
QQmlIncubatorPrivate::QQmlIncubatorPrivate(QQmlIncubator *q, QQmlIncubator::IncubationMode m)
: q(q), status(QQmlIncubator::Null), mode(m), isAsynchronous(false), progress(Execute),
- result(0), compiledData(0), vme(this), waitingOnMe(0)
+ result(0), compiledData(0), waitingOnMe(0)
{
}
@@ -297,13 +294,9 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
if (progress == QQmlIncubatorPrivate::Execute) {
enginePriv->referenceScarceResources();
QObject *tresult = 0;
- if (enginePriv->useNewCompiler) {
- tresult = creator->create(subComponentToCreate, /*parent*/0, &i);
- if (!tresult)
- errors = creator->errors;
- } else {
- tresult = vme.execute(&errors, i);
- }
+ tresult = creator->create(subComponentToCreate, /*parent*/0, &i);
+ if (!tresult)
+ errors = creator->errors;
enginePriv->dereferenceScarceResources();
if (watcher.hasRecursed())
@@ -347,10 +340,7 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
return;
QQmlContextData *ctxt = 0;
- if (enginePriv->useNewCompiler)
- ctxt = creator->finalize(i);
- else
- ctxt = vme.complete(i);
+ ctxt = creator->finalize(i);
if (ctxt) {
rootContext = ctxt;
progress = QQmlIncubatorPrivate::Completed;
@@ -382,10 +372,7 @@ finishIncubate:
}
}
} else {
- if (enginePriv->useNewCompiler)
- vmeGuard.guard(creator.data());
- else
- vmeGuard.guard(&vme);
+ vmeGuard.guard(creator.data());
}
}
@@ -584,7 +571,6 @@ void QQmlIncubator::clear()
bool guardOk = d->vmeGuard.isOK();
- d->vme.reset();
d->vmeGuard.clear();
if (d->creator && guardOk)
d->creator->clear();
diff --git a/src/qml/qml/qqmlincubator_p.h b/src/qml/qml/qqmlincubator_p.h
index 80da2910c1..ccb03f2bc4 100644
--- a/src/qml/qml/qqmlincubator_p.h
+++ b/src/qml/qml/qqmlincubator_p.h
@@ -88,12 +88,8 @@ public:
QPointer<QObject> result;
QQmlGuardedContextData rootContext;
QQmlCompiledData *compiledData;
- // --- old compiler
- QQmlVME vme;
- // --- new compiler
QScopedPointer<QQmlObjectCreator> creator;
int subComponentToCreate;
- // ---
QQmlVMEGuard vmeGuard;
QExplicitlySharedDataPointer<QQmlIncubatorPrivate> waitingOnMe;
diff --git a/src/qml/qml/qqmlinstruction.cpp b/src/qml/qml/qqmlinstruction.cpp
deleted file mode 100644
index 33ea3bb7d9..0000000000
--- a/src/qml/qml/qqmlinstruction.cpp
+++ /dev/null
@@ -1,283 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlinstruction_p.h"
-
-#include "qqmlcompiler_p.h"
-
-#include <QtCore/qdebug.h>
-
-QT_BEGIN_NAMESPACE
-
-void QQmlCompiledData::dump(QQmlInstruction *instr, int idx)
-{
-#ifdef QT_NO_DEBUG_STREAM
- Q_UNUSED(instr)
- Q_UNUSED(idx)
-#else
- switch (instructionType(instr)) {
- case QQmlInstruction::Init:
- qWarning().nospace() << idx << "\t\t" << "INIT\t\t\t" << instr->init.bindingsSize << "\t" << instr->init.parserStatusSize << "\t" << instr->init.contextCache << "\t" << instr->init.compiledBinding;
- break;
- case QQmlInstruction::DeferInit:
- qWarning().nospace() << idx << "\t\t" << "DEFER_INIT\t\t" << instr->deferInit.bindingsSize << "\t" << instr->deferInit.parserStatusSize << "\t" << instr->deferInit.objectStackSize << "\t" << instr->deferInit.listStackSize;
- break;
- case QQmlInstruction::Done:
- qWarning().nospace() << idx << "\t\t" << "DONE";
- break;
- case QQmlInstruction::CreateCppObject:
- qWarning().nospace() << idx << "\t\t" << "CREATECPP\t\t\t" << instr->create.type;
- break;
- case QQmlInstruction::CreateQMLObject:
- qWarning().nospace() << idx << "\t\t" << "CREATEQML\t\t\t" << instr->createQml.type << "\t" << instr->createQml.bindingBits;
- break;
- case QQmlInstruction::CompleteQMLObject:
- qWarning().nospace() << idx << "\t\t" << "COMPLETEQML";
- break;
- case QQmlInstruction::CreateSimpleObject:
- qWarning().nospace() << idx << "\t\t" << "CREATE_SIMPLE\t\t" << instr->createSimple.typeSize;
- break;
- case QQmlInstruction::SetId:
- qWarning().nospace() << idx << "\t\t" << "SETID\t\t\t" << instr->setId.value << "\t\t\t" << primitives.at(instr->setId.value);
- break;
- case QQmlInstruction::SetDefault:
- qWarning().nospace() << idx << "\t\t" << "SET_DEFAULT";
- break;
- case QQmlInstruction::CreateComponent:
- qWarning().nospace() << idx << "\t\t" << "CREATE_COMPONENT\t" << instr->createComponent.count;
- break;
- case QQmlInstruction::StoreMetaObject:
- qWarning().nospace() << idx << "\t\t" << "STORE_META\t\t";
- break;
- case QQmlInstruction::StoreFloat:
- qWarning().nospace() << idx << "\t\t" << "STORE_FLOAT\t\t" << instr->storeFloat.propertyIndex << "\t" << instr->storeFloat.value;
- break;
- case QQmlInstruction::StoreDouble:
- qWarning().nospace() << idx << "\t\t" << "STORE_DOUBLE\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value;
- break;
- case QQmlInstruction::StoreDoubleQList:
- qWarning().nospace() << idx << "\t\t" << "STORE_DOUBLE_QLIST\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value;
- break;
- case QQmlInstruction::StoreInteger:
- qWarning().nospace() << idx << "\t\t" << "STORE_INTEGER\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value;
- break;
- case QQmlInstruction::StoreIntegerQList:
- qWarning().nospace() << idx << "\t\t" << "STORE_INTEGER_QLIST\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value;
- break;
- case QQmlInstruction::StoreBool:
- qWarning().nospace() << idx << "\t\t" << "STORE_BOOL\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value;
- break;
- case QQmlInstruction::StoreBoolQList:
- qWarning().nospace() << idx << "\t\t" << "STORE_BOOL_QLIST\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value;
- break;
- case QQmlInstruction::StoreString:
- qWarning().nospace() << idx << "\t\t" << "STORE_STRING\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
- break;
- case QQmlInstruction::StoreStringList:
- qWarning().nospace() << idx << "\t\t" << "STORE_STRINGLIST\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
- break;
- case QQmlInstruction::StoreStringQList:
- qWarning().nospace() << idx << "\t\t" << "STORE_STRING_QLIST\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
- break;
-#ifndef QT_NO_TRANSLATION
- case QQmlInstruction::StoreTrString:
- qWarning().nospace() << idx << "\t\t" << "STORE_TR_STRING\t" << instr->storeTrString.propertyIndex << "\t" << instr->storeTrString.context << "\t" << instr->storeTrString.text << "\t" << instr->storeTrString.comment << "\t" << instr->storeTrString.n;
- break;
- case QQmlInstruction::StoreTrIdString:
- qWarning().nospace() << idx << "\t\t" << "STORE_TRID_STRING\t" << instr->storeTrIdString.propertyIndex << "\t" << instr->storeTrIdString.text << "\t" << instr->storeTrIdString.n;
- break;
-#endif
- case QQmlInstruction::StoreByteArray:
- qWarning().nospace() << idx << "\t\t" << "STORE_BYTEARRAY" << instr->storeByteArray.propertyIndex << "\t" << instr->storeByteArray.value << "\t\t" << datas.at(instr->storeByteArray.value);
- break;
- case QQmlInstruction::StoreUrl:
- qWarning().nospace() << idx << "\t\t" << "STORE_URL\t\t" << instr->storeUrl.propertyIndex << "\t" << instr->storeUrl.value << "\t\t" << urls.at(instr->storeUrl.value);
- break;
- case QQmlInstruction::StoreUrlQList:
- qWarning().nospace() << idx << "\t\t" << "STORE_URL_QLIST\t\t" << instr->storeUrl.propertyIndex << "\t" << instr->storeUrl.value << "\t\t" << urls.at(instr->storeUrl.value);
- break;
- case QQmlInstruction::StoreColor:
- qWarning().nospace() << idx << "\t\t" << "STORE_COLOR\t\t" << instr->storeColor.propertyIndex << "\t\t\t" << QString::number(instr->storeColor.value, 16);
- break;
- case QQmlInstruction::StoreDate:
- qWarning().nospace() << idx << "\t\t" << "STORE_DATE\t\t" << instr->storeDate.propertyIndex << "\t" << instr->storeDate.value;
- break;
- case QQmlInstruction::StoreTime:
- qWarning().nospace() << idx << "\t\t" << "STORE_TIME\t\t" << instr->storeTime.propertyIndex;
- break;
- case QQmlInstruction::StoreDateTime:
- qWarning().nospace() << idx << "\t\t" << "STORE_DATETIME\t\t" << instr->storeDateTime.propertyIndex;
- break;
- case QQmlInstruction::StorePoint:
- qWarning().nospace() << idx << "\t\t" << "STORE_POINT\t\t" << instr->storePoint.propertyIndex << "\t" << instr->storePoint.point.xp << "\t" << instr->storePoint.point.yp;
- break;
- case QQmlInstruction::StorePointF:
- qWarning().nospace() << idx << "\t\t" << "STORE_POINTF\t\t" << instr->storePointF.propertyIndex << "\t" << instr->storePointF.point.xp << "\t" << instr->storePointF.point.yp;
- break;
- case QQmlInstruction::StoreSize:
- qWarning().nospace() << idx << "\t\t" << "STORE_SIZE\t\t" << instr->storeSize.propertyIndex << "\t" << instr->storeSize.size.wd << "\t" << instr->storeSize.size.ht;
- break;
- case QQmlInstruction::StoreSizeF:
- qWarning().nospace() << idx << "\t\t" << "STORE_SIZEF\t\t" << instr->storeSizeF.propertyIndex << "\t" << instr->storeSizeF.size.wd << "\t" << instr->storeSizeF.size.ht;
- break;
- case QQmlInstruction::StoreRect:
- qWarning().nospace() << idx << "\t\t" << "STORE_RECT\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.rect.x1 << "\t" << instr->storeRect.rect.y1 << "\t" << instr->storeRect.rect.x2 << "\t" << instr->storeRect.rect.y2;
- break;
- case QQmlInstruction::StoreRectF:
- qWarning().nospace() << idx << "\t\t" << "STORE_RECTF\t\t" << instr->storeRectF.propertyIndex << "\t" << instr->storeRectF.rect.xp << "\t" << instr->storeRectF.rect.yp << "\t" << instr->storeRectF.rect.w << "\t" << instr->storeRectF.rect.h;
- break;
- case QQmlInstruction::StoreVector3D:
- qWarning().nospace() << idx << "\t\t" << "STORE_VECTOR3D\t\t" << instr->storeVector3D.propertyIndex << "\t" << instr->storeVector3D.vector.xp << "\t" << instr->storeVector3D.vector.yp << "\t" << instr->storeVector3D.vector.zp;
- break;
- case QQmlInstruction::StoreVector4D:
- qWarning().nospace() << idx << "\t\t" << "STORE_VECTOR4D\t\t" << instr->storeVector4D.propertyIndex << "\t" << instr->storeVector4D.vector.xp << "\t" << instr->storeVector4D.vector.yp << "\t" << instr->storeVector4D.vector.zp << "\t" << instr->storeVector4D.vector.wp;
- break;
- case QQmlInstruction::StoreVariant:
- qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
- break;
- case QQmlInstruction::StoreVariantInteger:
- qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT_INTEGER\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value;
- break;
- case QQmlInstruction::StoreVariantDouble:
- qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT_DOUBLE\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value;
- break;
- case QQmlInstruction::StoreVariantBool:
- qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT_BOOL\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value;
- break;
- case QQmlInstruction::StoreVar:
- qWarning().nospace() << idx << "\t\t" << "STORE_VAR\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
- break;
- case QQmlInstruction::StoreVarInteger:
- qWarning().nospace() << idx << "\t\t" << "STORE_VAR_INTEGER\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value;
- break;
- case QQmlInstruction::StoreVarDouble:
- qWarning().nospace() << idx << "\t\t" << "STORE_VAR_DOUBLE\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value;
- break;
- case QQmlInstruction::StoreVarBool:
- qWarning().nospace() << idx << "\t\t" << "STORE_VAR_BOOL\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value;
- break;
- case QQmlInstruction::StoreObject:
- qWarning().nospace() << idx << "\t\t" << "STORE_OBJECT\t\t" << instr->storeObject.propertyIndex;
- break;
- case QQmlInstruction::StoreVariantObject:
- qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT_OBJECT\t" << instr->storeObject.propertyIndex;
- break;
- case QQmlInstruction::StoreVarObject:
- qWarning().nospace() << idx << "\t\t" << "STORE_VAR_OBJECT\t" << instr->storeObject.propertyIndex;
- break;
- case QQmlInstruction::StoreInterface:
- qWarning().nospace() << idx << "\t\t" << "STORE_INTERFACE\t\t" << instr->storeObject.propertyIndex;
- break;
- case QQmlInstruction::StoreSignal:
- qWarning().nospace() << idx << "\t\t" << "STORE_SIGNAL\t\t" << instr->storeSignal.signalIndex << "\t" << instr->storeSignal.value;
- break;
- case QQmlInstruction::StoreImportedScript:
- qWarning().nospace() << idx << "\t\t" << "STORE_IMPORTED_SCRIPT\t" << instr->storeScript.value;
- break;
- case QQmlInstruction::StoreScriptString:
- qWarning().nospace() << idx << "\t\t" << "STORE_SCRIPT_STRING\t" << instr->storeScriptString.propertyIndex << "\t" << instr->storeScriptString.value << "\t" << instr->storeScriptString.scope << "\t" << instr->storeScriptString.bindingId;
- break;
- case QQmlInstruction::AssignSignalObject:
- qWarning().nospace() << idx << "\t\t" << "ASSIGN_SIGNAL_OBJECT\t" << instr->assignSignalObject.signal;
- break;
- case QQmlInstruction::AssignCustomType:
- qWarning().nospace() << idx << "\t\t" << "ASSIGN_CUSTOMTYPE\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.primitive << "\t" << instr->assignCustomType.type;
- break;
- case QQmlInstruction::StoreBinding:
- qWarning().nospace() << idx << "\t\t" << "STORE_BINDING\t" << instr->assignBinding.property.coreIndex << "\t" << instr->assignBinding.functionIndex << "\t" << instr->assignBinding.context;
- break;
- case QQmlInstruction::StoreValueSource:
- qWarning().nospace() << idx << "\t\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property.coreIndex << "\t" << instr->assignValueSource.castValue;
- break;
- case QQmlInstruction::StoreValueInterceptor:
- qWarning().nospace() << idx << "\t\t" << "STORE_VALUE_INTERCEPTOR\t" << instr->assignValueInterceptor.property.coreIndex << "\t" << instr->assignValueInterceptor.castValue;
- break;
- case QQmlInstruction::BeginObject:
- qWarning().nospace() << idx << "\t\t" << "BEGIN\t\t\t" << instr->begin.castValue;
- break;
- case QQmlInstruction::StoreObjectQList:
- qWarning().nospace() << idx << "\t\t" << "STORE_OBJECT_QLIST";
- break;
- case QQmlInstruction::AssignObjectList:
- qWarning().nospace() << idx << "\t\t" << "ASSIGN_OBJECT_LIST";
- break;
- case QQmlInstruction::FetchAttached:
- qWarning().nospace() << idx << "\t\t" << "FETCH_ATTACHED\t\t" << instr->fetchAttached.id;
- break;
- case QQmlInstruction::FetchQList:
- qWarning().nospace() << idx << "\t\t" << "FETCH_QLIST\t\t" << instr->fetch.property;
- break;
- case QQmlInstruction::FetchObject:
- qWarning().nospace() << idx << "\t\t" << "FETCH\t\t\t" << instr->fetch.property;
- break;
- case QQmlInstruction::FetchValueType:
- qWarning().nospace() << idx << "\t\t" << "FETCH_VALUE\t\t" << instr->fetchValue.property << "\t" << instr->fetchValue.type << "\t" << instr->fetchValue.bindingSkipList;
- break;
- case QQmlInstruction::PopFetchedObject:
- qWarning().nospace() << idx << "\t\t" << "POP";
- break;
- case QQmlInstruction::PopQList:
- qWarning().nospace() << idx << "\t\t" << "POP_QLIST";
- break;
- case QQmlInstruction::PopValueType:
- qWarning().nospace() << idx << "\t\t" << "POP_VALUE\t\t" << instr->fetchValue.property << "\t" << instr->fetchValue.type;
- break;
- case QQmlInstruction::Defer:
- qWarning().nospace() << idx << "\t\t" << "DEFER" << "\t\t\t" << instr->defer.deferCount;
- break;
- default:
- qWarning().nospace() << idx << "\t\t" << "XXX UNKNOWN INSTRUCTION" << "\t" << instructionType(instr);
- break;
- }
-#endif // QT_NO_DEBUG_STREAM
-}
-
-int QQmlInstruction::size(Type type)
-{
-#define QML_RETURN_INSTR_SIZE(I, FMT) case I: return QQmlInstructionMeta<(int)I>::Size;
- switch (type) {
- FOR_EACH_QML_INSTR(QML_RETURN_INSTR_SIZE)
- default: return 0;
- }
-#undef QML_RETURN_INSTR_SIZE
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlinstruction_p.h b/src/qml/qml/qqmlinstruction_p.h
deleted file mode 100644
index 27dc216a92..0000000000
--- a/src/qml/qml/qqmlinstruction_p.h
+++ /dev/null
@@ -1,560 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLINSTRUCTION_P_H
-#define QQMLINSTRUCTION_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qglobal.h>
-#include <private/qqmlpropertycache_p.h>
-
-QT_BEGIN_NAMESPACE
-
-#define FOR_EACH_QML_INSTR(F) \
- F(Init, init) \
- F(DeferInit, deferInit) \
- F(Done, common) \
- F(CreateCppObject, create) \
- F(CreateQMLObject, createQml) \
- F(CompleteQMLObject, completeQml) \
- F(CreateSimpleObject, createSimple) \
- F(SetId, setId) \
- F(SetDefault, common) \
- F(CreateComponent, createComponent) \
- F(StoreMetaObject, storeMeta) \
- F(StoreVariant, storeString) \
- F(StoreVariantInteger, storeInteger) \
- F(StoreVariantDouble, storeDouble) \
- F(StoreVariantBool, storeBool) \
- F(StoreVar, storeString) \
- F(StoreVarInteger, storeInteger) \
- F(StoreVarDouble, storeDouble) \
- F(StoreVarBool, storeBool) \
- F(StoreString, storeString) \
- F(StoreJSValueString, storeString) \
- F(StoreJSValueInteger, storeInteger) \
- F(StoreJSValueDouble, storeDouble) \
- F(StoreJSValueBool, storeBool) \
- F(StoreStringList, storeString) \
- F(StoreStringQList, storeString) \
- F_TRANSLATION(F, StoreTrString, storeTrString) \
- F_TRANSLATION(F, StoreTrIdString, storeTrIdString) \
- F(StoreByteArray, storeByteArray) \
- F(StoreUrl, storeUrl) \
- F(StoreUrlQList, storeUrl) \
- F(StoreFloat, storeFloat) \
- F(StoreDouble, storeDouble) \
- F(StoreDoubleQList, storeDouble) \
- F(StoreBool, storeBool) \
- F(StoreBoolQList, storeBool) \
- F(StoreInteger, storeInteger) \
- F(StoreIntegerQList, storeInteger) \
- F(StoreColor, storeColor) \
- F(StoreDate, storeDate) \
- F(StoreTime, storeTime) \
- F(StoreDateTime, storeDateTime) \
- F(StorePoint, storePoint) \
- F(StorePointF, storePointF) \
- F(StoreSize, storeSize) \
- F(StoreSizeF, storeSizeF) \
- F(StoreRect, storeRect) \
- F(StoreRectF, storeRectF) \
- F(StoreVector3D, storeVector3D) \
- F(StoreVector4D, storeVector4D) \
- F(StoreObject, storeObject) \
- F(AssignCustomType, assignCustomType) \
- F(AssignSignalObject, assignSignalObject) \
- F(StoreSignal, storeSignal) \
- F(StoreImportedScript, storeScript) \
- F(StoreScriptString, storeScriptString) \
- F(BeginObject, begin) \
- F(StoreBinding, assignBinding) \
- F(StoreValueSource, assignValueSource) \
- F(StoreValueInterceptor, assignValueInterceptor) \
- F(StoreObjectQList, common) \
- F(AssignObjectList, assignObjectList) \
- F(StoreVariantObject, storeObject) \
- F(StoreVarObject, storeObject) \
- F(StoreInterface, storeObject) \
- F(FetchAttached, fetchAttached) \
- F(FetchQList, fetchQmlList) \
- F(FetchObject, fetch) \
- F(PopQList, common) \
- F(Defer, defer) \
- F(PopFetchedObject, common) \
- F(FetchValueType, fetchValue) \
- F(PopValueType, fetchValue)
-
-#ifndef QT_NO_TRANSLATION
-#define F_TRANSLATION(F, I, FMT) F(I, FMT)
-#else
-#define F_TRANSLATION(F, I, FMT)
-#endif
-
-#if defined(Q_CC_GNU) && (!defined(Q_CC_INTEL) || __INTEL_COMPILER >= 1200)
-# define QML_THREADED_VME_INTERPRETER
-#endif
-
-#ifdef Q_ALIGNOF
-# define QML_INSTR_ALIGN_MASK (Q_ALIGNOF(QQmlInstruction) - 1)
-#else
-# define QML_INSTR_ALIGN_MASK (sizeof(void *) - 1)
-#endif
-
-#ifdef QML_THREADED_VME_INTERPRETER
-# define QML_INSTR_HEADER void *code;
-# define QML_INSTR_HEADER_INIT this->code = 0;
-#else
-# define QML_INSTR_HEADER quint8 instructionType;
-# define QML_INSTR_HEADER_INIT this->instructionType = 0;
-#endif
-
-#define QML_INSTR_ENUM(I, FMT) I,
-#define QML_INSTR_SIZE(I, FMT) ((sizeof(QQmlInstruction::instr_##FMT) + QML_INSTR_ALIGN_MASK) & ~QML_INSTR_ALIGN_MASK)
-
-class QQmlCompiledData;
-union QQmlInstruction
-{
- enum Type {
- FOR_EACH_QML_INSTR(QML_INSTR_ENUM)
- };
-
- struct instr_common {
- QML_INSTR_HEADER
- };
- struct instr_init {
- QML_INSTR_HEADER
- int bindingsSize;
- int parserStatusSize;
- int contextCache;
- int compiledBinding;
- int objectStackSize;
- int listStackSize;
- };
- struct instr_deferInit {
- QML_INSTR_HEADER
- int bindingsSize;
- int parserStatusSize;
- int objectStackSize;
- int listStackSize;
- };
- struct instr_createQml {
- QML_INSTR_HEADER
- int type;
- int bindingBits;
- bool isRoot;
- };
- struct instr_completeQml {
- QML_INSTR_HEADER
- ushort column;
- ushort line;
- bool isRoot;
- };
- struct instr_create {
- QML_INSTR_HEADER
- int type;
- int data;
- ushort column;
- ushort line;
- bool isRoot:1;
- bool parentToSuper:1;
- };
- struct instr_createSimple {
- QML_INSTR_HEADER
- void (*create)(void *);
- int typeSize;
- int type;
- ushort column;
- ushort line;
- bool parentToSuper;
- };
- struct instr_storeMeta {
- QML_INSTR_HEADER
- int aliasData;
- int propertyCache;
- };
- struct instr_setId {
- QML_INSTR_HEADER
- int value;
- int index;
- };
- struct instr_assignValueSource {
- QML_INSTR_HEADER
- QQmlPropertyRawData property;
- int castValue;
- };
- struct instr_assignValueInterceptor {
- QML_INSTR_HEADER
- QQmlPropertyRawData property;
- int castValue;
- };
- struct instr_assignBinding {
- QML_INSTR_HEADER
- QQmlPropertyRawData property;
- int functionIndex; // index in CompiledData::runtimeFunctions
- short context;
- short owner;
- bool isRoot:1;
- bool isAlias:1;
- bool isFallback:1;
- bool isSafe:1;
- ushort line;
- ushort column;
- };
- struct instr_fetch {
- QML_INSTR_HEADER
- int property;
- ushort line;
- ushort column;
- };
- struct instr_fetchValue {
- QML_INSTR_HEADER
- int property;
- int type;
- quint32 bindingSkipList;
- };
- struct instr_fetchQmlList {
- QML_INSTR_HEADER
- int property;
- int type;
- };
- struct instr_begin {
- QML_INSTR_HEADER
- int castValue;
- };
- struct instr_storeFloat {
- QML_INSTR_HEADER
- int propertyIndex;
- float value;
- };
- struct instr_storeDouble {
- QML_INSTR_HEADER
- int propertyIndex;
- double value;
- };
- struct instr_storeInteger {
- QML_INSTR_HEADER
- int propertyIndex;
- int value;
- };
- struct instr_storeBool {
- QML_INSTR_HEADER
- int propertyIndex;
- bool value;
- };
- struct instr_storeString {
- QML_INSTR_HEADER
- int propertyIndex;
- int value;
- };
- struct instr_storeTrString {
- QML_INSTR_HEADER
- int propertyIndex;
- int context;
- int text;
- int comment;
- int n;
- };
- struct instr_storeTrIdString {
- QML_INSTR_HEADER
- int propertyIndex;
- int text;
- int n;
- };
- struct instr_storeByteArray {
- QML_INSTR_HEADER
- int propertyIndex;
- int value;
- };
- struct instr_storeScriptString {
- QML_INSTR_HEADER
- int propertyIndex;
- int value;
- int scope;
- int bindingId;
- ushort line;
- ushort column;
- double numberValue;
- bool isStringLiteral:1;
- bool isNumberLiteral:1;
- };
- struct instr_storeScript {
- QML_INSTR_HEADER
- int value;
- };
- struct instr_storeUrl {
- QML_INSTR_HEADER
- int propertyIndex;
- int value;
- };
- struct instr_storeColor {
- QML_INSTR_HEADER
- int propertyIndex;
- unsigned int value;
- };
- struct instr_storeDate {
- QML_INSTR_HEADER
- int propertyIndex;
- int value;
- };
- struct instr_storeTime {
- QML_INSTR_HEADER
- int propertyIndex;
- int time; // QTime::fromMSecsSinceStartOfDay
- };
- struct instr_storeDateTime {
- QML_INSTR_HEADER
- int propertyIndex;
- int date;
- int time;
- };
- struct instr_storeRect {
- QML_INSTR_HEADER
- int propertyIndex;
- struct QRect {
- int x1;
- int y1;
- int x2;
- int y2;
- } rect;
- };
- struct instr_storeRectF {
- QML_INSTR_HEADER
- int propertyIndex;
- struct QRectF {
- qreal xp;
- qreal yp;
- qreal w;
- qreal h;
- } rect;
- };
- struct instr_storeObject {
- QML_INSTR_HEADER
- int propertyIndex;
- ushort line;
- };
- struct instr_assignCustomType {
- QML_INSTR_HEADER
- int propertyIndex;
- int primitive;
- int type;
- ushort line;
- };
- struct instr_storeSignal {
- QML_INSTR_HEADER
- int runtimeFunctionIndex;
- int handlerName;
- int parameters;
- int signalIndex;
- int value;
- short context;
- ushort line;
- ushort column;
- };
- struct instr_assignSignalObject {
- QML_INSTR_HEADER
- int signal;
- ushort line;
- ushort column;
- };
- struct instr_createComponent {
- QML_INSTR_HEADER
- int count;
- int endLine;
- int metaObject;
- ushort column;
- ushort line;
- bool isRoot;
- };
- struct instr_fetchAttached {
- QML_INSTR_HEADER
- int id;
- ushort line;
- };
- struct instr_defer {
- QML_INSTR_HEADER
- int deferCount;
- };
- struct instr_assignObjectList {
- QML_INSTR_HEADER
- ushort line;
- };
- struct instr_storePoint {
- QML_INSTR_HEADER
- int propertyIndex;
- struct QPoint {
- int xp;
- int yp;
- } point;
- };
- struct instr_storePointF {
- QML_INSTR_HEADER
- int propertyIndex;
- struct QPointF {
- qreal xp;
- qreal yp;
- } point;
- };
- struct instr_storeSize {
- QML_INSTR_HEADER
- int propertyIndex;
- struct QSize {
- int wd;
- int ht;
- } size;
- };
- struct instr_storeSizeF {
- QML_INSTR_HEADER
- int propertyIndex;
- struct QSizeF {
- qreal wd;
- qreal ht;
- } size;
- };
- struct instr_storeVector3D {
- QML_INSTR_HEADER
- int propertyIndex;
- struct QVector3D {
- float xp;
- float yp;
- float zp;
- } vector;
- };
- struct instr_storeVector4D {
- QML_INSTR_HEADER
- int propertyIndex;
- struct QVector4D {
- float xp;
- float yp;
- float zp;
- float wp;
- } vector;
- };
-
- instr_common common;
- instr_init init;
- instr_deferInit deferInit;
- instr_create create;
- instr_createQml createQml;
- instr_completeQml completeQml;
- instr_createSimple createSimple;
- instr_storeMeta storeMeta;
- instr_setId setId;
- instr_assignValueSource assignValueSource;
- instr_assignValueInterceptor assignValueInterceptor;
- instr_assignBinding assignBinding;
- instr_fetch fetch;
- instr_fetchValue fetchValue;
- instr_fetchQmlList fetchQmlList;
- instr_begin begin;
- instr_storeFloat storeFloat;
- instr_storeDouble storeDouble;
- instr_storeInteger storeInteger;
- instr_storeBool storeBool;
- instr_storeString storeString;
- instr_storeTrString storeTrString;
- instr_storeTrIdString storeTrIdString;
- instr_storeByteArray storeByteArray;
- instr_storeScriptString storeScriptString;
- instr_storeScript storeScript;
- instr_storeUrl storeUrl;
- instr_storeColor storeColor;
- instr_storeDate storeDate;
- instr_storeTime storeTime;
- instr_storeDateTime storeDateTime;
- instr_storePoint storePoint;
- instr_storePointF storePointF;
- instr_storeSize storeSize;
- instr_storeSizeF storeSizeF;
- instr_storeRect storeRect;
- instr_storeRectF storeRectF;
- instr_storeVector3D storeVector3D;
- instr_storeVector4D storeVector4D;
- instr_storeObject storeObject;
- instr_assignCustomType assignCustomType;
- instr_storeSignal storeSignal;
- instr_assignSignalObject assignSignalObject;
- instr_createComponent createComponent;
- instr_fetchAttached fetchAttached;
- instr_defer defer;
- instr_assignObjectList assignObjectList;
-
- static int size(Type type);
-};
-
-template<int N>
-struct QQmlInstructionMeta {
-};
-
-#define QML_INSTR_META_TEMPLATE(I, FMT) \
- template<> struct QQmlInstructionMeta<(int)QQmlInstruction::I> { \
- enum { Size = QML_INSTR_SIZE(I, FMT) }; \
- typedef QQmlInstruction::instr_##FMT DataType; \
- static const DataType &data(const QQmlInstruction &instr) { return instr.FMT; } \
- static void setData(QQmlInstruction &instr, const DataType &v) { memcpy(&instr.FMT, &v, Size); } \
- static void setDataNoCommon(QQmlInstruction &instr, const DataType &v) \
- { memcpy(reinterpret_cast<char *>(&instr.FMT) + sizeof(QQmlInstruction::instr_common), \
- reinterpret_cast<const char *>(&v) + sizeof(QQmlInstruction::instr_common), \
- Size - sizeof(QQmlInstruction::instr_common)); } \
- };
-FOR_EACH_QML_INSTR(QML_INSTR_META_TEMPLATE);
-#undef QML_INSTR_META_TEMPLATE
-
-template<int Instr>
-class QQmlInstructionData : public QQmlInstructionMeta<Instr>::DataType
-{
-public:
- QQmlInstructionData() : QQmlInstructionMeta<Instr>::DataType() { QML_INSTR_HEADER_INIT }
-};
-
-QT_END_NAMESPACE
-
-#endif // QQMLINSTRUCTION_P_H
diff --git a/src/qml/qml/qqmlscript.cpp b/src/qml/qml/qqmlscript.cpp
index 0618c90fa5..cf56d5701d 100644
--- a/src/qml/qml/qqmlscript.cpp
+++ b/src/qml/qml/qqmlscript.cpp
@@ -58,1359 +58,6 @@ QT_BEGIN_NAMESPACE
using namespace QQmlJS;
using namespace QQmlScript;
-//
-// Parser IR classes
-//
-QQmlScript::Object::Object()
-: type(-1), typeReference(0), idIndex(-1), metatype(0), synthCache(0),
- defaultProperty(0), parserStatusCast(-1), componentCompileState(0), nextAliasingObject(0),
- nextIdObject(0)
-{
-}
-
-QQmlScript::Object::~Object()
-{
- if (synthCache) synthCache->release();
-}
-
-void Object::setBindingBit(int b)
-{
- while (bindingBitmask.size() < 4 * (1 + b / 32))
- bindingBitmask.append(char(0));
-
- quint32 *bits = (quint32 *)bindingBitmask.data();
- bits[b / 32] |= (1 << (b % 32));
-}
-
-QQmlScript::Property *Object::getDefaultProperty()
-{
- if (!defaultProperty) {
- defaultProperty = pool()->New<Property>();
- defaultProperty->parent = this;
- }
- return defaultProperty;
-}
-
-void QQmlScript::Object::addValueProperty(Property *p)
-{
- valueProperties.append(p);
-}
-
-void QQmlScript::Object::addSignalProperty(Property *p)
-{
- signalProperties.append(p);
-}
-
-void QQmlScript::Object::addAttachedProperty(Property *p)
-{
- attachedProperties.append(p);
-}
-
-void QQmlScript::Object::addGroupedProperty(Property *p)
-{
- groupedProperties.append(p);
-}
-
-void QQmlScript::Object::addValueTypeProperty(Property *p)
-{
- valueTypeProperties.append(p);
-}
-
-void QQmlScript::Object::addScriptStringProperty(Property *p)
-{
- scriptStringProperties.append(p);
-}
-
-// This lookup is optimized for missing, and having to create a new property.
-Property *QQmlScript::Object::getProperty(const QHashedStringRef &name, bool create)
-{
- if (create) {
- quint32 h = name.hash();
- if (propertiesHashField.testAndSet(h)) {
- for (Property *p = properties.first(); p; p = properties.next(p)) {
- if (p->name() == name)
- return p;
- }
- }
-
- Property *property = pool()->New<Property>();
- property->parent = this;
- property->_name = name;
- property->isDefault = false;
- properties.prepend(property);
- return property;
- } else {
- for (Property *p = properties.first(); p; p = properties.next(p)) {
- if (p->name() == name)
- return p;
- }
- }
-
- return 0;
-}
-
-Property *QQmlScript::Object::getProperty(const QStringRef &name, bool create)
-{
- return getProperty(QHashedStringRef(name), create);
-}
-
-Property *QQmlScript::Object::getProperty(const QString &name, bool create)
-{
- for (Property *p = properties.first(); p; p = properties.next(p)) {
- if (p->name() == name)
- return p;
- }
-
- if (create) {
- Property *property = pool()->New<Property>();
- property->parent = this;
- property->_name = QStringRef(pool()->NewString(name));
- propertiesHashField.testAndSet(property->_name.hash());
- property->isDefault = false;
- properties.prepend(property);
- return property;
- } else {
- return 0;
- }
-}
-
-int QQmlScript::Object::aggregateDynamicSignalParameterCount() const
-{
- int sum = 0;
- for (DynamicSignal *s = dynamicSignals.first(); s; s = dynamicSignals.next(s))
- sum += s->parameterTypes.count() + 1; // +1 for return type
- return sum;
-}
-
-int QQmlScript::Object::aggregateDynamicSlotParameterCount() const
-{
- int sum = 0;
- for (DynamicSlot *s = dynamicSlots.first(); s; s = dynamicSlots.next(s))
- sum += s->parameterNames.count() + 1; // +1 for return type
- return sum;
-}
-
-QQmlScript::Object::DynamicProperty::DynamicProperty()
-: isDefaultProperty(false), isReadOnly(false), type(Variant), defaultValue(0), nextProperty(0),
- nameIndex(-1)
-{
-}
-
-QQmlScript::Object::DynamicSignal::DynamicSignal()
-: nextSignal(0), nameIndex(-1)
-{
-}
-
-QQmlScript::Object::DynamicSlot::DynamicSlot()
-: funcDecl(0), nextSlot(0), nameIndex(-1)
-{
-}
-
-int QQmlScript::Object::DynamicSlot::parameterNamesLength() const
-{
- int rv = 0;
- for (int ii = 0; ii < parameterNames.count(); ++ii)
- rv += parameterNames.at(ii).length();
- return rv;
-}
-
-QQmlScript::Property::Property()
-: parent(0), type(0), index(-1), value(0), isDefault(true), isDeferred(false),
- isValueTypeSubProperty(false), isAlias(false), isReadOnlyDeclaration(false),
- scriptStringScope(-1), nextMainProperty(0), nextProperty(0)
-{
-}
-
-QQmlScript::Object *QQmlScript::Property::getValue(const LocationSpan &l)
-{
- if (!value) { value = pool()->New<Object>(); value->location = l; }
- return value;
-}
-
-void QQmlScript::Property::addValue(Value *v)
-{
- values.append(v);
-}
-
-void QQmlScript::Property::addOnValue(Value *v)
-{
- onValues.append(v);
-}
-
-bool QQmlScript::Property::isEmpty() const
-{
- return !value && values.isEmpty() && onValues.isEmpty();
-}
-
-QQmlScript::Value::Value()
-: type(Unknown), object(0), bindingReference(0), nextValue(0)
-{
-}
-
-QQmlScript::Variant::Variant()
-: t(Invalid)
-{
-}
-
-QQmlScript::Variant::Variant(const Variant &o)
-: t(o.t), d(o.d), asWritten(o.asWritten)
-{
-}
-
-QQmlScript::Variant::Variant(bool v)
-: t(Boolean), b(v)
-{
-}
-
-QQmlScript::Variant::Variant(double v, const QStringRef &asWritten)
-: t(Number), d(v), asWritten(asWritten)
-{
-}
-
-QQmlScript::Variant::Variant(QQmlJS::AST::StringLiteral *v)
-: t(String), l(v)
-{
-}
-
-QQmlScript::Variant::Variant(const QStringRef &asWritten, QQmlJS::AST::Node *n)
-: t(Script), n(n), asWritten(asWritten)
-{
-}
-
-QQmlScript::Variant &QQmlScript::Variant::operator=(const Variant &o)
-{
- t = o.t;
- d = o.d;
- asWritten = o.asWritten;
- return *this;
-}
-
-QQmlScript::Variant::Type QQmlScript::Variant::type() const
-{
- return t;
-}
-
-bool QQmlScript::Variant::asBoolean() const
-{
- return b;
-}
-
-QString QQmlScript::Variant::asString() const
-{
- if (t == String) {
- return l->value.toString();
- } else {
- return asWritten.toString();
- }
-}
-
-double QQmlScript::Variant::asNumber() const
-{
- return d;
-}
-
-//reverse of Lexer::singleEscape()
-QString escapedString(const QString &string)
-{
- QString tmp = QLatin1String("\"");
- for (int i = 0; i < string.length(); ++i) {
- const QChar &c = string.at(i);
- switch(c.unicode()) {
- case 0x08:
- tmp += QLatin1String("\\b");
- break;
- case 0x09:
- tmp += QLatin1String("\\t");
- break;
- case 0x0A:
- tmp += QLatin1String("\\n");
- break;
- case 0x0B:
- tmp += QLatin1String("\\v");
- break;
- case 0x0C:
- tmp += QLatin1String("\\f");
- break;
- case 0x0D:
- tmp += QLatin1String("\\r");
- break;
- case 0x22:
- tmp += QLatin1String("\\\"");
- break;
- case 0x27:
- tmp += QLatin1String("\\\'");
- break;
- case 0x5C:
- tmp += QLatin1String("\\\\");
- break;
- default:
- tmp += c;
- break;
- }
- }
- tmp += QLatin1Char('\"');
- return tmp;
-}
-
-QString QQmlScript::Variant::asScript() const
-{
- switch (type()) {
- default:
- case Invalid:
- return QString();
- case Boolean:
- return b?QLatin1String("true"):QLatin1String("false");
- case Number:
- if (asWritten.isEmpty())
- return QString::number(d);
- else
- return asWritten.toString();
- case String:
- return escapedString(asString());
- case Script:
- if (AST::IdentifierExpression *i = AST::cast<AST::IdentifierExpression *>(n)) {
- return i->name.toString();
- } else
- return asWritten.toString();
- }
-}
-
-QQmlJS::AST::Node *QQmlScript::Variant::asAST() const
-{
- if (type() == Script)
- return n;
- else
- return 0;
-}
-
-bool QQmlScript::Variant::isStringList() const
-{
- if (isString())
- return true;
-
- if (type() != Script || !n)
- return false;
-
- AST::ArrayLiteral *array = AST::cast<AST::ArrayLiteral *>(n);
- if (!array)
- return false;
-
- AST::ElementList *elements = array->elements;
-
- while (elements) {
-
- if (!AST::cast<AST::StringLiteral *>(elements->expression))
- return false;
-
- elements = elements->next;
- }
-
- return true;
-}
-
-QStringList QQmlScript::Variant::asStringList() const
-{
- QStringList rv;
- if (isString()) {
- rv << asString();
- return rv;
- }
-
- AST::ArrayLiteral *array = AST::cast<AST::ArrayLiteral *>(n);
- if (!array)
- return rv;
-
- AST::ElementList *elements = array->elements;
- while (elements) {
-
- AST::StringLiteral *string = AST::cast<AST::StringLiteral *>(elements->expression);
- if (!string)
- return QStringList();
- rv.append(string->value.toString());
-
- elements = elements->next;
- }
-
- return rv;
-}
-
-//
-// Actual parser classes
-//
-namespace {
-
-class ProcessAST: protected AST::Visitor
-{
- struct State {
- State() : object(0), property(0) {}
- State(QQmlScript::Object *o) : object(o), property(0) {}
- State(QQmlScript::Object *o, Property *p) : object(o), property(p) {}
-
- QQmlScript::Object *object;
- Property *property;
- };
-
- struct StateStack : public QStack<State>
- {
- void pushObject(QQmlScript::Object *obj)
- {
- push(State(obj));
- }
-
- void pushProperty(const QString &name, const LocationSpan &location)
- {
- const State &state = top();
- if (state.property) {
- State s(state.property->getValue(location),
- state.property->getValue(location)->getProperty(name));
- s.property->location = location;
- push(s);
- } else {
- State s(state.object, state.object->getProperty(name));
-
- s.property->location = location;
- push(s);
- }
- }
-
- void pushProperty(const QStringRef &name, const LocationSpan &location)
- {
- const State &state = top();
- if (state.property) {
- State s(state.property->getValue(location),
- state.property->getValue(location)->getProperty(name));
- s.property->location = location;
- push(s);
- } else {
- State s(state.object, state.object->getProperty(name));
-
- s.property->location = location;
- push(s);
- }
- }
- };
-
-public:
- ProcessAST(QQmlScript::Parser *parser);
- virtual ~ProcessAST();
-
- void operator()(const QString &code, AST::Node *node);
-
- static void extractVersion(QStringRef string, int *maj, int *min);
-
-protected:
-
- QQmlScript::Object *defineObjectBinding(AST::Node *node, AST::UiQualifiedId *propertyName, bool onAssignment,
- const QString &objectType,
- AST::SourceLocation typeLocation,
- LocationSpan location,
- AST::UiObjectInitializer *initializer = 0);
-
- QQmlScript::Variant getVariant(AST::Statement *stmt);
- QQmlScript::Variant getVariant(AST::ExpressionNode *expr);
-
- LocationSpan location(AST::SourceLocation start, AST::SourceLocation end);
- LocationSpan location(AST::UiQualifiedId *);
-
- using AST::Visitor::visit;
- using AST::Visitor::endVisit;
-
- virtual bool visit(AST::UiProgram *node);
- virtual bool visit(AST::UiImport *node);
- virtual bool visit(AST::UiPragma *node);
- virtual bool visit(AST::UiObjectDefinition *node);
- virtual bool visit(AST::UiPublicMember *node);
- virtual bool visit(AST::UiObjectBinding *node);
-
- virtual bool visit(AST::UiScriptBinding *node);
- virtual bool visit(AST::UiArrayBinding *node);
- virtual bool visit(AST::UiSourceElement *node);
-
- void accept(AST::Node *node);
-
- QString asString(AST::UiQualifiedId *node) const;
-
- const State state() const;
- QQmlScript::Object *currentObject() const;
- Property *currentProperty() const;
-
- QString textAt(const AST::SourceLocation &loc) const
- { return _contents->mid(loc.offset, loc.length); }
-
- QStringRef textRefAt(const AST::SourceLocation &loc) const
- { return QStringRef(_contents, loc.offset, loc.length); }
-
- QString textAt(const AST::SourceLocation &first,
- const AST::SourceLocation &last) const
- { return _contents->mid(first.offset, last.offset + last.length - first.offset); }
-
- QStringRef textRefAt(const AST::SourceLocation &first,
- const AST::SourceLocation &last) const
- { return QStringRef(_contents, first.offset, last.offset + last.length - first.offset); }
-
- QString asString(AST::ExpressionNode *expr)
- {
- if (! expr)
- return QString();
-
- return textAt(expr->firstSourceLocation(), expr->lastSourceLocation());
- }
-
- QStringRef asStringRef(AST::ExpressionNode *expr)
- {
- if (! expr)
- return QStringRef();
-
- return textRefAt(expr->firstSourceLocation(), expr->lastSourceLocation());
- }
-
- QString asString(AST::Statement *stmt)
- {
- if (! stmt)
- return QString();
-
- QString s = textAt(stmt->firstSourceLocation(), stmt->lastSourceLocation());
- s += QLatin1Char('\n');
- return s;
- }
-
- QStringRef asStringRef(AST::Statement *stmt)
- {
- if (! stmt)
- return QStringRef();
-
- return textRefAt(stmt->firstSourceLocation(), stmt->lastSourceLocation());
- }
-
-private:
- QQmlScript::Parser *_parser;
- StateStack _stateStack;
- const QString *_contents;
-};
-
-ProcessAST::ProcessAST(QQmlScript::Parser *parser)
- : _parser(parser)
-{
-}
-
-ProcessAST::~ProcessAST()
-{
-}
-
-void ProcessAST::operator()(const QString &code, AST::Node *node)
-{
- _contents = &code;
- accept(node);
-}
-
-void ProcessAST::accept(AST::Node *node)
-{
- AST::Node::acceptChild(node, this);
-}
-
-const ProcessAST::State ProcessAST::state() const
-{
- if (_stateStack.isEmpty())
- return State();
-
- return _stateStack.back();
-}
-
-QQmlScript::Object *ProcessAST::currentObject() const
-{
- return state().object;
-}
-
-Property *ProcessAST::currentProperty() const
-{
- return state().property;
-}
-
-void ProcessAST::extractVersion(QStringRef string, int *maj, int *min)
-{
- *maj = -1; *min = -1;
-
- if (!string.isEmpty()) {
-
- int dot = string.indexOf(QLatin1Char('.'));
-
- if (dot < 0) {
- *maj = string.toInt();
- *min = 0;
- } else {
- *maj = string.left(dot).toInt();
- *min = string.mid(dot + 1).toInt();
- }
- }
-}
-
-QString ProcessAST::asString(AST::UiQualifiedId *node) const
-{
- QString s;
-
- for (AST::UiQualifiedId *it = node; it; it = it->next) {
- s.append(it->name);
-
- if (it->next)
- s.append(QLatin1Char('.'));
- }
-
- return s;
-}
-
-QQmlScript::Object *
-ProcessAST::defineObjectBinding(AST::Node *node,
- AST::UiQualifiedId *propertyName,
- bool onAssignment,
- const QString &objectType,
- AST::SourceLocation typeLocation,
- LocationSpan location,
- AST::UiObjectInitializer *initializer)
-{
- int lastTypeDot = objectType.lastIndexOf(QLatin1Char('.'));
-
- // With no preceding qualification, first char is at (-1 + 1) == 0
- bool isType = !objectType.isEmpty() && objectType.at(lastTypeDot+1).isUpper();
-
- int propertyCount = 0;
- for (AST::UiQualifiedId *name = propertyName; name; name = name->next){
- ++propertyCount;
- _stateStack.pushProperty(name->name,
- this->location(name));
- }
-
- if (!onAssignment && propertyCount && currentProperty() && !currentProperty()->values.isEmpty()) {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","Property value set multiple times"));
- error.setLine(this->location(propertyName).start.line);
- error.setColumn(this->location(propertyName).start.column);
- _parser->_errors << error;
- return 0;
- }
-
- if (!isType) {
-
- // Is the identifier qualified by a namespace?
- int namespaceLength = 0;
- if (lastTypeDot > 0) {
- const QString qualifier(objectType.left(lastTypeDot));
-
- for (int ii = 0; ii < _parser->_imports.count(); ++ii) {
- const QQmlScript::Import &import = _parser->_imports.at(ii);
- if (import.qualifier == qualifier) {
- // The qualifier is a namespace - expect a type here
- namespaceLength = qualifier.length() + 1;
- break;
- }
- }
- }
-
- if (propertyCount || !currentObject() || namespaceLength) {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","Expected type name"));
- error.setLine(typeLocation.startLine);
- error.setColumn(typeLocation.startColumn + namespaceLength);
- _parser->_errors << error;
- return 0;
- }
-
- LocationSpan loc = ProcessAST::location(typeLocation, typeLocation);
- if (propertyName)
- loc = ProcessAST::location(propertyName);
-
- _stateStack.pushProperty(objectType, loc);
- accept(initializer);
- _stateStack.pop();
-
- return 0;
-
- } else {
- // Class
-
- QQmlScript::Object *obj = _parser->_pool.New<QQmlScript::Object>();
-
- obj->type = _parser->findOrCreateTypeId(objectType, obj);
- obj->typeReference = _parser->_refTypes.at(obj->type);
- obj->location = location;
- obj->astNode = node;
-
- if (propertyCount) {
- Property *prop = currentProperty();
- QQmlScript::Value *v = _parser->_pool.New<QQmlScript::Value>();
- v->object = obj;
- v->location = obj->location;
- if (onAssignment)
- prop->addOnValue(v);
- else
- prop->addValue(v);
-
- while (propertyCount--)
- _stateStack.pop();
-
- } else {
-
- if (! _parser->tree()) {
- _parser->setTree(obj);
- } else {
- const State state = _stateStack.top();
- QQmlScript::Value *v = _parser->_pool.New<QQmlScript::Value>();
- v->object = obj;
- v->location = obj->location;
- if (state.property) {
- state.property->addValue(v);
- } else {
- Property *defaultProp = state.object->getDefaultProperty();
- if (defaultProp->location.start.line == 0) {
- defaultProp->location = v->location;
- defaultProp->location.end = defaultProp->location.start;
- defaultProp->location.range.length = 0;
- }
- defaultProp->addValue(v);
- }
- }
- }
-
- _stateStack.pushObject(obj);
- accept(initializer);
- _stateStack.pop();
-
- return obj;
- }
-}
-
-LocationSpan ProcessAST::location(AST::UiQualifiedId *id)
-{
- return location(id->identifierToken, id->identifierToken);
-}
-
-LocationSpan ProcessAST::location(AST::SourceLocation start, AST::SourceLocation end)
-{
- LocationSpan rv;
- rv.start.line = start.startLine;
- rv.start.column = start.startColumn;
- rv.end.line = end.startLine;
- rv.end.column = end.startColumn + end.length - 1;
- rv.range.offset = start.offset;
- rv.range.length = end.offset + end.length - start.offset;
- return rv;
-}
-
-// UiProgram: UiHeaderItemListOpt UiObjectMemberList ;
-bool ProcessAST::visit(AST::UiProgram *node)
-{
- accept(node->headers);
- accept(node->members->member);
- return false;
-}
-
-// UiImport: T_IMPORT T_STRING_LITERAL ;
-bool ProcessAST::visit(AST::UiImport *node)
-{
- QString uri;
- QQmlScript::Import import;
-
- if (!node->fileName.isNull()) {
- uri = node->fileName.toString();
-
- if (uri.endsWith(QLatin1String(".js"))) {
- import.type = QQmlScript::Import::Script;
- } else {
- import.type = QQmlScript::Import::File;
- }
- } else {
- import.type = QQmlScript::Import::Library;
- uri = asString(node->importUri);
- }
-
- AST::SourceLocation startLoc = node->importToken;
- AST::SourceLocation endLoc = node->semicolonToken;
-
- // Qualifier
- if (!node->importId.isNull()) {
- import.qualifier = node->importId.toString();
- if (!import.qualifier.at(0).isUpper()) {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","Invalid import qualifier ID"));
- error.setLine(node->importIdToken.startLine);
- error.setColumn(node->importIdToken.startColumn);
- _parser->_errors << error;
- return false;
- }
- if (import.qualifier == QLatin1String("Qt")) {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","Reserved name \"Qt\" cannot be used as an qualifier"));
- error.setLine(node->importIdToken.startLine);
- error.setColumn(node->importIdToken.startColumn);
- _parser->_errors << error;
- return false;
- }
-
- // Check for script qualifier clashes
- bool isScript = import.type == QQmlScript::Import::Script;
- for (int ii = 0; ii < _parser->_imports.count(); ++ii) {
- const QQmlScript::Import &other = _parser->_imports.at(ii);
- bool otherIsScript = other.type == QQmlScript::Import::Script;
-
- if ((isScript || otherIsScript) && import.qualifier == other.qualifier) {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","Script import qualifiers must be unique."));
- error.setLine(node->importIdToken.startLine);
- error.setColumn(node->importIdToken.startColumn);
- _parser->_errors << error;
- return false;
- }
- }
-
- } else if (import.type == QQmlScript::Import::Script) {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","Script import requires a qualifier"));
- error.setLine(node->fileNameToken.startLine);
- error.setColumn(node->fileNameToken.startColumn);
- _parser->_errors << error;
- return false;
- }
-
- if (node->versionToken.isValid()) {
- extractVersion(textRefAt(node->versionToken), &import.majorVersion, &import.minorVersion);
- } else if (import.type == QQmlScript::Import::Library) {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","Library import requires a version"));
- error.setLine(node->importIdToken.startLine);
- error.setColumn(node->importIdToken.startColumn);
- _parser->_errors << error;
- return false;
- }
-
-
- import.location = location(startLoc, endLoc);
- import.uri = uri;
-
- _parser->_imports << import;
-
- return false;
-}
-
-bool ProcessAST::visit(AST::UiPragma *node)
-{
- QQmlScript::Pragma pragma;
-
- // For now the only valid pragma is Singleton, so lets validate the input
- if (!node->pragmaType->name.isNull())
- {
- if (QLatin1String("Singleton") == node->pragmaType->name)
- {
- pragma.type = QQmlScript::Pragma::Singleton;
- } else {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","Pragma requires a valid qualifier"));
- error.setLine(node->pragmaToken.startLine);
- error.setColumn(node->pragmaToken.startColumn);
- _parser->_errors << error;
- return false;
- }
- } else {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","Pragma requires a valid qualifier"));
- error.setLine(node->pragmaToken.startLine);
- error.setColumn(node->pragmaToken.startColumn);
- _parser->_errors << error;
- return false;
- }
-
- AST::SourceLocation startLoc = node->pragmaToken;
- AST::SourceLocation endLoc = node->semicolonToken;
- pragma.location = location(startLoc, endLoc);
- _parser->_pragmas << pragma;
-
- return false;
-}
-
-bool ProcessAST::visit(AST::UiPublicMember *node)
-{
- static const struct TypeNameToType {
- const char *name;
- size_t nameLength;
- Object::DynamicProperty::Type type;
- } propTypeNameToTypes[] = {
- { "int", strlen("int"), Object::DynamicProperty::Int },
- { "bool", strlen("bool"), Object::DynamicProperty::Bool },
- { "double", strlen("double"), Object::DynamicProperty::Real },
- { "real", strlen("real"), Object::DynamicProperty::Real },
- { "string", strlen("string"), Object::DynamicProperty::String },
- { "url", strlen("url"), Object::DynamicProperty::Url },
- { "color", strlen("color"), Object::DynamicProperty::Color },
- // Internally QTime, QDate and QDateTime are all supported.
- // To be more consistent with JavaScript we expose only
- // QDateTime as it matches closely with the Date JS type.
- // We also call it "date" to match.
- // { "time", strlen("time"), Object::DynamicProperty::Time },
- // { "date", strlen("date"), Object::DynamicProperty::Date },
- { "date", strlen("date"), Object::DynamicProperty::DateTime },
- { "rect", strlen("rect"), Object::DynamicProperty::Rect },
- { "point", strlen("point"), Object::DynamicProperty::Point },
- { "size", strlen("size"), Object::DynamicProperty::Size },
- { "font", strlen("font"), Object::DynamicProperty::Font },
- { "vector2d", strlen("vector2d"), Object::DynamicProperty::Vector2D },
- { "vector3d", strlen("vector3d"), Object::DynamicProperty::Vector3D },
- { "vector4d", strlen("vector4d"), Object::DynamicProperty::Vector4D },
- { "quaternion", strlen("quaternion"), Object::DynamicProperty::Quaternion },
- { "matrix4x4", strlen("matrix4x4"), Object::DynamicProperty::Matrix4x4 },
- { "variant", strlen("variant"), Object::DynamicProperty::Variant },
- { "var", strlen("var"), Object::DynamicProperty::Var }
- };
- static const int propTypeNameToTypesCount = sizeof(propTypeNameToTypes) /
- sizeof(propTypeNameToTypes[0]);
-
- if(node->type == AST::UiPublicMember::Signal) {
- Object::DynamicSignal *signal = _parser->_pool.New<Object::DynamicSignal>();
- signal->name = node->name;
-
- AST::UiParameterList *p = node->parameters;
- int paramLength = 0;
- while (p) { paramLength++; p = p->next; }
- p = node->parameters;
-
- if (paramLength) {
- signal->parameterTypes = _parser->_pool.NewRawList<Object::DynamicProperty::Type>(paramLength);
- signal->parameterTypeNames = _parser->_pool.NewRawList<QHashedStringRef>(paramLength);
- signal->parameterNames = _parser->_pool.NewRawList<QHashedStringRef>(paramLength);
- }
-
- int index = 0;
- while (p) {
- const QStringRef &memberType = p->type;
-
- if (memberType.isEmpty()) {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","Expected parameter type"));
- error.setLine(node->typeToken.startLine);
- error.setColumn(node->typeToken.startColumn);
- _parser->_errors << error;
- return false;
- }
-
- const TypeNameToType *type = 0;
- for(int typeIndex = 0; typeIndex < propTypeNameToTypesCount; ++typeIndex) {
- const TypeNameToType *t = propTypeNameToTypes + typeIndex;
- if (t->nameLength == size_t(memberType.length()) &&
- QHashedString::compare(memberType.constData(), t->name, int(t->nameLength))) {
- type = t;
- break;
- }
- }
-
- if (!type) {
- if (memberType.at(0).isUpper()) {
- // Must be a QML object type.
- // Lazily determine type during compilation.
- signal->parameterTypes[index] = Object::DynamicProperty::Custom;
- signal->parameterTypeNames[index] = QHashedStringRef(p->type);
- } else {
- QQmlError error;
- QString errStr = QCoreApplication::translate("QQmlParser","Invalid signal parameter type: ");
- errStr.append(memberType.toString());
- error.setDescription(errStr);
- error.setLine(node->typeToken.startLine);
- error.setColumn(node->typeToken.startColumn);
- _parser->_errors << error;
- return false;
- }
- } else {
- // the parameter is a known basic type
- signal->parameterTypes[index] = type->type;
- }
-
- signal->parameterNames[index] = QHashedStringRef(p->name);
- p = p->next;
- index++;
- }
-
- signal->location = location(node->typeToken, node->semicolonToken);
- _stateStack.top().object->dynamicSignals.append(signal);
- } else {
- const QStringRef &memberType = node->memberType;
- const QStringRef &name = node->name;
-
- bool typeFound = false;
- Object::DynamicProperty::Type type;
-
- if ((unsigned)memberType.length() == strlen("alias") &&
- QHashedString::compare(memberType.constData(), "alias", int(strlen("alias")))) {
- type = Object::DynamicProperty::Alias;
- typeFound = true;
- }
-
- for(int ii = 0; !typeFound && ii < propTypeNameToTypesCount; ++ii) {
- const TypeNameToType *t = propTypeNameToTypes + ii;
- if (t->nameLength == size_t(memberType.length()) &&
- QHashedString::compare(memberType.constData(), t->name, int(t->nameLength))) {
- type = t->type;
- typeFound = true;
- }
- }
-
- if (!typeFound && memberType.at(0).isUpper()) {
- const QStringRef &typeModifier = node->typeModifier;
-
- if (typeModifier.isEmpty()) {
- type = Object::DynamicProperty::Custom;
- } else if ((unsigned)typeModifier.length() == strlen("list") &&
- QHashedString::compare(typeModifier.constData(), "list", int(strlen("list")))) {
- type = Object::DynamicProperty::CustomList;
- } else {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","Invalid property type modifier"));
- error.setLine(node->typeModifierToken.startLine);
- error.setColumn(node->typeModifierToken.startColumn);
- _parser->_errors << error;
- return false;
- }
- typeFound = true;
- } else if (!node->typeModifier.isNull()) {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","Unexpected property type modifier"));
- error.setLine(node->typeModifierToken.startLine);
- error.setColumn(node->typeModifierToken.startColumn);
- _parser->_errors << error;
- return false;
- }
-
- if(!typeFound) {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","Expected property type"));
- error.setLine(node->typeToken.startLine);
- error.setColumn(node->typeToken.startColumn);
- _parser->_errors << error;
- return false;
- }
-
- Object::DynamicProperty *property = _parser->_pool.New<Object::DynamicProperty>();
- property->isDefaultProperty = node->isDefaultMember;
- property->isReadOnly = node->isReadonlyMember;
- property->type = type;
- property->nameLocation.line = node->identifierToken.startLine;
- property->nameLocation.column = node->identifierToken.startColumn;
- if (type >= Object::DynamicProperty::Custom) {
- // This forces the type to be added to the resolved types list
- _parser->findOrCreateTypeId(memberType.toString(), _stateStack.top().object);
- property->customType = memberType;
- }
-
- property->name = QHashedStringRef(name);
- property->location = location(node->firstSourceLocation(),
- node->lastSourceLocation());
-
- if (node->statement) { // default value
- property->defaultValue = _parser->_pool.New<Property>();
- property->defaultValue->parent = _stateStack.top().object;
- property->defaultValue->location =
- location(node->statement->firstSourceLocation(),
- node->statement->lastSourceLocation());
- QQmlScript::Value *value = _parser->_pool.New<QQmlScript::Value>();
- value->location = location(node->statement->firstSourceLocation(),
- node->statement->lastSourceLocation());
- value->value = getVariant(node->statement);
- property->defaultValue->values.append(value);
- }
-
- _stateStack.top().object->dynamicProperties.append(property);
-
- // process QML-like initializers (e.g. property Object o: Object {})
- accept(node->binding);
- }
-
- return false;
-}
-
-
-// UiObjectMember: UiQualifiedId UiObjectInitializer ;
-bool ProcessAST::visit(AST::UiObjectDefinition *node)
-{
- LocationSpan l = location(node->firstSourceLocation(),
- node->lastSourceLocation());
-
- const QString objectType = asString(node->qualifiedTypeNameId);
- const AST::SourceLocation typeLocation = node->qualifiedTypeNameId->identifierToken;
-
- defineObjectBinding(node, /*propertyName = */ 0, false, objectType,
- typeLocation, l, node->initializer);
-
- return false;
-}
-
-
-// UiObjectMember: UiQualifiedId T_COLON UiQualifiedId UiObjectInitializer ;
-bool ProcessAST::visit(AST::UiObjectBinding *node)
-{
- LocationSpan l = location(node->qualifiedTypeNameId->identifierToken,
- node->initializer->rbraceToken);
-
- const QString objectType = asString(node->qualifiedTypeNameId);
- const AST::SourceLocation typeLocation = node->qualifiedTypeNameId->identifierToken;
-
- defineObjectBinding(node, node->qualifiedId, node->hasOnToken, objectType,
- typeLocation, l, node->initializer);
-
- return false;
-}
-
-QQmlScript::Variant ProcessAST::getVariant(AST::Statement *stmt)
-{
- if (stmt) {
- if (AST::ExpressionStatement *exprStmt = AST::cast<AST::ExpressionStatement *>(stmt))
- return getVariant(exprStmt->expression);
-
- return QQmlScript::Variant(asStringRef(stmt), stmt);
- }
-
- return QQmlScript::Variant();
-}
-
-QQmlScript::Variant ProcessAST::getVariant(AST::ExpressionNode *expr)
-{
- if (AST::StringLiteral *lit = AST::cast<AST::StringLiteral *>(expr)) {
- return QQmlScript::Variant(lit);
- } else if (expr->kind == AST::Node::Kind_TrueLiteral) {
- return QQmlScript::Variant(true);
- } else if (expr->kind == AST::Node::Kind_FalseLiteral) {
- return QQmlScript::Variant(false);
- } else if (AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(expr)) {
- return QQmlScript::Variant(lit->value, asStringRef(expr));
- } else {
-
- if (AST::UnaryMinusExpression *unaryMinus = AST::cast<AST::UnaryMinusExpression *>(expr)) {
- if (AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(unaryMinus->expression)) {
- return QQmlScript::Variant(-lit->value, asStringRef(expr));
- }
- }
-
- return QQmlScript::Variant(asStringRef(expr), expr);
- }
-}
-
-
-// UiObjectMember: UiQualifiedId T_COLON Statement ;
-bool ProcessAST::visit(AST::UiScriptBinding *node)
-{
- int propertyCount = 0;
- AST::UiQualifiedId *propertyName = node->qualifiedId;
- for (AST::UiQualifiedId *name = propertyName; name; name = name->next){
- ++propertyCount;
- _stateStack.pushProperty(name->name,
- location(name));
- }
-
- Property *prop = currentProperty();
-
- if (!prop->values.isEmpty()) {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","Property value set multiple times"));
- error.setLine(this->location(propertyName).start.line);
- error.setColumn(this->location(propertyName).start.column);
- _parser->_errors << error;
- return 0;
- }
-
- QQmlScript::Variant primitive;
-
- if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(node->statement)) {
- primitive = getVariant(stmt->expression);
- } else { // do binding
- primitive = QQmlScript::Variant(asStringRef(node->statement), node->statement);
- }
-
- prop->location.range.length = prop->location.range.offset + prop->location.range.length - node->qualifiedId->identifierToken.offset;
- prop->location.range.offset = node->qualifiedId->identifierToken.offset;
- QQmlScript::Value *v = _parser->_pool.New<QQmlScript::Value>();
- v->value = primitive;
- v->location = location(node->statement->firstSourceLocation(),
- node->statement->lastSourceLocation());
-
- prop->addValue(v);
-
- while (propertyCount--)
- _stateStack.pop();
-
- return false;
-}
-
-// UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ;
-bool ProcessAST::visit(AST::UiArrayBinding *node)
-{
- int propertyCount = 0;
- AST::UiQualifiedId *propertyName = node->qualifiedId;
- for (AST::UiQualifiedId *name = propertyName; name; name = name->next){
- ++propertyCount;
- _stateStack.pushProperty(name->name,
- location(name));
- }
-
- Property* prop = currentProperty();
-
- if (!prop->values.isEmpty()) {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","Property value set multiple times"));
- error.setLine(this->location(propertyName).start.line);
- error.setColumn(this->location(propertyName).start.column);
- _parser->_errors << error;
- return false;
- }
-
- accept(node->members);
-
- // For the DOM, store the position of the T_LBRACKET upto the T_RBRACKET as the range:
- prop->listValueRange.offset = node->lbracketToken.offset;
- prop->listValueRange.length = node->rbracketToken.offset + node->rbracketToken.length - node->lbracketToken.offset;
-
- while (propertyCount--)
- _stateStack.pop();
-
- return false;
-}
-
-bool ProcessAST::visit(AST::UiSourceElement *node)
-{
- QQmlScript::Object *obj = currentObject();
-
- if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) {
-
- Object::DynamicSlot *slot = _parser->_pool.New<Object::DynamicSlot>();
- slot->location = location(funDecl->identifierToken, funDecl->lastSourceLocation());
-
- AST::FormalParameterList *f = funDecl->formals;
- while (f) {
- slot->parameterNames << f->name.toUtf8();
- f = f->next;
- }
-
- AST::SourceLocation loc = funDecl->rparenToken;
- loc.offset = loc.end();
- loc.startColumn += 1;
- slot->name = funDecl->name;
- slot->funcDecl = funDecl;
- obj->dynamicSlots.append(slot);
-
- } else {
- QQmlError error;
- error.setDescription(QCoreApplication::translate("QQmlParser","JavaScript declaration outside Script element"));
- error.setLine(node->firstSourceLocation().startLine);
- error.setColumn(node->firstSourceLocation().startColumn);
- _parser->_errors << error;
- }
- return false;
-}
-
-} // end of anonymous namespace
-
-
-QQmlScript::Parser::Parser()
-: root(0), _qmlRoot(0), data(0)
-{
-
-}
-
-QQmlScript::Parser::~Parser()
-{
- clear();
-}
-
-namespace QQmlScript {
-class ParserJsASTData
-{
-public:
- ParserJsASTData(const QString &filename)
- : filename(filename) {}
-
- QString filename;
- Engine engine;
-};
-}
-
-QByteArray QQmlScript::Parser::preparseData() const
-{
- return QByteArray();
-}
-
-bool QQmlScript::Parser::parse(const QString &qmlcode, const QByteArray & /* preparseData */,
- const QUrl &url, const QString &urlString)
-{
- clear();
-
- if (urlString.isEmpty()) {
- _scriptFile = url.toString();
- } else {
- // Q_ASSERT(urlString == url.toString());
- _scriptFile = urlString;
- }
-
- QString *code = _pool.NewString(qmlcode);
-
- data = new QQmlScript::ParserJsASTData(_scriptFile);
-
- Lexer lexer(&data->engine);
- lexer.setCode(*code, /*line = */ 1);
-
- QQmlJS::Parser parser(&data->engine);
-
- if (! parser.parse() || !parser.diagnosticMessages().isEmpty()) {
-
- // Extract errors from the parser
- foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) {
-
- if (m.isWarning()) {
- qWarning("%s:%d : %s", qPrintable(_scriptFile), m.loc.startLine, qPrintable(m.message));
- continue;
- }
-
- QQmlError error;
- error.setUrl(url);
- error.setDescription(m.message);
- error.setLine(m.loc.startLine);
- error.setColumn(m.loc.startColumn);
- _errors << error;
-
- }
- }
-
- if (_errors.isEmpty()) {
- ProcessAST process(this);
- process(*code, parser.ast());
-
- // Set the url for process errors
- for(int ii = 0; ii < _errors.count(); ++ii)
- _errors[ii].setUrl(url);
- }
-
- _qmlRoot = parser.ast();
-
- return _errors.isEmpty();
-}
-
-QList<QQmlScript::TypeReference*> QQmlScript::Parser::referencedTypes() const
-{
- return _refTypes;
-}
-
-QQmlScript::Object *QQmlScript::Parser::tree() const
-{
- return root;
-}
-
-QList<QQmlScript::Import> QQmlScript::Parser::imports() const
-{
- return _imports;
-}
-
-QList<QQmlScript::Pragma> QQmlScript::Parser::pragmas() const
-{
- return _pragmas;
-}
-
-QList<QQmlError> QQmlScript::Parser::errors() const
-{
- return _errors;
-}
-
static void replaceWithSpace(QString &str, int idx, int n)
{
QChar *data = str.data() + idx;
@@ -1540,6 +187,24 @@ static inline bool isUriToken(int token)
return false;
}
+static void extractVersion(QStringRef string, int *maj, int *min)
+{
+ *maj = -1; *min = -1;
+
+ if (!string.isEmpty()) {
+
+ int dot = string.indexOf(QLatin1Char('.'));
+
+ if (dot < 0) {
+ *maj = string.toInt();
+ *min = 0;
+ } else {
+ *maj = string.left(dot).toInt();
+ *min = string.mid(dot + 1).toInt();
+ }
+ }
+}
+
QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QString &script, QQmlError *error)
{
Q_ASSERT(error);
@@ -1670,7 +335,7 @@ QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QStri
}
int vmaj, vmin;
- ProcessAST::extractVersion(QStringRef(&script, l.tokenOffset(), l.tokenLength()),
+ extractVersion(QStringRef(&script, l.tokenOffset(), l.tokenLength()),
&vmaj, &vmin);
bool invalidImport = false;
@@ -1749,46 +414,4 @@ QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QStri
return rv;
}
-void QQmlScript::Parser::clear()
-{
- _pragmas.clear();
- _imports.clear();
- _refTypes.clear();
- _errors.clear();
-
- if (data) {
- delete data;
- data = 0;
- }
-
- _pool.clear();
- _qmlRoot = 0;
-}
-
-int QQmlScript::Parser::findOrCreateTypeId(const QString &name, Object *object)
-{
- for (int ii = 0; ii < _refTypes.size(); ++ii) {
- if (_refTypes.at(ii)->name == name)
- return ii;
- }
-
- TypeReference *type = _pool.New<TypeReference>();
- type->name = name;
- type->firstUse = object;
- _refTypes.append(type);
- return _refTypes.size() - 1;
-}
-
-void QQmlScript::Parser::setTree(QQmlScript::Object *tree)
-{
- Q_ASSERT(! root);
-
- root = tree;
-}
-
-Engine *QQmlScript::Parser::jsEngine() const
-{
- return data ? &data->engine : 0;
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlscript_p.h b/src/qml/qml/qqmlscript_p.h
index 29da97fe83..15446c089f 100644
--- a/src/qml/qml/qqmlscript_p.h
+++ b/src/qml/qml/qqmlscript_p.h
@@ -68,7 +68,6 @@ QT_BEGIN_NAMESPACE
class QByteArray;
class QQmlPropertyCache;
namespace QQmlJS { class Engine; namespace AST { class Node; class StringLiteral; class UiProgram; class FunctionDeclaration; } }
-namespace QQmlCompilerTypes { struct BindingReference; struct ComponentCompileState; }
namespace QQmlScript {
@@ -137,241 +136,11 @@ class TypeReference : public QQmlPool::Class
public:
// type as it has been referenced in Qml
QString name;
- // The first use of this type in the parse tree. Useful for error locations.
- QQmlScript::Object *firstUse;
-};
-
-class Object;
-class Property;
-
-class Q_QML_PRIVATE_EXPORT Variant
-{
-public:
- enum Type {
- Invalid,
- Boolean,
- Number,
- String,
- Script
- };
-
- Variant();
- Variant(const Variant &);
- explicit Variant(bool);
- explicit Variant(double, const QStringRef &asWritten = QStringRef());
- explicit Variant(QQmlJS::AST::StringLiteral *);
- explicit Variant(const QStringRef &asWritten, QQmlJS::AST::Node *);
- Variant &operator=(const Variant &);
-
- Type type() const;
-
- bool isBoolean() const { return type() == Boolean; }
- bool isNumber() const { return type() == Number; }
- bool isString() const { return type() == String; }
- bool isScript() const { return type() == Script; }
- bool isStringList() const;
-
- bool asBoolean() const;
- QString asString() const;
- double asNumber() const;
- QString asScript() const;
- QQmlJS::AST::Node *asAST() const;
- QStringList asStringList() const;
-
-private:
- Type t;
- union {
- bool b;
- double d;
- QQmlJS::AST::StringLiteral *l;
- QQmlJS::AST::Node *n;
- };
- QStringRef asWritten;
-};
-
-class Value : public QQmlPool::POD
-{
-public:
- Value();
-
- enum Type {
- // The type of this value assignment is not yet known
- Unknown,
- // This is used as a literal property assignment
- Literal,
- // This is used as a property binding assignment
- PropertyBinding,
- // This is used as a QQmlPropertyValueSource assignment
- ValueSource,
- // This is used as a QQmlPropertyValueInterceptor assignment
- ValueInterceptor,
- // This is used as a property QObject assignment
- CreatedObject,
- // This is used as a signal object assignment
- SignalObject,
- // This is used as a signal expression assignment
- SignalExpression,
- // This is used as an id assignment only
- Id
- };
- Type type;
-
- // ### Temporary (for id only)
- QString primitive() const { return value.isString() ? value.asString() : value.asScript(); }
-
- // Primitive value
- Variant value;
- // Object value
- Object *object;
-
- LocationSpan location;
-
- // Used by compiler
- struct SignalData {
- int signalExpressionContextStack;
- Object *signalScopeObject;
- int functionIndex; // before gen() index in functionsToCompile, then index in runtime functions
- };
- union {
- QQmlCompilerTypes::BindingReference *bindingReference;
- SignalData signalData;
- };
-
- // Used in Property::ValueList lists
- Value *nextValue;
-};
-
-class Property : public QQmlPool::POD
-{
-public:
- Property();
-
- // The Object to which this property is attached
- Object *parent;
-
- Object *getValue(const LocationSpan &);
- void addValue(Value *v);
- void addOnValue(Value *v);
-
- // The QVariant::Type of the property, or 0 (QVariant::Invalid) if
- // unknown.
- int type;
- // The metaobject index of this property, or -1 if unknown.
- int index;
- // The core data in the case of a regular property.
- // XXX This has to be a value now as the synthCache may change during
- // compilation which invalidates pointers. We should fix this.
- QQmlPropertyData core;
-
- // Returns true if this is an empty property - both value and values
- // are unset.
- bool isEmpty() const;
-
- typedef QFieldList<Value, &Value::nextValue> ValueList;
- // The list of values assigned to this property. Content in values
- // and value are mutually exclusive
- ValueList values;
- // The list of values assigned to this property using the "on" syntax
- ValueList onValues;
- // The accessed property. This is used to represent dot properties.
- // Content in value and values are mutually exclusive.
- Object *value;
- // The property name
- const QHashedStringRef &name() const { return _name; }
- void setName(const QString &n) { _name = QHashedStringRef(pool()->NewString(n)); }
- void setName(const QHashedStringRef &n) { _name = n; }
- // True if this property was accessed as the default property.
- bool isDefault;
- // True if the setting of this property will be deferred. Set by the
- // QQmlCompiler
- bool isDeferred;
- // True if this property is a value-type pseudo-property
- bool isValueTypeSubProperty;
- // True if this property is a property alias. Set by the
- // QQmlCompiler
- bool isAlias;
- // True if this is a readonly property declaration
- bool isReadOnlyDeclaration;
-
- // Used for scriptStringProperties
- int scriptStringScope;
-
- LocationSpan location;
- LocationRange listValueRange;
-
- // Used in Object::MainPropertyList
- Property *nextMainProperty;
-
- // Used in Object::PropertyList lists
- Property *nextProperty;
-
-private:
- friend class Object;
- QHashedStringRef _name;
};
class Object : public QQmlPool::Class
{
public:
- Object();
- virtual ~Object();
-
- // Type of the object. The integer is an index into the
- // QQmlCompiledData::types array, or -1 if the object is a property
- // group.
- int type;
- // A back pointer to the QQmlScript::TypeReference for this type, if any.
- // Set by the parser.
- TypeReference *typeReference;
-
- // The id assigned to the object (if any). Set by the QQmlCompiler
- QString id;
- // The id index assigned to the object (if any). Set by the QQmlCompiler
- int idIndex;
- // Custom parsed data
- QByteArray custom;
- // Bit mask of the properties assigned bindings
- QByteArray bindingBitmask;
- void setBindingBit(int);
-
- QQmlPropertyCache *metatype;
-
- QQmlJS::AST::Node *astNode; // responsible for the creation of this object
-
- // The synthesized metaobject, if QML added signals or properties to
- // this type. Otherwise null
- QByteArray synthdata; // Generated by compiler
- QQmlPropertyCache *synthCache; // Generated by compiler
-
- Property *getDefaultProperty();
- // name ptr must be guaranteed to remain valid
- Property *getProperty(const QHashedStringRef &name, bool create=true);
- Property *getProperty(const QStringRef &name, bool create=true);
- Property *getProperty(const QString &name, bool create=true);
-
- Property *defaultProperty;
-
- typedef QFieldList<Property, &Property::nextMainProperty> MainPropertyList;
- MainPropertyList properties;
- QHashField propertiesHashField;
-
- // Output of the compilation phase (these properties continue to exist
- // in either the defaultProperty or properties members too)
- void addValueProperty(Property *);
- void addSignalProperty(Property *);
- void addAttachedProperty(Property *);
- void addGroupedProperty(Property *);
- void addValueTypeProperty(Property *);
- void addScriptStringProperty(Property *);
-
- typedef QFieldList<Property, &Property::nextProperty> PropertyList;
- PropertyList valueProperties;
- PropertyList signalProperties;
- PropertyList attachedProperties;
- PropertyList groupedProperties;
- PropertyList valueTypeProperties;
- PropertyList scriptStringProperties;
-
// Script blocks that were nested under this object
struct ScriptBlock {
enum Pragma {
@@ -384,120 +153,11 @@ public:
QString file;
Pragmas pragmas;
};
-
- // The bytes to cast instances by to get to the QQmlParserStatus
- // interface. -1 indicates the type doesn't support this interface.
- // Set by the QQmlCompiler.
- int parserStatusCast;
-
- LocationSpan location;
-
- struct DynamicProperty : public QQmlPool::POD
- {
- DynamicProperty();
-
- enum Type { Var, Variant, Int, Bool, Real, String, Url, Color,
- Font, Time, Date, DateTime, Rect, Point, Size,
- Vector2D, Vector3D, Vector4D, Matrix4x4, Quaternion,
- Alias, Custom, CustomList };
-
- quint32 isDefaultProperty:1;
- quint32 isReadOnly:1;
-
- Type type;
-
- QHashedStringRef customType;
- QHashedStringRef name;
- QQmlScript::Property *defaultValue;
- LocationSpan location;
- Location nameLocation;
-
- // Used by Object::DynamicPropertyList
- DynamicProperty *nextProperty;
-
- // Used by the compiler
- int nameIndex; // Points at the name and name + "Changed()" strings
- };
-
- struct DynamicSignal : public QQmlPool::POD
- {
- DynamicSignal();
-
- QHashedStringRef name;
- QQmlPool::List<DynamicProperty::Type> parameterTypes;
- QQmlPool::List<QHashedStringRef> parameterTypeNames;
- QQmlPool::List<QHashedStringRef> parameterNames;
-
- // Used by Object::DynamicSignalList
- DynamicSignal *nextSignal;
-
- // Used by the compiler
- int nameIndex;
- LocationSpan location;
- };
-
- struct DynamicSlot : public QQmlPool::Class
- {
- DynamicSlot();
-
- QQmlJS::AST::FunctionDeclaration *funcDecl;
- QHashedStringRef name;
- QList<QByteArray> parameterNames;
- LocationSpan location;
-
- int parameterNamesLength() const;
-
- // Used by Object::DynamicSlotList
- DynamicSlot *nextSlot;
-
- // Used by the compiler
- int nameIndex;
- };
-
- // The list of dynamic properties
- typedef QFieldList<DynamicProperty, &DynamicProperty::nextProperty> DynamicPropertyList;
- DynamicPropertyList dynamicProperties;
- // The list of dynamic signals
- typedef QFieldList<DynamicSignal, &DynamicSignal::nextSignal> DynamicSignalList;
- DynamicSignalList dynamicSignals;
- // The list of dynamic slots
- typedef QFieldList<DynamicSlot, &DynamicSlot::nextSlot> DynamicSlotList;
- DynamicSlotList dynamicSlots;
-
- int aggregateDynamicSignalParameterCount() const;
- int aggregateDynamicSlotParameterCount() const;
-
- // Used by compiler
- QQmlCompilerTypes::ComponentCompileState *componentCompileState;
-
- // Used by ComponentCompileState::AliasingObjectsList
- Object *nextAliasingObject;
- // Used by ComponentComppileState::IdList
- Object *nextIdObject;
};
-class ParserJsASTData;
class Q_QML_PRIVATE_EXPORT Parser
{
public:
- Parser();
- ~Parser();
-
- bool parse(const QString &data, const QByteArray &preparseData,
- const QUrl &url = QUrl(), const QString &urlString = QString());
-
- QByteArray preparseData() const;
-
- QList<TypeReference*> referencedTypes() const;
-
- QQmlScript::Object *tree() const;
- QList<Import> imports() const;
- QList<Pragma> pragmas() const;
-
- void clear();
-
- QList<QQmlError> errors() const;
-
class JavaScriptMetaData {
public:
JavaScriptMetaData()
@@ -509,29 +169,6 @@ public:
static QQmlScript::Object::ScriptBlock::Pragmas extractPragmas(QString &);
static JavaScriptMetaData extractMetaData(QString &, QQmlError *error);
-
-
-// ### private:
- int findOrCreateTypeId(const QString &name, Object *);
- void setTree(QQmlScript::Object *tree);
-
- void setScriptFile(const QString &filename) {_scriptFile = filename; }
- QString scriptFile() const { return _scriptFile; }
-
- QQmlJS::AST::UiProgram *qmlRoot() const { return _qmlRoot; }
- QQmlJS::Engine *jsEngine() const;
-
-// ### private:
- QList<QQmlError> _errors;
-
- QQmlPool _pool;
- QQmlScript::Object *root;
- QList<Import> _imports;
- QList<Pragma> _pragmas;
- QList<TypeReference*> _refTypes;
- QString _scriptFile;
- QQmlJS::AST::UiProgram *_qmlRoot;
- ParserJsASTData *data;
};
}
@@ -540,6 +177,4 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlScript::Object::ScriptBlock::Pragmas)
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QQmlScript::Variant)
-
#endif // QQMLSCRIPT_P_H
diff --git a/src/qml/qml/qqmlstringconverters.cpp b/src/qml/qml/qqmlstringconverters.cpp
index 79bb1e9394..c0da9b458f 100644
--- a/src/qml/qml/qqmlstringconverters.cpp
+++ b/src/qml/qml/qqmlstringconverters.cpp
@@ -41,7 +41,6 @@
#include "qqmlstringconverters_p.h"
#include <private/qqmlglobal_p.h>
-#include <private/qqmlinstruction_p.h>
#include <QtCore/qpoint.h>
#include <QtCore/qrect.h>
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index c1074e8a84..258c5c71b3 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -1966,15 +1966,12 @@ QQmlTypeData::QQmlTypeData(const QUrl &url, QQmlTypeLoader *manager)
: QQmlTypeLoader::Blob(url, QmlFile, manager),
m_typesResolved(false), m_compiledData(0), m_implicitImport(0), m_implicitImportLoaded(false)
{
- m_useNewCompiler = QQmlEnginePrivate::get(manager->engine())->useNewCompiler;
}
QQmlTypeData::~QQmlTypeData()
{
for (int ii = 0; ii < m_scripts.count(); ++ii)
m_scripts.at(ii).script->release();
- for (int ii = 0; ii < m_types.count(); ++ii)
- if (m_types.at(ii).typeData) m_types.at(ii).typeData->release();
for (QHash<int, TypeReference>::ConstIterator it = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd();
it != end; ++it) {
if (QQmlTypeData *tdata = it->typeData)
@@ -1986,16 +1983,6 @@ QQmlTypeData::~QQmlTypeData()
delete m_implicitImport;
}
-const QQmlScript::Parser &QQmlTypeData::parser() const
-{
- return scriptParser;
-}
-
-const QList<QQmlTypeData::TypeReference> &QQmlTypeData::resolvedTypes() const
-{
- return m_types;
-}
-
const QList<QQmlTypeData::ScriptReference> &QQmlTypeData::resolvedScripts() const
{
return m_scripts;
@@ -2048,24 +2035,6 @@ void QQmlTypeData::done()
}
// Check all type dependencies for errors
- // --- old compiler:
- for (int ii = 0; !isError() && ii < m_types.count(); ++ii) {
- const TypeReference &type = m_types.at(ii);
- Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError());
- if (type.typeData && type.typeData->isError()) {
- QString typeName = scriptParser.referencedTypes().at(ii)->name;
-
- QList<QQmlError> errors = type.typeData->errors();
- QQmlError error;
- error.setUrl(finalUrl());
- error.setLine(type.location.line);
- error.setColumn(type.location.column);
- error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
- errors.prepend(error);
- setError(errors);
- }
- }
- // --- new compiler:
for (QHash<int, TypeReference>::ConstIterator it = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd();
!isError() && it != end; ++it) {
const TypeReference &type = *it;
@@ -2083,7 +2052,6 @@ void QQmlTypeData::done()
setError(errors);
}
}
- // ---
// Check all composite singleton type dependencies for errors
for (int ii = 0; !isError() && ii < m_compositeSingletons.count(); ++ii) {
@@ -2119,7 +2087,6 @@ void QQmlTypeData::done()
if (!isError())
compile();
- scriptParser.clear();
parsedQML.reset();
}
@@ -2160,19 +2127,12 @@ void QQmlTypeData::dataReceived(const Data &data)
if (data.isFile()) preparseData = data.asFile()->metaData(QLatin1String("qml:preparse"));
- if (m_useNewCompiler) {
- QQmlEngine *qmlEngine = typeLoader()->engine();
- parsedQML.reset(new QtQml::ParsedQML(QV8Engine::getV4(qmlEngine)->debugger != 0));
- QQmlCodeGenerator compiler(QV8Engine::get(qmlEngine)->illegalNames());
- if (!compiler.generateFromQml(code, finalUrl(), finalUrlString(), parsedQML.data())) {
- setError(compiler.errors);
- return;
- }
- } else {
- if (!scriptParser.parse(code, preparseData, finalUrl(), finalUrlString())) {
- setError(scriptParser.errors());
- return;
- }
+ QQmlEngine *qmlEngine = typeLoader()->engine();
+ parsedQML.reset(new QtQml::ParsedQML(QV8Engine::getV4(qmlEngine)->debugger != 0));
+ QQmlCodeGenerator compiler(QV8Engine::get(qmlEngine)->illegalNames());
+ if (!compiler.generateFromQml(code, finalUrl(), finalUrlString(), parsedQML.data())) {
+ setError(compiler.errors);
+ return;
}
m_imports.setBaseUrl(finalUrl(), finalUrlString());
@@ -2203,7 +2163,7 @@ void QQmlTypeData::dataReceived(const Data &data)
QList<QQmlError> errors;
// ### convert to use new data structure once old compiler is gone.
- if (m_useNewCompiler && m_newImports.isEmpty()) {
+ if (m_newImports.isEmpty()) {
m_newImports.reserve(parsedQML->imports.size());
foreach (QV4::CompiledData::Import *i, parsedQML->imports) {
QQmlScript::Import import;
@@ -2226,7 +2186,7 @@ void QQmlTypeData::dataReceived(const Data &data)
}
}
- foreach (const QQmlScript::Import &import, m_useNewCompiler ? m_newImports : scriptParser.imports()) {
+ foreach (const QQmlScript::Import &import, m_newImports) {
if (!addImport(import, &errors)) {
Q_ASSERT(errors.size());
QQmlError error(errors.takeFirst());
@@ -2240,7 +2200,7 @@ void QQmlTypeData::dataReceived(const Data &data)
}
// ### convert to use new data structure once old compiler is gone.
- if (m_useNewCompiler && m_newPragmas.isEmpty()) {
+ if (m_newPragmas.isEmpty()) {
m_newPragmas.reserve(parsedQML->pragmas.size());
foreach (QtQml::Pragma *p, parsedQML->pragmas) {
QQmlScript::Pragma pragma;
@@ -2256,7 +2216,7 @@ void QQmlTypeData::dataReceived(const Data &data)
}
}
- foreach (const QQmlScript::Pragma &pragma, m_useNewCompiler ? m_newPragmas : scriptParser.pragmas()) {
+ foreach (const QQmlScript::Pragma &pragma, m_newPragmas) {
if (!addPragma(pragma, &errors)) {
Q_ASSERT(errors.size());
setError(errors);
@@ -2312,20 +2272,11 @@ void QQmlTypeData::compile()
QQmlCompilingProfiler prof(QQmlEnginePrivate::get(typeLoader()->engine())->profiler, m_compiledData->name);
- if (m_useNewCompiler) {
- QQmlTypeCompiler compiler(QQmlEnginePrivate::get(typeLoader()->engine()), m_compiledData, this, parsedQML.data());
- if (!compiler.compile()) {
- setError(compiler.compilationErrors());
- m_compiledData->release();
- m_compiledData = 0;
- }
- } else {
- QQmlCompiler compiler(&scriptParser._pool);
- if (!compiler.compile(typeLoader()->engine(), this, m_compiledData)) {
- setError(compiler.errors());
- m_compiledData->release();
- m_compiledData = 0;
- }
+ QQmlTypeCompiler compiler(QQmlEnginePrivate::get(typeLoader()->engine()), m_compiledData, this, parsedQML.data());
+ if (!compiler.compile()) {
+ setError(compiler.compilationErrors());
+ m_compiledData->release();
+ m_compiledData = 0;
}
}
@@ -2357,9 +2308,6 @@ void QQmlTypeData::resolveTypes()
TypeReference ref;
QQmlScript::TypeReference parserRef;
parserRef.name = csRef.typeName;
- // we are basing our type on the information from qmldir and therefore
- // do not have a proper location.
- parserRef.firstUse = NULL;
if (!csRef.prefix.isEmpty()) {
parserRef.name.prepend(csRef.prefix + QLatin1Char('.'));
@@ -2382,31 +2330,6 @@ void QQmlTypeData::resolveTypes()
}
}
- // --- old compiler:
- foreach (QQmlScript::TypeReference *parserRef, scriptParser.referencedTypes()) {
- TypeReference ref;
-
- int majorVersion = -1;
- int minorVersion = -1;
-
- if (!resolveType(parserRef, majorVersion, minorVersion, ref))
- return;
-
- if (ref.type->isComposite()) {
- ref.typeData = typeLoader()->getType(ref.type->sourceUrl());
- addDependency(ref.typeData);
- }
-
- ref.majorVersion = majorVersion;
- ref.minorVersion = minorVersion;
-
- Q_ASSERT(parserRef->firstUse);
- ref.location = parserRef->firstUse->location.start;
-
- m_types << ref;
- }
-
- // --- new compiler:
QV4::CompiledData::TypeReferenceMap typeReferences;
QStringList names;
if (parsedQML) {
@@ -2523,12 +2446,6 @@ bool QQmlTypeData::resolveType(const QQmlScript::TypeReference *parserRef, int &
error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(parserRef->name).arg(error.description()));
}
- if (parserRef->firstUse)
- {
- error.setLine(parserRef->firstUse->location.start.line);
- error.setColumn(parserRef->firstUse->location.start.column);
- }
-
errors.prepend(error);
setError(errors);
return false;
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index ab6f47e8de..a42412754f 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -424,13 +424,7 @@ private:
public:
~QQmlTypeData();
- const QQmlScript::Parser &parser() const;
-
- // old compiler:
- const QList<TypeReference> &resolvedTypes() const;
- // new compiler:
const QHash<int, TypeReference> &resolvedTypeRefs() const { return m_resolvedTypes; }
- // ---
const QList<ScriptReference> &resolvedScripts() const;
const QSet<QString> &namespaces() const;
@@ -461,27 +455,18 @@ private:
virtual void scriptImported(QQmlScriptBlob *blob, const QQmlScript::Location &location, const QString &qualifier, const QString &nameSpace);
- // --- old compiler
- QQmlScript::Parser scriptParser;
- // --- new compiler
QScopedPointer<QtQml::ParsedQML> parsedQML;
QList<QQmlScript::Import> m_newImports;
QList<QQmlScript::Pragma> m_newPragmas;
- // ---
QList<ScriptReference> m_scripts;
QSet<QString> m_namespaces;
QList<TypeReference> m_compositeSingletons;
- // --- old compiler
- QList<TypeReference> m_types;
- // --- new compiler
// map from name index to resolved type
QHash<int, TypeReference> m_resolvedTypes;
- // ---
bool m_typesResolved:1;
- bool m_useNewCompiler:1;
QQmlCompiledData *m_compiledData;
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index 15401e269b..56befa4a3e 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -82,1192 +82,8 @@ QT_BEGIN_NAMESPACE
using namespace QQmlVMETypes;
-#define VME_EXCEPTION(desc, line) \
- { \
- QQmlError error; \
- error.setDescription(desc.trimmed()); \
- error.setLine(line); \
- error.setUrl(COMP->url); \
- *errors << error; \
- goto exceptionExit; \
- }
-
-#define VME_EXCEPTION_WITH_COLUMN(desc, line, column) \
- { \
- QQmlError error; \
- error.setDescription(desc.trimmed()); \
- error.setLine(line); \
- error.setColumn(column); \
- error.setUrl(COMP->url); \
- *errors << error; \
- goto exceptionExit; \
- }
-
bool QQmlVME::s_enableComponentComplete = true;
-void QQmlVME::init(QQmlContextData *ctxt, QQmlCompiledData *comp, int start,
- QQmlContextData *creation)
-{
- Q_ASSERT(ctxt);
- Q_ASSERT(comp);
-
- if (start == -1) {
- start = 0;
- } else {
- creationContext = creation;
- }
-
- State initState;
- initState.context = ctxt;
- initState.compiledData = comp;
- initState.instructionStream = comp->bytecode.constData() + start;
- states.push(initState);
-
- typedef QQmlInstruction I;
- I *i = (I *)initState.instructionStream;
-
- Q_ASSERT(comp->instructionType(i) == I::Init);
-
- objects.allocate(i->init.objectStackSize);
- lists.allocate(i->init.listStackSize);
- bindValues.allocate(i->init.bindingsSize);
- parserStatus.allocate(i->init.parserStatusSize);
-
-#ifdef QML_ENABLE_TRACE
- parserStatusData.allocate(i->init.parserStatusSize);
- rootComponent = comp;
-#endif
-
- rootContext = 0;
- engine = ctxt->engine;
- profiler.profiler = QQmlEnginePrivate::get(engine)->profiler;
-}
-
-bool QQmlVME::initDeferred(QObject *object)
-{
- QQmlData *data = QQmlData::get(object);
-
- if (!data || !data->deferredData)
- return false;
-
- QQmlContextData *ctxt = data->deferredData->context;
- QQmlCompiledData *comp = data->deferredData->compiledData;
- int start = data->deferredData->deferredIdx;
-
- State initState;
- initState.flags = State::Deferred;
- initState.context = ctxt;
- initState.compiledData = comp;
- initState.instructionStream = comp->bytecode.constData() + start;
- states.push(initState);
-
- typedef QQmlInstruction I;
- I *i = (I *)initState.instructionStream;
-
- Q_ASSERT(comp->instructionType(i) == I::DeferInit);
-
- objects.allocate(i->deferInit.objectStackSize);
- lists.allocate(i->deferInit.listStackSize);
- bindValues.allocate(i->deferInit.bindingsSize);
- parserStatus.allocate(i->deferInit.parserStatusSize);
-
- objects.push(object);
-
-#ifdef QML_ENABLE_TRACE
- parserStatusData.allocate(i->deferInit.parserStatusSize);
- rootComponent = comp;
-#endif
-
- rootContext = 0;
- engine = ctxt->engine;
- profiler.profiler = QQmlEnginePrivate::get(engine)->profiler;
-
- return true;
-}
-
-namespace {
-struct ActiveVMERestorer
-{
- ActiveVMERestorer(QQmlVME *me, QQmlEnginePrivate *ep)
- : ep(ep), oldVME(ep->activeVME) { ep->activeVME = me; }
- ~ActiveVMERestorer() { ep->activeVME = oldVME; }
-
- QQmlEnginePrivate *ep;
- QQmlVME *oldVME;
-};
-}
-
-QObject *QQmlVME::execute(QList<QQmlError> *errors, const QQmlInstantiationInterrupt &interrupt)
-{
- Q_ASSERT(states.count() >= 1);
-
-#ifdef QML_ENABLE_TRACE
- QQmlTrace trace("VME Execute");
- trace.addDetail("URL", rootComponent->url);
-#endif
-
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(states.at(0).context->engine);
-
- ActiveVMERestorer restore(this, ep);
-
- QObject *rv = run(errors, interrupt);
-
- return rv;
-}
-
-inline bool fastHasBinding(QObject *o, int index)
-{
- if (QQmlData *ddata = static_cast<QQmlData *>(QObjectPrivate::get(o)->declarativeData)) {
- int coreIndex = index & 0x0000FFFF;
- return ddata->hasBindingBit(coreIndex);
- }
-
- return false;
-}
-
-static void removeBindingOnProperty(QObject *o, int index)
-{
- int coreIndex = index & 0x0000FFFF;
- int valueTypeIndex = (index & 0xFFFF0000 ? index >> 16 : -1);
-
- QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(o, coreIndex, valueTypeIndex, 0);
- if (binding) binding->destroy();
-}
-
-static QVariant variantFromString(const QString &string)
-{
- return QQmlStringConverters::variantFromString(string);
-}
-
-static QV4::ExecutionContext *qmlBindingContext(QQmlEngine *engine, QV4::ExecutionEngine *v4, QV4::Value *qmlBindingWrappers, QQmlContextData *context, QObject *scope, int objIdx)
-{
- QV4::Scope valueScope(v4);
- QV4::Scoped<QV4::QmlBindingWrapper> wrapper(valueScope, qmlBindingWrappers[objIdx]);
- if (!wrapper) {
- QV4::ScopedObject scopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, scope));
- wrapper = new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, scopeObject);
- qmlBindingWrappers[objIdx] = wrapper;
- }
- return wrapper->context();
-}
-
-// XXX we probably need some form of "work count" here to prevent us checking this
-// for every instruction.
-#define QML_BEGIN_INSTR_COMMON(I) { \
- const QQmlInstructionMeta<(int)QQmlInstruction::I>::DataType &instr = QQmlInstructionMeta<(int)QQmlInstruction::I>::data(*genericInstr); \
- INSTRUCTIONSTREAM += QQmlInstructionMeta<(int)QQmlInstruction::I>::Size; \
- Q_UNUSED(instr);
-
-#ifdef QML_THREADED_VME_INTERPRETER
-# define QML_BEGIN_INSTR(I) op_##I: \
- QML_BEGIN_INSTR_COMMON(I)
-
-# define QML_NEXT_INSTR(I) { \
- if (watcher.hasRecursed()) return 0; \
- genericInstr = reinterpret_cast<const QQmlInstruction *>(INSTRUCTIONSTREAM); \
- goto *genericInstr->common.code; \
- }
-
-# define QML_END_INSTR(I) } \
- if (watcher.hasRecursed()) return 0; \
- genericInstr = reinterpret_cast<const QQmlInstruction *>(INSTRUCTIONSTREAM); \
- if (interrupt.shouldInterrupt()) return 0; \
- goto *genericInstr->common.code;
-
-#else
-# define QML_BEGIN_INSTR(I) \
- case QQmlInstruction::I: \
- QML_BEGIN_INSTR_COMMON(I)
-
-# define QML_NEXT_INSTR(I) { \
- if (watcher.hasRecursed()) return 0; \
- break; \
- }
-
-# define QML_END_INSTR(I) \
- if (watcher.hasRecursed() || interrupt.shouldInterrupt()) return 0; \
- } break;
-#endif
-
-#define QML_STORE_VALUE(name, cpptype, value) \
- QML_BEGIN_INSTR(name) \
- cpptype v = value; \
- void *a[] = { (void *)&v, 0, &status, &flags }; \
- QObject *target = objects.top(); \
- CLEAN_PROPERTY(target, instr.propertyIndex); \
- QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); \
- QML_END_INSTR(name)
-
-#define QML_STORE_PROVIDER_VALUE(name, type, value) \
- QML_BEGIN_INSTR(name) \
- struct { void *data[4]; } buffer; \
- if (QQml_valueTypeProvider()->storeValueType(type, &value, &buffer, sizeof(buffer))) { \
- void *a[] = { reinterpret_cast<void *>(&buffer), 0, &status, &flags }; \
- QObject *target = objects.top(); \
- CLEAN_PROPERTY(target, instr.propertyIndex); \
- QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); \
- } \
- QML_END_INSTR(name)
-
-#define QML_STORE_LIST(name, cpptype, value) \
- QML_BEGIN_INSTR(name) \
- cpptype v; \
- v.append(value); \
- void *a[] = { (void *)&v, 0, &status, &flags }; \
- QObject *target = objects.top(); \
- CLEAN_PROPERTY(target, instr.propertyIndex); \
- QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); \
- QML_END_INSTR(name)
-
-#define QML_STORE_VAR(name, value) \
- QML_BEGIN_INSTR(name) \
- tmpValue = (value); \
- QV4::ValueRef valueref(tmpValue); \
- QObject *target = objects.top(); \
- CLEAN_PROPERTY(target, instr.propertyIndex); \
- QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(target); \
- Q_ASSERT(vmemo); \
- vmemo->setVMEProperty(instr.propertyIndex, valueref); \
- QML_END_INSTR(name)
-
-#define QML_STORE_POINTER(name, value) \
- QML_BEGIN_INSTR(name) \
- void *a[] = { (void *)value, 0, &status, &flags }; \
- QObject *target = objects.top(); \
- CLEAN_PROPERTY(target, instr.propertyIndex); \
- QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); \
- QML_END_INSTR(name)
-
-#define CLEAN_PROPERTY(o, index) \
- if (fastHasBinding(o, index)) \
- removeBindingOnProperty(o, index)
-
-QObject *QQmlVME::run(QList<QQmlError> *errors,
- const QQmlInstantiationInterrupt &interrupt
-#ifdef QML_THREADED_VME_INTERPRETER
- , void * const **storeJumpTable
-#endif
- )
-{
-#ifdef QML_THREADED_VME_INTERPRETER
- if (storeJumpTable) {
-#define QML_INSTR_ADDR(I, FMT) &&op_##I,
- static void *const jumpTable[] = {
- FOR_EACH_QML_INSTR(QML_INSTR_ADDR)
- };
-#undef QML_INSTR_ADDR
- *storeJumpTable = jumpTable;
- return 0;
- }
-#endif
- Q_ASSERT(errors->isEmpty());
- Q_ASSERT(states.count() >= 1);
-
- QQmlEngine *engine = states.at(0).context->engine;
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
- QV4::ExecutionEngine *v4 = ep->v4engine();
- QV4::Scope valueScope(v4);
- QV4::ScopedValue tmpValue(valueScope);
- QV4::Value *qmlBindingWrappers = valueScope.alloc(objects.capacity());
- std::fill(qmlBindingWrappers, qmlBindingWrappers + objects.capacity(), QV4::Primitive::undefinedValue());
-
- int status = -1; // needed for dbus
- QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
-
- QRecursionWatcher<QQmlVME, &QQmlVME::recursion> watcher(this);
-
-#define COMP states.top().compiledData
-#define CTXT states.top().context
-#define INSTRUCTIONSTREAM states.top().instructionStream
-#define BINDINGSKIPLIST states.top().bindingSkipList
-
-#define TYPES COMP->types
-#define PRIMITIVES COMP->primitives
-#define DATAS COMP->datas
-#define PROGRAMS COMP->programs
-#define PROPERTYCACHES COMP->propertyCaches
-#define SCRIPTS COMP->scripts
-#define URLS COMP->urls
-
-#ifdef QML_THREADED_VME_INTERPRETER
- const QQmlInstruction *genericInstr = reinterpret_cast<const QQmlInstruction *>(INSTRUCTIONSTREAM);
- goto *genericInstr->common.code;
-#else
- for (;;) {
- const QQmlInstruction *genericInstr = reinterpret_cast<const QQmlInstruction *>(INSTRUCTIONSTREAM);
-
- switch (genericInstr->common.instructionType) {
-#endif
-
- // Store a created object in a property. These all pop from the objects stack.
- QML_STORE_VALUE(StoreObject, QObject *, objects.pop());
- QML_STORE_VALUE(StoreVariantObject, QVariant, QVariant::fromValue(objects.pop()));
- QML_STORE_VAR(StoreVarObject, QV4::QObjectWrapper::wrap(ep->v4engine(), objects.pop()));
-
- // Store a literal value in a corresponding property
- QML_STORE_VALUE(StoreFloat, float, instr.value);
- QML_STORE_VALUE(StoreDouble, double, instr.value);
- QML_STORE_VALUE(StoreBool, bool, instr.value);
- QML_STORE_VALUE(StoreInteger, int, instr.value);
- QML_STORE_PROVIDER_VALUE(StoreColor, QMetaType::QColor, instr.value);
- QML_STORE_VALUE(StoreDate, QDate, QDate::fromJulianDay(instr.value));
- QML_STORE_VALUE(StoreDateTime, QDateTime,
- QDateTime(QDate::fromJulianDay(instr.date), QTime::fromMSecsSinceStartOfDay(instr.time)));
- QML_STORE_VALUE(StoreTime, QTime, QTime::fromMSecsSinceStartOfDay(instr.time));
- QML_STORE_POINTER(StorePoint, (QPoint *)&instr.point);
- QML_STORE_POINTER(StorePointF, (QPointF *)&instr.point);
- QML_STORE_POINTER(StoreSize, (QSize *)&instr.size);
- QML_STORE_POINTER(StoreSizeF, (QSizeF *)&instr.size);
- QML_STORE_POINTER(StoreRect, (QRect *)&instr.rect);
- QML_STORE_POINTER(StoreRectF, (QRectF *)&instr.rect);
- QML_STORE_PROVIDER_VALUE(StoreVector3D, QMetaType::QVector3D, instr.vector);
- QML_STORE_PROVIDER_VALUE(StoreVector4D, QMetaType::QVector4D, instr.vector);
- QML_STORE_POINTER(StoreString, &PRIMITIVES.at(instr.value));
- QML_STORE_POINTER(StoreByteArray, &DATAS.at(instr.value));
- QML_STORE_POINTER(StoreUrl, &URLS.at(instr.value));
-#ifndef QT_NO_TRANSLATION
- QML_STORE_VALUE(StoreTrString, QString,
- QCoreApplication::translate(DATAS.at(instr.context).constData(),
- DATAS.at(instr.text).constData(),
- DATAS.at(instr.comment).constData(),
- instr.n));
- QML_STORE_VALUE(StoreTrIdString, QString, qtTrId(DATAS.at(instr.text).constData(), instr.n));
-#endif
-
- // Store a literal value in a QList
- QML_STORE_LIST(StoreStringList, QStringList, PRIMITIVES.at(instr.value));
- QML_STORE_LIST(StoreStringQList, QList<QString>, PRIMITIVES.at(instr.value));
- QML_STORE_LIST(StoreUrlQList, QList<QUrl>, URLS.at(instr.value));
- QML_STORE_LIST(StoreDoubleQList, QList<double>, instr.value);
- QML_STORE_LIST(StoreBoolQList, QList<bool>, instr.value);
- QML_STORE_LIST(StoreIntegerQList, QList<int>, instr.value);
-
- // Store a literal value in a QVariant property
- QML_STORE_VALUE(StoreVariant, QVariant, variantFromString(PRIMITIVES.at(instr.value)));
- QML_STORE_VALUE(StoreVariantInteger, QVariant, QVariant(instr.value));
- QML_STORE_VALUE(StoreVariantDouble, QVariant, QVariant(instr.value));
- QML_STORE_VALUE(StoreVariantBool, QVariant, QVariant(instr.value));
-
- // Store a literal value in a var property.
- // We deliberately do not use string converters here
- QML_STORE_VAR(StoreVar, ep->v8engine()->fromVariant(PRIMITIVES.at(instr.value)));
- QML_STORE_VAR(StoreVarInteger, QV4::Primitive::fromInt32(instr.value));
- QML_STORE_VAR(StoreVarDouble, QV4::Primitive::fromDouble(instr.value));
- QML_STORE_VAR(StoreVarBool, QV4::Primitive::fromBoolean(instr.value));
-
- // Store a literal value in a QJSValue property.
- QML_STORE_VALUE(StoreJSValueString, QJSValue, QJSValue(PRIMITIVES.at(instr.value)));
- QML_STORE_VALUE(StoreJSValueInteger, QJSValue, QJSValue(instr.value));
- QML_STORE_VALUE(StoreJSValueDouble, QJSValue, QJSValue(instr.value));
- QML_STORE_VALUE(StoreJSValueBool, QJSValue, QJSValue(instr.value));
-
- QML_BEGIN_INSTR(Init)
- // Ensure that the compiled data has been initialized
- if (!COMP->isInitialized()) COMP->initialize(engine);
-
- QQmlContextData *parentCtxt = CTXT;
- CTXT = new QQmlContextData;
- CTXT->isInternal = true;
- CTXT->url = COMP->url;
- CTXT->urlString = COMP->name;
- CTXT->imports = COMP->importCache;
- CTXT->imports->addref();
- CTXT->setParent(parentCtxt);
- if (instr.contextCache != -1)
- CTXT->setIdPropertyData(COMP->contextCaches.at(instr.contextCache));
- if (states.count() == 1) {
- rootContext = CTXT;
- rootContext->activeVMEData = data;
- rootContext->isRootObjectInCreation = true;
- }
- if (states.count() == 1 && !creationContext.isNull()) {
- // A component that is logically created within another component instance shares the
- // same instances of script imports. For example:
- //
- // import QtQuick 2.0
- // import "test.js" as Test
- // ListView {
- // model: Test.getModel()
- // delegate: Component {
- // Text { text: Test.getValue(index); }
- // }
- // }
- //
- // Has the same "Test" instance. To implement this, we simply copy the v8 handles into
- // the inner context. We have to create a fresh persistent handle for each to prevent
- // double dispose. It is possible we could do this more efficiently using some form of
- // referencing instead.
- CTXT->importedScripts = creationContext->importedScripts;
- }
- QML_END_INSTR(Init)
-
- QML_BEGIN_INSTR(DeferInit)
- QML_END_INSTR(DeferInit)
-
- QML_BEGIN_INSTR(Done)
- states.pop();
-
- if (states.isEmpty())
- goto normalExit;
- QML_END_INSTR(Done)
-
- QML_BEGIN_INSTR(CreateQMLObject)
- const QQmlCompiledData::TypeReference &type = TYPES.at(instr.type);
- Q_ASSERT(type.component);
-
- Q_QML_VME_PROFILE(profiler, startBackground(type.component->name));
-
- states.push(State());
-
- State *cState = &states[states.count() - 2];
- State *nState = &states[states.count() - 1];
-
- nState->context = cState->context;
- nState->compiledData = type.component;
- nState->instructionStream = type.component->bytecode.constData();
-
- if (instr.bindingBits != -1) {
- const QByteArray &bits = cState->compiledData->datas.at(instr.bindingBits);
- nState->bindingSkipList = QBitField((const quint32*)bits.constData(),
- bits.size() * 8);
- }
- if (instr.isRoot)
- nState->bindingSkipList = nState->bindingSkipList.united(cState->bindingSkipList);
-
- // As the state in the state stack changed, execution will continue in the new program.
- QML_END_INSTR(CreateQMLObject)
-
- QML_BEGIN_INSTR(CompleteQMLObject)
- Q_QML_VME_PROFILE(profiler, foreground(CTXT->url, instr.line, instr.column));
-
- QObject *o = objects.top();
- Q_ASSERT(o);
-
- QQmlData *ddata = QQmlData::get(o);
- Q_ASSERT(ddata);
-
- if (states.count() == 1) {
- // Keep a reference to the compiled data we rely on.
- // Only the top-level component instance needs to add a reference - higher-level
- // components add a reference to the components they depend on, so an instance
- // of the top-level component keeps them all referenced.
- ddata->compiledData = states[0].compiledData;
- ddata->compiledData->addref();
- }
-
- if (instr.isRoot) {
- if (ddata->context) {
- Q_ASSERT(ddata->context != CTXT);
- Q_ASSERT(ddata->outerContext);
- Q_ASSERT(ddata->outerContext != CTXT);
- QQmlContextData *c = ddata->context;
- while (c->linkedContext) c = c->linkedContext;
- c->linkedContext = CTXT;
- } else {
- CTXT->addObject(o);
- }
-
- ddata->ownContext = true;
- } else if (!ddata->context) {
- CTXT->addObject(o);
- }
-
- ddata->setImplicitDestructible();
- ddata->outerContext = CTXT;
- ddata->lineNumber = instr.line;
- ddata->columnNumber = instr.column;
- qmlBindingWrappers[objects.count() - 1] = QV4::Primitive::undefinedValue();
- QML_END_INSTR(CompleteQMLObject)
-
- QML_BEGIN_INSTR(CreateCppObject)
- const QQmlCompiledData::TypeReference &type = TYPES.at(instr.type);
- Q_ASSERT(type.type);
- Q_QML_VME_PROFILE(profiler, start(type.type->qmlTypeName(), CTXT->url, instr.line, instr.column));
-
- QObject *o = 0;
- void *memory = 0;
- type.type->create(&o, &memory, sizeof(QQmlData));
-
- if (!o)
- VME_EXCEPTION(tr("Unable to create object of type %1").arg(type.type->elementName()),
- instr.line);
-
- QQmlData *ddata = new (memory) QQmlData;
- ddata->ownMemory = false;
- QObjectPrivate::get(o)->declarativeData = ddata;
-
- if (rootContext && rootContext->isRootObjectInCreation) {
- ddata->rootObjectInCreation = true;
- rootContext->isRootObjectInCreation = false;
- }
-
- if (type.typePropertyCache && !ddata->propertyCache) {
- ddata->propertyCache = type.typePropertyCache;
- ddata->propertyCache->addref();
- }
-
- if (states.count() == 1) {
- // Keep a reference to the compiled data we rely on
- ddata->compiledData = states[0].compiledData;
- ddata->compiledData->addref();
- }
-
- if (instr.isRoot) {
- if (ddata->context) {
- Q_ASSERT(ddata->context != CTXT);
- Q_ASSERT(ddata->outerContext);
- Q_ASSERT(ddata->outerContext != CTXT);
- QQmlContextData *c = ddata->context;
- while (c->linkedContext) c = c->linkedContext;
- c->linkedContext = CTXT;
- } else {
- CTXT->addObject(o);
- }
-
- ddata->ownContext = true;
- } else if (!ddata->context) {
- CTXT->addObject(o);
- }
-
- ddata->setImplicitDestructible();
- ddata->outerContext = CTXT;
- ddata->lineNumber = instr.line;
- ddata->columnNumber = instr.column;
-
- if (instr.data != -1) {
- QQmlCustomParser *customParser =
- TYPES.at(instr.type).type->customParser();
- customParser->setCustomData(o, DATAS.at(instr.data));
- }
- if (!objects.isEmpty()) {
- QObject *parent = objects.at(objects.count() - 1 - (instr.parentToSuper?1:0));
-#if 0 // ### refactor
- if (o->isWidgetType() && parent->isWidgetType())
- static_cast<QWidget*>(o)->setParent(static_cast<QWidget*>(parent));
- else
-#endif
- QQml_setParent_noEvent(o, parent);
- ddata->parentFrozen = true;
- }
- objects.push(o);
- qmlBindingWrappers[objects.count() - 1] = QV4::Primitive::undefinedValue();
- QML_END_INSTR(CreateCppObject)
-
- QML_BEGIN_INSTR(CreateSimpleObject)
- const QQmlCompiledData::TypeReference &ref = TYPES.at(instr.type);
- Q_QML_VME_PROFILE(profiler, start(ref.type->qmlTypeName(), CTXT->url, instr.line, instr.column));
- QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QQmlData));
- ::memset(static_cast<void *>(o), 0, instr.typeSize + sizeof(QQmlData));
- instr.create(o);
-
- QQmlData *ddata = (QQmlData *)(((const char *)o) + instr.typeSize);
- if (!ddata->propertyCache && ref.typePropertyCache) {
- ddata->propertyCache = ref.typePropertyCache;
- ddata->propertyCache->addref();
- }
- ddata->lineNumber = instr.line;
- ddata->columnNumber = instr.column;
-
- QObjectPrivate::get(o)->declarativeData = ddata;
- ddata->context = ddata->outerContext = CTXT;
- ddata->nextContextObject = CTXT->contextObjects;
- if (ddata->nextContextObject)
- ddata->nextContextObject->prevContextObject = &ddata->nextContextObject;
- ddata->prevContextObject = &CTXT->contextObjects;
- CTXT->contextObjects = ddata;
-
- QObject *parent = objects.at(objects.count() - 1 - (instr.parentToSuper?1:0));
- QQml_setParent_noEvent(o, parent);
-
- ddata->parentFrozen = true;
- objects.push(o);
- qmlBindingWrappers[objects.count() - 1] = QV4::Primitive::undefinedValue();
- QML_END_INSTR(CreateSimpleObject)
-
- QML_BEGIN_INSTR(SetId)
- QObject *target = objects.top();
- CTXT->setIdProperty(instr.index, target);
- QML_END_INSTR(SetId)
-
- QML_BEGIN_INSTR(SetDefault)
- CTXT->contextObject = objects.top();
- QML_END_INSTR(SetDefault)
-
- QML_BEGIN_INSTR(CreateComponent)
- QQmlComponent *qcomp =
- new QQmlComponent(CTXT->engine, COMP, INSTRUCTIONSTREAM - COMP->bytecode.constData(),
- objects.isEmpty() ? 0 : objects.top());
-
- QQmlData *ddata = QQmlData::get(qcomp, true);
- Q_ASSERT(ddata);
-
- CTXT->addObject(qcomp);
-
- if (states.count() == 1) {
- // Keep a reference to the compiled data we rely on
- ddata->compiledData = states[0].compiledData;
- ddata->compiledData->addref();
- }
-
- if (instr.isRoot)
- ddata->ownContext = true;
-
- ddata->setImplicitDestructible();
- ddata->outerContext = CTXT;
- ddata->lineNumber = instr.line;
- ddata->columnNumber = instr.column;
-
- QQmlComponentPrivate::get(qcomp)->creationContext = CTXT;
-
- objects.push(qcomp);
- qmlBindingWrappers[objects.count() - 1] = QV4::Primitive::undefinedValue();
- INSTRUCTIONSTREAM += instr.count;
- QML_END_INSTR(CreateComponent)
-
- QML_BEGIN_INSTR(StoreMetaObject)
- QObject *target = objects.top();
-
- QQmlPropertyCache *propertyCache = PROPERTYCACHES.at(instr.propertyCache);
-
- const QQmlVMEMetaData *data =
- (const QQmlVMEMetaData *)DATAS.at(instr.aliasData).constData();
-
- QV4::ExecutionContext *qmlContext = qmlBindingContext(engine, QV8Engine::getV4(engine), qmlBindingWrappers, CTXT, target, objects.count() - 1);
- (void)new QQmlVMEMetaObject(target, propertyCache, data, qmlContext, COMP);
-
- QQmlData *ddata = QQmlData::get(target, true);
- if (ddata->propertyCache) ddata->propertyCache->release();
- ddata->propertyCache = propertyCache;
- ddata->propertyCache->addref();
-
- QML_END_INSTR(StoreMetaObject)
-
- QML_BEGIN_INSTR(AssignCustomType)
- QObject *target = objects.top();
- CLEAN_PROPERTY(target, instr.propertyIndex);
-
- const QString &primitive = PRIMITIVES.at(instr.primitive);
- int type = instr.type;
- QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(type);
- QVariant v = (*converter)(primitive);
-
- QMetaProperty prop =
- target->metaObject()->property(instr.propertyIndex);
- if (v.isNull() || ((int)prop.type() != type && prop.userType() != type))
- VME_EXCEPTION(tr("Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.line);
-
- void *a[] = { (void *)v.data(), 0, &status, &flags };
- QMetaObject::metacall(target, QMetaObject::WriteProperty,
- instr.propertyIndex, a);
- QML_END_INSTR(AssignCustomType)
-
- QML_BEGIN_INSTR(AssignSignalObject)
- // XXX optimize
-
- QObject *assign = objects.pop();
- QObject *target = objects.top();
- int sigIdx = instr.signal;
- const QString &pr = PRIMITIVES.at(sigIdx);
-
- QQmlProperty prop(target, pr);
- if (prop.type() & QQmlProperty::SignalProperty) {
-
- QMetaMethod method = QQmlMetaType::defaultMethod(assign);
- if (!method.isValid())
- VME_EXCEPTION_WITH_COLUMN(tr("Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())), instr.line, instr.column);
-
- if (!QMetaObject::checkConnectArgs(prop.method(), method)) {
- VME_EXCEPTION(tr("Cannot connect mismatched signal/slot %1 %vs. %2")
- .arg(QString::fromLatin1(method.methodSignature().constData()))
- .arg(QString::fromLatin1(prop.method().methodSignature().constData())), instr.line);
- }
-
- QQmlPropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
-
- } else {
- VME_EXCEPTION(tr("Cannot assign an object to signal property %1").arg(pr), instr.line);
- }
-
-
- QML_END_INSTR(AssignSignalObject)
-
- QML_BEGIN_INSTR(StoreSignal)
- QObject *target = objects.top();
- QObject *context = objects.at(objects.count() - 1 - instr.context);
-
- QV4::ExecutionContext *qmlContext = qmlBindingContext(engine, QV8Engine::getV4(engine), qmlBindingWrappers, CTXT, context, objects.count() - 1 - instr.context);
-
- QV4::Function *runtimeFunction = COMP->compilationUnit->runtimeFunctions[instr.runtimeFunctionIndex];
-
- tmpValue = QV4::FunctionObject::creatScriptFunction(qmlContext, runtimeFunction, /*createProto*/ false);
-
- QQmlBoundSignal *bs = new QQmlBoundSignal(target, instr.signalIndex, target, engine);
- QQmlBoundSignalExpression *expr =
- new QQmlBoundSignalExpression(target, instr.signalIndex,
- CTXT, context, tmpValue);
- bs->takeExpression(expr);
- QML_END_INSTR(StoreSignal)
-
- QML_BEGIN_INSTR(StoreImportedScript)
- QV4::Scope scope(v4);
- QV4::ScopedObject scripts(scope, CTXT->importedScripts.value());
- if (!scripts) {
- scripts = v4->newArrayObject();
- CTXT->importedScripts = scripts;
- }
- scripts->putIndexed(instr.value, SCRIPTS.at(instr.value)->scriptValueForContext(CTXT));
- QML_END_INSTR(StoreImportedScript)
-
- QML_BEGIN_INSTR(StoreScriptString)
- QObject *target = objects.top();
- QObject *scope = objects.at(objects.count() - 1 - instr.scope);
- QQmlScriptString ss(PRIMITIVES.at(instr.value), CTXT->asQQmlContext(), scope);
- ss.d.data()->bindingId = instr.bindingId;
- ss.d.data()->lineNumber = qmlSourceCoordinate(instr.line);
- ss.d.data()->columnNumber = qmlSourceCoordinate(instr.column);
- ss.d.data()->isStringLiteral = instr.isStringLiteral;
- ss.d.data()->isNumberLiteral = instr.isNumberLiteral;
- ss.d.data()->numberValue = instr.numberValue;
-
- void *a[] = { &ss, 0, &status, &flags };
- QMetaObject::metacall(target, QMetaObject::WriteProperty,
- instr.propertyIndex, a);
- QML_END_INSTR(StoreScriptString)
-
- QML_BEGIN_INSTR(BeginObject)
- Q_QML_VME_PROFILE(profiler, push());
- QObject *target = objects.top();
- QQmlParserStatus *status = reinterpret_cast<QQmlParserStatus *>(reinterpret_cast<char *>(target) + instr.castValue);
- parserStatus.push(status);
-#ifdef QML_ENABLE_TRACE
- Q_ASSERT(QObjectPrivate::get(target)->declarativeData);
- parserStatusData.push(static_cast<QQmlData *>(QObjectPrivate::get(target)->declarativeData));
-#endif
- status->d = &parserStatus.top();
-
- status->classBegin();
- QML_END_INSTR(BeginObject)
-
- QML_BEGIN_INSTR(StoreBinding)
- QObject *target =
- objects.at(objects.count() - 1 - instr.owner);
- QObject *context =
- objects.at(objects.count() - 1 - instr.context);
-
- if (instr.isRoot && BINDINGSKIPLIST.testBit(instr.property.coreIndex))
- QML_NEXT_INSTR(StoreBinding);
-
- QV4::ExecutionContext *qmlContext = qmlBindingContext(engine, QV8Engine::getV4(engine), qmlBindingWrappers, CTXT, context, objects.count() - 1 - instr.context);
-
- QV4::Function *runtimeFunction = COMP->compilationUnit->runtimeFunctions[instr.functionIndex];
-
- tmpValue = QV4::FunctionObject::creatScriptFunction(qmlContext, runtimeFunction, /*createProto*/ false);
-
- QQmlBinding *bind = new QQmlBinding(tmpValue, context, CTXT, COMP->name, instr.line, instr.column);
- bindValues.push(bind);
- bind->m_mePtr = &bindValues.top();
- bind->setTarget(target, instr.property, CTXT);
-
- if (instr.isAlias) {
- QQmlAbstractBinding *old =
- QQmlPropertyPrivate::setBindingNoEnable(target,
- instr.property.coreIndex,
- instr.property.getValueTypeCoreIndex(),
- bind);
- if (old) { old->destroy(); }
- } else {
- typedef QQmlPropertyPrivate QDPP;
- Q_ASSERT(bind->propertyIndex() == QDPP::bindingIndex(instr.property));
- Q_ASSERT(bind->object() == target);
-
- CLEAN_PROPERTY(target, QDPP::bindingIndex(instr.property));
-
- bind->addToObject();
-
- if (!instr.property.isValueTypeVirtual()) {
- QQmlData *data = QQmlData::get(target);
- Q_ASSERT(data);
- data->setPendingBindingBit(target, instr.property.coreIndex);
- }
- }
- QML_END_INSTR(StoreBinding)
-
- QML_BEGIN_INSTR(StoreValueSource)
- QObject *obj = objects.pop();
- QQmlPropertyValueSource *vs = reinterpret_cast<QQmlPropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.castValue);
- QObject *target = obj->parent();
- vs->setTarget(QQmlPropertyPrivate::restore(target, instr.property, CTXT));
- QML_END_INSTR(StoreValueSource)
-
- QML_BEGIN_INSTR(StoreValueInterceptor)
- QObject *obj = objects.pop();
- QQmlPropertyValueInterceptor *vi = reinterpret_cast<QQmlPropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.castValue);
- QObject *target = obj->parent();
- QQmlProperty prop =
- QQmlPropertyPrivate::restore(target, instr.property, CTXT);
- vi->setTarget(prop);
- QQmlVMEMetaObject *mo = QQmlVMEMetaObject::get(target);
- Q_ASSERT(mo);
- mo->registerInterceptor(prop.index(), QQmlPropertyPrivate::valueTypeCoreIndex(prop), vi);
- QML_END_INSTR(StoreValueInterceptor)
-
- QML_BEGIN_INSTR(StoreObjectQList)
- QObject *assign = objects.pop();
-
- const List &list = lists.top();
- if (list.qListProperty.append)
- list.qListProperty.append((QQmlListProperty<void>*)&list.qListProperty, assign);
- else
- VME_EXCEPTION(tr("Cannot assign object to read only list"), -1);
- QML_END_INSTR(StoreObjectQList)
-
- QML_BEGIN_INSTR(AssignObjectList)
- // This is only used for assigning interfaces
- QObject *assign = objects.pop();
- const List &list = lists.top();
-
- int type = list.type;
-
- void *ptr = 0;
-
- const char *iid = QQmlMetaType::interfaceIId(type);
- if (iid)
- ptr = assign->qt_metacast(iid);
- if (!ptr)
- VME_EXCEPTION(tr("Cannot assign object to list"), instr.line);
-
- if (list.qListProperty.append)
- list.qListProperty.append((QQmlListProperty<void>*)&list.qListProperty, ptr);
- else
- VME_EXCEPTION(tr("Cannot assign object to read only list"), -1);
- QML_END_INSTR(AssignObjectList)
-
- QML_BEGIN_INSTR(StoreInterface)
- QObject *assign = objects.pop();
- QObject *target = objects.top();
- CLEAN_PROPERTY(target, instr.propertyIndex);
-
- int coreIdx = instr.propertyIndex;
- QMetaProperty prop = target->metaObject()->property(coreIdx);
- int t = prop.userType();
- const char *iid = QQmlMetaType::interfaceIId(t);
- bool ok = false;
- if (iid) {
- void *ptr = assign->qt_metacast(iid);
- if (ptr) {
- void *a[] = { &ptr, 0, &status, &flags };
- QMetaObject::metacall(target,
- QMetaObject::WriteProperty,
- coreIdx, a);
- ok = true;
- }
- }
-
- if (!ok)
- VME_EXCEPTION(tr("Cannot assign object to interface property"), instr.line);
- QML_END_INSTR(StoreInterface)
-
- QML_BEGIN_INSTR(FetchAttached)
- QObject *target = objects.top();
-
- QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.id, target);
-
- if (!qmlObject)
- VME_EXCEPTION(tr("Unable to create attached object"), instr.line);
-
- objects.push(qmlObject);
- qmlBindingWrappers[objects.count() - 1] = QV4::Primitive::undefinedValue();
- QML_END_INSTR(FetchAttached)
-
- QML_BEGIN_INSTR(FetchQList)
- QObject *target = objects.top();
-
- lists.push(List(instr.type));
-
- void *a[1];
- a[0] = (void *)&(lists.top().qListProperty);
- QMetaObject::metacall(target, QMetaObject::ReadProperty,
- instr.property, a);
- QML_END_INSTR(FetchQList)
-
- QML_BEGIN_INSTR(FetchObject)
- QObject *target = objects.top();
-
- QObject *obj = 0;
- // NOTE: This assumes a cast to QObject does not alter the
- // object pointer
- void *a[1];
- a[0] = &obj;
- QMetaObject::metacall(target, QMetaObject::ReadProperty,
- instr.property, a);
-
- if (!obj)
- VME_EXCEPTION_WITH_COLUMN(tr("Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.property).name())), instr.line, instr.column);
-
- objects.push(obj);
- qmlBindingWrappers[objects.count() - 1] = QV4::Primitive::undefinedValue();
- QML_END_INSTR(FetchObject)
-
- QML_BEGIN_INSTR(PopQList)
- lists.pop();
- QML_END_INSTR(PopQList)
-
- QML_BEGIN_INSTR(Defer)
- if (instr.deferCount) {
- QObject *target = objects.top();
- QQmlData *data = QQmlData::get(target, true);
- if (data->deferredData) {
- //This rare case still won't always work right
- qmlInfo(target) << "Setting deferred property across multiple components may not work";
- delete data->deferredData;
- }
- data->deferredData = new QQmlData::DeferredData;
- //If we're in a CreateQML here, data->compiledData could be reset later
- data->deferredData->compiledData = COMP;
- data->deferredData->context = CTXT;
- // Keep this data referenced until we're initialized
- data->deferredData->compiledData->addref();
- data->deferredData->deferredIdx = INSTRUCTIONSTREAM - COMP->bytecode.constData();
- Q_ASSERT(data->deferredData->deferredIdx != 0);
- INSTRUCTIONSTREAM += instr.deferCount;
- }
- QML_END_INSTR(Defer)
-
- QML_BEGIN_INSTR(PopFetchedObject)
- objects.pop();
- QML_END_INSTR(PopFetchedObject)
-
- QML_BEGIN_INSTR(FetchValueType)
- QObject *target = objects.top();
-
- if (instr.bindingSkipList != 0) {
- // Possibly need to clear bindings
- QQmlData *targetData = QQmlData::get(target);
- if (targetData) {
- QQmlAbstractBinding *binding =
- QQmlPropertyPrivate::binding(target, instr.property, -1);
-
- if (binding && binding->bindingType() != QQmlAbstractBinding::ValueTypeProxy) {
- QQmlPropertyPrivate::setBinding(target, instr.property, -1, 0);
- binding->destroy();
- } else if (binding) {
- QQmlValueTypeProxyBinding *proxy =
- static_cast<QQmlValueTypeProxyBinding *>(binding);
- proxy->removeBindings(instr.bindingSkipList);
- }
- }
- }
-
- QQmlValueType *valueHandler = QQmlValueTypeFactory::valueType(instr.type);
- Q_ASSERT(valueHandler);
- valueHandler->read(target, instr.property);
- objects.push(valueHandler);
- qmlBindingWrappers[objects.count() - 1] = QV4::Primitive::undefinedValue();
- QML_END_INSTR(FetchValueType)
-
- QML_BEGIN_INSTR(PopValueType)
- QQmlValueType *valueHandler =
- static_cast<QQmlValueType *>(objects.pop());
- QObject *target = objects.top();
- valueHandler->write(target, instr.property, QQmlPropertyPrivate::BypassInterceptor);
- QML_END_INSTR(PopValueType)
-
-#ifdef QML_THREADED_VME_INTERPRETER
- // nothing to do
-#else
- default:
- Q_UNREACHABLE();
- qFatal("QQmlCompiledData: Internal error - unknown instruction %d", genericInstr->common.instructionType);
- break;
- }
- }
-#endif
-
-exceptionExit:
- Q_ASSERT(!states.isEmpty());
- Q_ASSERT(!errors->isEmpty());
-
- reset();
-
- return 0;
-
-normalExit:
- Q_ASSERT(objects.count() == 1);
-
- QObject *rv = objects.top();
-
- objects.deallocate();
- lists.deallocate();
- states.clear();
- Q_QML_VME_PROFILE(profiler, stop());
-
- return rv;
-}
-
-void QQmlVME::reset()
-{
- Q_ASSERT(!states.isEmpty() || objects.isEmpty());
-
- QRecursionWatcher<QQmlVME, &QQmlVME::recursion> watcher(this);
-
- if (!objects.isEmpty() && !(states.at(0).flags & State::Deferred))
- delete objects.at(0);
-
- if (!rootContext.isNull())
- rootContext->activeVMEData = 0;
-
- // Remove the QQmlParserStatus and QQmlAbstractBinding back pointers
- blank(parserStatus);
- blank(bindValues);
-
- while (componentAttached) {
- QQmlComponentAttached *a = componentAttached;
- a->rem();
- }
-
- engine = 0;
- objects.deallocate();
- lists.deallocate();
- bindValues.deallocate();
- parserStatus.deallocate();
-#ifdef QML_ENABLE_TRACE
- parserStatusData.deallocate();
-#endif
- finalizeCallbacks.clear();
- states.clear();
- rootContext = 0;
- creationContext = 0;
-
- // If profiling is switched off during a VME run and then switched back on
- // before or during the next run background ranges from the first run will
- // be reported in the second run because we don't clear() here. We accept
- // that as the collected data will be incomplete anyway and because not
- // calling clear() here is benefitial for the non-profiling case.
- Q_QML_VME_PROFILE(profiler, clear(true));
-}
-
-#ifdef QML_THREADED_VME_INTERPRETER
-void *const *QQmlVME::instructionJumpTable()
-{
- static void * const *jumpTable = 0;
- if (!jumpTable) {
- QQmlVME dummy;
- QQmlInstantiationInterrupt i;
- dummy.run(0, i, &jumpTable);
- }
- return jumpTable;
-}
-#endif
-
-QQmlContextData *QQmlVME::complete(const QQmlInstantiationInterrupt &interrupt)
-{
- Q_ASSERT(engine ||
- (bindValues.isEmpty() &&
- parserStatus.isEmpty() &&
- componentAttached == 0 &&
- rootContext.isNull() &&
- finalizeCallbacks.isEmpty()));
-
- if (!engine)
- return 0;
-
- QQmlTrace trace("VME Complete");
-#ifdef QML_ENABLE_TRACE
- trace.addDetail("URL", rootComponent->url);
-#endif
-
- ActiveVMERestorer restore(this, QQmlEnginePrivate::get(engine));
- QRecursionWatcher<QQmlVME, &QQmlVME::recursion> watcher(this);
-
- {
- QQmlTrace trace("VME Binding Enable");
- trace.event("begin binding eval");
- while (!bindValues.isEmpty()) {
- QQmlAbstractBinding *b = bindValues.pop();
-
- if (b) {
- b->m_mePtr = 0;
- QQmlData *data = QQmlData::get(b->object());
- Q_ASSERT(data);
- data->clearPendingBindingBit(b->propertyIndex());
- b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::DontRemoveBinding);
- }
-
- if (watcher.hasRecursed() || interrupt.shouldInterrupt())
- return 0;
- }
- bindValues.deallocate();
- }
-
- if (componentCompleteEnabled()) { // the qml designer does the component complete later
- QQmlTrace trace("VME Component Complete");
- while (!parserStatus.isEmpty()) {
- Q_QML_VME_PROFILE(profiler, pop());
- QQmlParserStatus *status = parserStatus.pop();
-#ifdef QML_ENABLE_TRACE
- QQmlData *data = parserStatusData.pop();
-#endif
-
- if (status && status->d) {
- status->d = 0;
-#ifdef QML_ENABLE_TRACE
- QQmlTrace trace("Component complete");
- trace.addDetail("URL", data->outerContext->url);
- trace.addDetail("Line", data->lineNumber);
-#endif
- status->componentComplete();
- }
-
- if (watcher.hasRecursed() || interrupt.shouldInterrupt())
- return 0;
- }
- parserStatus.deallocate();
- Q_QML_VME_PROFILE(profiler, clear());
- }
-
- {
- QQmlTrace trace("VME Finalize Callbacks");
- for (int ii = 0; ii < finalizeCallbacks.count(); ++ii) {
- QQmlEnginePrivate::FinalizeCallback callback = finalizeCallbacks.at(ii);
- QObject *obj = callback.first;
- if (obj) {
- void *args[] = { 0 };
- QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, callback.second, args);
- }
- if (watcher.hasRecursed())
- return 0;
- }
- finalizeCallbacks.clear();
- }
-
- {
- QQmlTrace trace("VME Component.onCompleted Callbacks");
- while (componentAttached) {
- QQmlComponentAttached *a = componentAttached;
- a->rem();
- QQmlData *d = QQmlData::get(a->parent());
- Q_ASSERT(d);
- Q_ASSERT(d->context);
- a->add(&d->context->componentAttached);
- if (componentCompleteEnabled())
- emit a->completed();
-
- if (watcher.hasRecursed() || interrupt.shouldInterrupt())
- return 0;
- }
- }
-
- QQmlContextData *rv = rootContext;
-
- reset();
-
- if (rv) rv->activeVMEData = data;
-
- return rv;
-}
-
void QQmlVME::enableComponentComplete()
{
s_enableComponentComplete = true;
@@ -1283,22 +99,6 @@ bool QQmlVME::componentCompleteEnabled()
return s_enableComponentComplete;
}
-void QQmlVME::blank(QFiniteStack<QQmlAbstractBinding *> &bs)
-{
- for (int ii = 0; ii < bs.count(); ++ii) {
- QQmlAbstractBinding *b = bs.at(ii);
- if (b) b->m_mePtr = 0;
- }
-}
-
-void QQmlVME::blank(QFiniteStack<QQmlParserStatus *> &pss)
-{
- for (int ii = 0; ii < pss.count(); ++ii) {
- QQmlParserStatus *ps = pss.at(ii);
- if(ps) ps->d = 0;
- }
-}
-
QQmlVMEGuard::QQmlVMEGuard()
: m_objectCount(0), m_objects(0), m_contextCount(0), m_contexts(0)
{
@@ -1309,23 +109,6 @@ QQmlVMEGuard::~QQmlVMEGuard()
clear();
}
-void QQmlVMEGuard::guard(QQmlVME *vme)
-{
- clear();
-
- m_objectCount = vme->objects.count();
- m_objects = new QPointer<QObject>[m_objectCount];
- for (int ii = 0; ii < m_objectCount; ++ii)
- m_objects[ii] = vme->objects[ii];
-
- m_contextCount = (vme->rootContext.isNull()?0:1) + vme->states.count();
- m_contexts = new QQmlGuardedContextData[m_contextCount];
- for (int ii = 0; ii < vme->states.count(); ++ii)
- m_contexts[ii] = vme->states.at(ii).context;
- if (!vme->rootContext.isNull())
- m_contexts[m_contextCount - 1] = vme->rootContext.contextData();
-}
-
void QQmlVMEGuard::guard(QQmlObjectCreator *creator)
{
clear();
diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h
index cde8c0c6c4..f6476d77e0 100644
--- a/src/qml/qml/qqmlvme_p.h
+++ b/src/qml/qml/qqmlvme_p.h
@@ -55,7 +55,6 @@
#include "qqmlerror.h"
#include <private/qbitfield_p.h>
-#include "qqmlinstruction_p.h"
#include <private/qrecursionwatcher_p.h>
#include <QtCore/QStack>
@@ -122,67 +121,12 @@ private:
class Q_QML_PRIVATE_EXPORT QQmlVME
{
- Q_DECLARE_TR_FUNCTIONS(QQmlVME)
public:
- QQmlVME() : data(0), componentAttached(0) {}
- QQmlVME(void *data) : data(data), componentAttached(0) {}
-
- void *data;
- QQmlComponentAttached *componentAttached;
- QList<QQmlEnginePrivate::FinalizeCallback> finalizeCallbacks;
-
- void init(QQmlContextData *, QQmlCompiledData *, int start,
- QQmlContextData * = 0);
- bool initDeferred(QObject *);
- void reset();
-
- QObject *execute(QList<QQmlError> *errors, const QQmlInstantiationInterrupt & = QQmlInstantiationInterrupt());
- QQmlContextData *complete(const QQmlInstantiationInterrupt & = QQmlInstantiationInterrupt());
-
static void enableComponentComplete();
static void disableComponentComplete();
static bool componentCompleteEnabled();
private:
- friend class QQmlVMEGuard;
-
- QObject *run(QList<QQmlError> *errors, const QQmlInstantiationInterrupt &
-#ifdef QML_THREADED_VME_INTERPRETER
- , void *const**storeJumpTable = 0
-#endif
- );
-
-#ifdef QML_THREADED_VME_INTERPRETER
- static void *const*instructionJumpTable();
- friend class QQmlCompiledData;
-#endif
-
- QQmlEngine *engine;
- QRecursionNode recursion;
-
-#ifdef QML_ENABLE_TRACE
- QQmlCompiledData *rootComponent;
-#endif
-
- QFiniteStack<QObject *> objects;
- QFiniteStack<QQmlVMETypes::List> lists;
-
- QFiniteStack<QQmlAbstractBinding *> bindValues;
- QFiniteStack<QQmlParserStatus *> parserStatus;
-#ifdef QML_ENABLE_TRACE
- QFiniteStack<QQmlData *> parserStatusData;
-#endif
- QQmlVmeProfiler profiler;
-
- QQmlGuardedContextData rootContext;
- QQmlGuardedContextData creationContext;
-
- typedef QQmlVMETypes::State State;
- QStack<State> states;
-
- static void blank(QFiniteStack<QQmlParserStatus *> &);
- static void blank(QFiniteStack<QQmlAbstractBinding *> &);
-
static bool s_enableComponentComplete;
};
@@ -195,7 +139,6 @@ public:
QQmlVMEGuard();
~QQmlVMEGuard();
- void guard(QQmlVME *);
void guard(QQmlObjectCreator *);
void clear();
diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp
index 70f859ffe2..122056e653 100644
--- a/src/qml/types/qqmlconnections.cpp
+++ b/src/qml/types/qqmlconnections.cpp
@@ -203,54 +203,6 @@ void QQmlConnections::setIgnoreUnknownSignals(bool ignore)
d->ignoreUnknownSignals = ignore;
}
-
-
-QByteArray
-QQmlConnectionsParser::compile(const QList<QQmlCustomParserProperty> &props)
-{
- QByteArray rv;
- QDataStream ds(&rv, QIODevice::WriteOnly);
-
- for(int ii = 0; ii < props.count(); ++ii)
- {
- QString propName = props.at(ii).name();
- int propLine = props.at(ii).location().line;
- int propColumn = props.at(ii).location().column;
-
- if (!propName.startsWith(QLatin1String("on")) || !propName.at(2).isUpper()) {
- error(props.at(ii), QQmlConnections::tr("Cannot assign to non-existent property \"%1\"").arg(propName));
- return QByteArray();
- }
-
- QList<QVariant> values = props.at(ii).assignedValues();
-
- for (int i = 0; i < values.count(); ++i) {
- const QVariant &value = values.at(i);
-
- if (value.userType() == qMetaTypeId<QQmlCustomParserNode>()) {
- error(props.at(ii), QQmlConnections::tr("Connections: nested objects not allowed"));
- return QByteArray();
- } else if (value.userType() == qMetaTypeId<QQmlCustomParserProperty>()) {
- error(props.at(ii), QQmlConnections::tr("Connections: syntax error"));
- return QByteArray();
- } else {
- QQmlScript::Variant v = qvariant_cast<QQmlScript::Variant>(value);
- if (v.isScript()) {
- ds << propName;
- ds << v.asScript();
- ds << propLine;
- ds << propColumn;
- } else {
- error(props.at(ii), QQmlConnections::tr("Connections: script expected"));
- return QByteArray();
- }
- }
- }
- }
-
- return rv;
-}
-
QByteArray QQmlConnectionsParser::compile(const QV4::CompiledData::QmlUnit *qmlUnit, int objectIndex, const QList<const QV4::CompiledData::Binding *> &props)
{
Q_UNUSED(objectIndex)
diff --git a/src/qml/types/qqmlconnections_p.h b/src/qml/types/qqmlconnections_p.h
index cb436b1eb4..f9b664cccf 100644
--- a/src/qml/types/qqmlconnections_p.h
+++ b/src/qml/types/qqmlconnections_p.h
@@ -84,7 +84,6 @@ private:
class QQmlConnectionsParser : public QQmlCustomParser
{
public:
- virtual QByteArray compile(const QList<QQmlCustomParserProperty> &);
virtual QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, int objectIndex, const QList<const QV4::CompiledData::Binding *> &props);
virtual void setCustomData(QObject *, const QByteArray &);
};
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index 60c6389d28..e0d9094387 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -1872,16 +1872,8 @@ void QQmlDelegateModelItem::incubateObject(
incubatorPriv->compiledData = componentPriv->cc;
incubatorPriv->compiledData->addref();
- if (enginePriv->useNewCompiler) {
- incubatorPriv->creator.reset(new QQmlObjectCreator(context, componentPriv->cc, componentPriv->creationContext));
- incubatorPriv->subComponentToCreate = componentPriv->start;
- } else {
- incubatorPriv->vme.init(
- context,
- componentPriv->cc,
- componentPriv->start,
- componentPriv->creationContext);
- }
+ incubatorPriv->creator.reset(new QQmlObjectCreator(context, componentPriv->cc, componentPriv->creationContext));
+ incubatorPriv->subComponentToCreate = componentPriv->start;
enginePriv->incubate(*incubationTask, forContext);
}
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index fbf3c091c2..dd52dfc1d4 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -2252,139 +2252,6 @@ void QQmlListModel::sync()
qmlInfo(this) << "List sync() can only be called from a WorkerScript";
}
-bool QQmlListModelParser::compileProperty(const QQmlCustomParserProperty &prop, QList<ListInstruction> &instr, QByteArray &data)
-{
- QList<QVariant> values = prop.assignedValues();
- for(int ii = 0; ii < values.count(); ++ii) {
- const QVariant &value = values.at(ii);
-
- if(value.userType() == qMetaTypeId<QQmlCustomParserNode>()) {
- QQmlCustomParserNode node =
- qvariant_cast<QQmlCustomParserNode>(value);
-
- if (node.name() != listElementTypeName) {
- const QMetaObject *mo = resolveType(node.name());
- if (mo != &QQmlListElement::staticMetaObject) {
- error(node, QQmlListModel::tr("ListElement: cannot contain nested elements"));
- return false;
- }
- listElementTypeName = node.name(); // cache right name for next time
- }
-
- {
- ListInstruction li;
- li.type = ListInstruction::Push;
- li.dataIdx = -1;
- instr << li;
- }
-
- QList<QQmlCustomParserProperty> props = node.properties();
- for(int jj = 0; jj < props.count(); ++jj) {
- const QQmlCustomParserProperty &nodeProp = props.at(jj);
- if (nodeProp.name().isEmpty()) {
- error(nodeProp, QQmlListModel::tr("ListElement: cannot contain nested elements"));
- return false;
- }
- if (nodeProp.name() == QStringLiteral("id")) {
- error(nodeProp, QQmlListModel::tr("ListElement: cannot use reserved \"id\" property"));
- return false;
- }
-
- ListInstruction li;
- int ref = data.count();
- data.append(nodeProp.name().toUtf8());
- data.append('\0');
- li.type = ListInstruction::Set;
- li.dataIdx = ref;
- instr << li;
-
- if(!compileProperty(nodeProp, instr, data))
- return false;
-
- li.type = ListInstruction::Pop;
- li.dataIdx = -1;
- instr << li;
- }
-
- {
- ListInstruction li;
- li.type = ListInstruction::Pop;
- li.dataIdx = -1;
- instr << li;
- }
-
- } else {
-
- QQmlScript::Variant variant =
- qvariant_cast<QQmlScript::Variant>(value);
-
- int ref = data.count();
-
- QByteArray d;
- d += char(variant.type()); // type tag
- if (variant.isString()) {
- d += variant.asString().toUtf8();
- } else if (variant.isNumber()) {
- d += QByteArray::number(variant.asNumber(),'g',20);
- } else if (variant.isBoolean()) {
- d += char(variant.asBoolean());
- } else if (variant.isScript()) {
- if (definesEmptyList(variant.asScript())) {
- d[0] = char(QQmlScript::Variant::Invalid); // marks empty list
- } else {
- QByteArray script = variant.asScript().toUtf8();
- bool ok;
- int v = evaluateEnum(script, &ok);
- if (!ok) {
- using namespace QQmlJS;
- AST::Node *node = variant.asAST();
- AST::StringLiteral *literal = 0;
- if (AST::CallExpression *callExpr = AST::cast<AST::CallExpression *>(node)) {
- if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(callExpr->base)) {
- if (idExpr->name == QLatin1String("QT_TR_NOOP") || idExpr->name == QLatin1String("QT_TRID_NOOP")) {
- if (callExpr->arguments && !callExpr->arguments->next)
- literal = AST::cast<AST::StringLiteral *>(callExpr->arguments->expression);
- if (!literal) {
- error(prop, QQmlListModel::tr("ListElement: improperly specified %1").arg(idExpr->name.toString()));
- return false;
- }
- } else if (idExpr->name == QLatin1String("QT_TRANSLATE_NOOP")) {
- if (callExpr->arguments && callExpr->arguments->next && !callExpr->arguments->next->next)
- literal = AST::cast<AST::StringLiteral *>(callExpr->arguments->next->expression);
- if (!literal) {
- error(prop, QQmlListModel::tr("ListElement: improperly specified QT_TRANSLATE_NOOP"));
- return false;
- }
- }
- }
- }
-
- if (literal) {
- d[0] = char(QQmlScript::Variant::String);
- d += literal->value.toUtf8();
- } else {
- error(prop, QQmlListModel::tr("ListElement: cannot use script for property value"));
- return false;
- }
- } else {
- d[0] = char(QQmlScript::Variant::Number);
- d += QByteArray::number(v);
- }
- }
- }
- d.append('\0');
- data.append(d);
-
- ListInstruction li;
- li.type = ListInstruction::Value;
- li.dataIdx = ref;
- instr << li;
- }
- }
-
- return true;
-}
-
bool QQmlListModelParser::compileProperty(const QV4::CompiledData::QmlUnit *qmlUnit, int objectIndex, const QV4::CompiledData::Binding *binding, QList<QQmlListModelParser::ListInstruction> &instr, QByteArray &data)
{
if (binding->type >= QV4::CompiledData::Binding::Type_Object) {
@@ -2448,18 +2315,18 @@ bool QQmlListModelParser::compileProperty(const QV4::CompiledData::QmlUnit *qmlU
QByteArray d;
if (binding->type == QV4::CompiledData::Binding::Type_String) {
- d += char(QQmlScript::Variant::String);
+ d += char(String);
d += binding->valueAsString(&qmlUnit->header).toUtf8();
} else if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- d += char(QQmlScript::Variant::Number);
+ d += char(Number);
d += QByteArray::number(binding->valueAsNumber(),'g',20);
} else if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
- d += char(QQmlScript::Variant::Boolean);
+ d += char(Boolean);
d += char(binding->valueAsBoolean());
} else if (binding->type == QV4::CompiledData::Binding::Type_Script) {
QString scriptStr = binding->valueAsScriptString(&qmlUnit->header);
if (definesEmptyList(scriptStr)) {
- d[0] = char(QQmlScript::Variant::Invalid); // marks empty list
+ d[0] = char(Invalid); // marks empty list
} else {
QByteArray script = scriptStr.toUtf8();
bool ok;
@@ -2491,14 +2358,14 @@ bool QQmlListModelParser::compileProperty(const QV4::CompiledData::QmlUnit *qmlU
}
if (literal) {
- d[0] = char(QQmlScript::Variant::String);
+ d[0] = char(String);
d += literal->value.toUtf8();
} else {
error(binding, QQmlListModel::tr("ListElement: cannot use script for property value"));
return false;
}
} else {
- d[0] = char(QQmlScript::Variant::Number);
+ d[0] = char(Number);
d += QByteArray::number(v);
}
}
@@ -2516,42 +2383,6 @@ bool QQmlListModelParser::compileProperty(const QV4::CompiledData::QmlUnit *qmlU
return true;
}
-QByteArray QQmlListModelParser::compile(const QList<QQmlCustomParserProperty> &customProps)
-{
- QList<ListInstruction> instr;
- QByteArray data;
- listElementTypeName = QString(); // unknown
-
- for(int ii = 0; ii < customProps.count(); ++ii) {
- const QQmlCustomParserProperty &prop = customProps.at(ii);
- if(!prop.name().isEmpty()) { // isn't default property
- error(prop, QQmlListModel::tr("ListModel: undefined property '%1'").arg(prop.name()));
- return QByteArray();
- }
-
- if(!compileProperty(prop, instr, data)) {
- return QByteArray();
- }
- }
-
- int size = sizeof(ListModelData) +
- instr.count() * sizeof(ListInstruction) +
- data.count();
-
- QByteArray rv;
- rv.resize(size);
-
- ListModelData *lmd = (ListModelData *)rv.data();
- lmd->dataOffset = sizeof(ListModelData) +
- instr.count() * sizeof(ListInstruction);
- lmd->instrCount = instr.count();
- for (int ii = 0; ii < instr.count(); ++ii)
- lmd->instructions()[ii] = instr.at(ii);
- ::memcpy(rv.data() + lmd->dataOffset, data.constData(), data.count());
-
- return rv;
-}
-
QByteArray QQmlListModelParser::compile(const QV4::CompiledData::QmlUnit *qmlUnit, int objectIndex, const QList<const QV4::CompiledData::Binding *> &bindings)
{
QList<ListInstruction> instr;
@@ -2647,21 +2478,21 @@ void QQmlListModelParser::setCustomData(QObject *obj, const QByteArray &d)
QString name = e0.name;
QVariant value;
- switch (QQmlScript::Variant::Type(data[instr.dataIdx])) {
- case QQmlScript::Variant::Invalid:
+ switch (PropertyType(data[instr.dataIdx])) {
+ case Invalid:
{
const ListLayout::Role &role = e1.model->getOrCreateListRole(e0.name);
ListModel *emptyModel = new ListModel(role.subLayout, 0, -1);
value = QVariant::fromValue(emptyModel);
}
break;
- case QQmlScript::Variant::Boolean:
+ case Boolean:
value = bool(data[1 + instr.dataIdx]);
break;
- case QQmlScript::Variant::Number:
+ case Number:
value = QByteArray(data + 1 + instr.dataIdx).toDouble();
break;
- case QQmlScript::Variant::String:
+ case String:
value = QString::fromUtf8(data + 1 + instr.dataIdx);
break;
default:
diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h
index 1fd57f063c..17fbb8a819 100644
--- a/src/qml/types/qqmllistmodel_p.h
+++ b/src/qml/types/qqmllistmodel_p.h
@@ -158,8 +158,16 @@ Q_OBJECT
class QQmlListModelParser : public QQmlCustomParser
{
public:
+ enum PropertyType {
+ Invalid,
+ Boolean,
+ Number,
+ String,
+ Script
+ };
+
+
QQmlListModelParser() : QQmlCustomParser(QQmlCustomParser::AcceptsSignalHandlers) {}
- QByteArray compile(const QList<QQmlCustomParserProperty> &);
QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, int objectIndex, const QList<const QV4::CompiledData::Binding *> &bindings);
void setCustomData(QObject *, const QByteArray &);
@@ -175,7 +183,6 @@ private:
int instrCount;
ListInstruction *instructions() const;
};
- bool compileProperty(const QQmlCustomParserProperty &prop, QList<ListInstruction> &instr, QByteArray &data);
bool compileProperty(const QV4::CompiledData::QmlUnit *qmlUnit, int objectIndex, const QV4::CompiledData::Binding *binding, QList<ListInstruction> &instr, QByteArray &data);
bool definesEmptyList(const QString &);