From a129444bb0156c936900dbd2f12bd9f427ff366c Mon Sep 17 00:00:00 2001 From: Qt by Nokia Date: Wed, 27 Apr 2011 14:13:26 +0200 Subject: Initial import from qtquick2. Branched from the monolithic repo, Qt qtquick2 branch, at commit a4a585d2ee907746682846ae6e8a48e19deef469 --- src/declarative/qml/qdeclarative.h | 33 + src/declarative/qml/qdeclarativebinding.cpp | 19 +- .../qml/qdeclarativecompiledbindings.cpp | 2906 -------------------- .../qml/qdeclarativecompiledbindings_p.h | 116 - src/declarative/qml/qdeclarativecompileddata.cpp | 3 + src/declarative/qml/qdeclarativecompiler.cpp | 149 +- src/declarative/qml/qdeclarativecompiler_p.h | 5 +- src/declarative/qml/qdeclarativecomponent.cpp | 39 +- src/declarative/qml/qdeclarativecomponent.h | 1 - src/declarative/qml/qdeclarativecontext.cpp | 84 +- src/declarative/qml/qdeclarativecontext_p.h | 11 +- src/declarative/qml/qdeclarativedirparser.cpp | 23 +- src/declarative/qml/qdeclarativedirparser_p.h | 16 + src/declarative/qml/qdeclarativedom.cpp | 1835 ------------ src/declarative/qml/qdeclarativedom_p.h | 362 --- src/declarative/qml/qdeclarativedom_p_p.h | 157 -- src/declarative/qml/qdeclarativeengine.cpp | 132 +- src/declarative/qml/qdeclarativeengine.h | 3 +- src/declarative/qml/qdeclarativeengine_p.h | 25 +- src/declarative/qml/qdeclarativeexpression.cpp | 7 +- src/declarative/qml/qdeclarativeimageprovider.cpp | 33 + src/declarative/qml/qdeclarativeimageprovider.h | 5 +- src/declarative/qml/qdeclarativeimport.cpp | 208 +- src/declarative/qml/qdeclarativeimport_p.h | 6 +- src/declarative/qml/qdeclarativeinfo.cpp | 12 + src/declarative/qml/qdeclarativeinstruction.cpp | 3 + src/declarative/qml/qdeclarativeinstruction_p.h | 7 + src/declarative/qml/qdeclarativemetatype.cpp | 96 +- src/declarative/qml/qdeclarativemetatype_p.h | 39 + .../qml/qdeclarativeobjectscriptclass.cpp | 27 + src/declarative/qml/qdeclarativeprivate.h | 17 +- src/declarative/qml/qdeclarativepropertycache.cpp | 2 + src/declarative/qml/qdeclarativepropertycache_p.h | 21 +- .../qml/qdeclarativescarceresourcescriptclass.cpp | 193 ++ .../qml/qdeclarativescarceresourcescriptclass_p.h | 163 ++ src/declarative/qml/qdeclarativescriptparser.cpp | 47 +- src/declarative/qml/qdeclarativescriptparser_p.h | 2 + src/declarative/qml/qdeclarativetypeloader.cpp | 244 +- src/declarative/qml/qdeclarativetypeloader_p.h | 62 +- src/declarative/qml/qdeclarativetypenamecache.cpp | 8 +- src/declarative/qml/qdeclarativetypenamecache_p.h | 16 + .../qml/qdeclarativetypenamescriptclass.cpp | 38 +- .../qml/qdeclarativetypenamescriptclass_p.h | 1 + src/declarative/qml/qdeclarativevme.cpp | 82 +- src/declarative/qml/qdeclarativevme_p.h | 4 + src/declarative/qml/qdeclarativevmemetaobject.cpp | 10 + src/declarative/qml/qdeclarativexmlhttprequest.cpp | 21 + src/declarative/qml/qintrusivelist.cpp | 173 ++ src/declarative/qml/qintrusivelist_p.h | 254 ++ src/declarative/qml/qmetaobjectbuilder.cpp | 57 +- src/declarative/qml/qmetaobjectbuilder_p.h | 4 + src/declarative/qml/qml.pri | 14 +- src/declarative/qml/v4/qdeclarativev4bindings.cpp | 1530 +++++++++++ src/declarative/qml/v4/qdeclarativev4bindings_p.h | 92 + src/declarative/qml/v4/qdeclarativev4compiler.cpp | 1340 +++++++++ src/declarative/qml/v4/qdeclarativev4compiler_p.h | 104 + .../qml/v4/qdeclarativev4compiler_p_p.h | 184 ++ .../qml/v4/qdeclarativev4instruction.cpp | 559 ++++ .../qml/v4/qdeclarativev4instruction_p.h | 444 +++ src/declarative/qml/v4/qdeclarativev4ir.cpp | 832 ++++++ src/declarative/qml/v4/qdeclarativev4ir_p.h | 546 ++++ src/declarative/qml/v4/qdeclarativev4irbuilder.cpp | 1315 +++++++++ src/declarative/qml/v4/qdeclarativev4irbuilder_p.h | 242 ++ src/declarative/qml/v4/qdeclarativev4program_p.h | 122 + src/declarative/qml/v4/v4.pri | 17 + 65 files changed, 9420 insertions(+), 5702 deletions(-) delete mode 100644 src/declarative/qml/qdeclarativecompiledbindings.cpp delete mode 100644 src/declarative/qml/qdeclarativecompiledbindings_p.h delete mode 100644 src/declarative/qml/qdeclarativedom.cpp delete mode 100644 src/declarative/qml/qdeclarativedom_p.h delete mode 100644 src/declarative/qml/qdeclarativedom_p_p.h create mode 100644 src/declarative/qml/qdeclarativescarceresourcescriptclass.cpp create mode 100644 src/declarative/qml/qdeclarativescarceresourcescriptclass_p.h create mode 100644 src/declarative/qml/qintrusivelist.cpp create mode 100644 src/declarative/qml/qintrusivelist_p.h create mode 100644 src/declarative/qml/v4/qdeclarativev4bindings.cpp create mode 100644 src/declarative/qml/v4/qdeclarativev4bindings_p.h create mode 100644 src/declarative/qml/v4/qdeclarativev4compiler.cpp create mode 100644 src/declarative/qml/v4/qdeclarativev4compiler_p.h create mode 100644 src/declarative/qml/v4/qdeclarativev4compiler_p_p.h create mode 100644 src/declarative/qml/v4/qdeclarativev4instruction.cpp create mode 100644 src/declarative/qml/v4/qdeclarativev4instruction_p.h create mode 100644 src/declarative/qml/v4/qdeclarativev4ir.cpp create mode 100644 src/declarative/qml/v4/qdeclarativev4ir_p.h create mode 100644 src/declarative/qml/v4/qdeclarativev4irbuilder.cpp create mode 100644 src/declarative/qml/v4/qdeclarativev4irbuilder_p.h create mode 100644 src/declarative/qml/v4/qdeclarativev4program_p.h create mode 100644 src/declarative/qml/v4/v4.pri (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarative.h b/src/declarative/qml/qdeclarative.h index 5da7901528..9227260b64 100644 --- a/src/declarative/qml/qdeclarative.h +++ b/src/declarative/qml/qdeclarative.h @@ -53,6 +53,9 @@ QT_BEGIN_HEADER +#define QML_VERSION 0x020000 +#define QML_VERSION_STR "2.0" + #define QML_DECLARE_TYPE(TYPE) \ Q_DECLARE_METATYPE(TYPE *) \ Q_DECLARE_METATYPE(QDeclarativeListProperty) @@ -392,6 +395,8 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, class QDeclarativeContext; class QDeclarativeEngine; +class QScriptValue; +class QScriptEngine; Q_DECLARATIVE_EXPORT void qmlExecuteDeferred(QObject *); Q_DECLARATIVE_EXPORT QDeclarativeContext *qmlContext(const QObject *); Q_DECLARATIVE_EXPORT QDeclarativeEngine *qmlEngine(const QObject *); @@ -405,6 +410,34 @@ QObject *qmlAttachedPropertiesObject(const QObject *obj, bool create = true) return qmlAttachedPropertiesObject(&idx, obj, &T::staticMetaObject, create); } +inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMinor, + QScriptValue (*callback)(QDeclarativeEngine *, QScriptEngine *)) +{ + QDeclarativePrivate::RegisterModuleApi api = { + 0, + + uri, versionMajor, versionMinor, + + callback, 0 + }; + + return QDeclarativePrivate::qmlregister(QDeclarativePrivate::ModuleApiRegistration, &api); +} + +inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMinor, + QObject *(*callback)(QDeclarativeEngine *, QScriptEngine *)) +{ + QDeclarativePrivate::RegisterModuleApi api = { + 0, + + uri, versionMajor, versionMinor, + + 0, callback + }; + + return QDeclarativePrivate::qmlregister(QDeclarativePrivate::ModuleApiRegistration, &api); +} + QT_END_NAMESPACE QML_DECLARE_TYPE(QObject) diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index a5bd604c53..3e93ce7266 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -357,13 +357,17 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) } else { QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(d->context()->engine); + ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation. bool isUndefined = false; QVariant value; QScriptValue scriptValue = d->scriptValue(0, &isUndefined); - if (wasDeleted) + + if (wasDeleted) { + ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete. return; + } if (d->property.propertyTypeCategory() == QDeclarativeProperty::List) { value = ep->scriptValueToVariant(scriptValue, qMetaTypeId >()); @@ -420,8 +424,10 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) } else if (d->property.object() && !QDeclarativePropertyPrivate::write(d->property, value, flags)) { - if (wasDeleted) + if (wasDeleted) { + ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete. return; + } QUrl url = QUrl(d->url); int line = d->line; @@ -440,14 +446,21 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) QLatin1String(QMetaType::typeName(d->property.propertyType()))); } - if (wasDeleted) + if (wasDeleted) { + ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete. return; + } if (d->error.isValid()) { if (!d->addError(ep)) ep->warning(this->error()); } else { d->removeError(); } + + // at this point, the binding has been evaluated. If any scarce + // resources were copied during the evaluation of the binding, + // we need to release those copies. + ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete. } d->updating = false; diff --git a/src/declarative/qml/qdeclarativecompiledbindings.cpp b/src/declarative/qml/qdeclarativecompiledbindings.cpp deleted file mode 100644 index a6fcce4c99..0000000000 --- a/src/declarative/qml/qdeclarativecompiledbindings.cpp +++ /dev/null @@ -1,2906 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// #define COMPILEDBINDINGS_DEBUG -// #define REGISTER_CLEANUP_DEBUG - -#include "private/qdeclarativecompiledbindings_p.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -DEFINE_BOOL_CONFIG_OPTION(qmlExperimental, QML_EXPERIMENTAL); -DEFINE_BOOL_CONFIG_OPTION(qmlDisableOptimizer, QML_DISABLE_OPTIMIZER); -DEFINE_BOOL_CONFIG_OPTION(qmlDisableFastProperties, QML_DISABLE_FAST_PROPERTIES); -DEFINE_BOOL_CONFIG_OPTION(bindingsDump, QML_BINDINGS_DUMP); - -Q_GLOBAL_STATIC(QDeclarativeFastProperties, fastProperties); - -#if defined(Q_CC_GNU) && (!defined(Q_CC_INTEL) || __INTEL_COMPILER >= 1200) -# define QML_THREADED_INTERPRETER -#endif - -#define FOR_EACH_QML_INSTR(F) \ - F(Noop) /* Nop */ \ - F(BindingId) /* id */ \ - F(Subscribe) /* subscribe */ \ - F(SubscribeId) /* subscribe */ \ - F(FetchAndSubscribe) /* fetchAndSubscribe */ \ - F(LoadId) /* load */ \ - F(LoadScope) /* load */ \ - F(LoadRoot) /* load */ \ - F(LoadAttached) /* attached */ \ - F(ConvertIntToReal) /* unaryop */ \ - F(ConvertRealToInt) /* unaryop */ \ - F(Real) /* real_value */ \ - F(Int) /* int_value */ \ - F(Bool) /* bool_value */ \ - F(String) /* string_value */ \ - F(AddReal) /* binaryop */ \ - F(AddInt) /* binaryop */ \ - F(AddString) /* binaryop */ \ - F(MinusReal) /* binaryop */ \ - F(MinusInt) /* binaryop */ \ - F(CompareReal) /* binaryop */ \ - F(CompareString) /* binaryop */ \ - F(NotCompareReal) /* binaryop */ \ - F(NotCompareString) /* binaryop */ \ - F(GreaterThanReal) /* binaryop */ \ - F(MaxReal) /* binaryop */ \ - F(MinReal) /* binaryop */ \ - F(NewString) /* construct */ \ - F(NewUrl) /* construct */ \ - F(CleanupUrl) /* cleanup */ \ - F(CleanupString) /* cleanup */ \ - F(Copy) /* copy */ \ - F(Fetch) /* fetch */ \ - F(Store) /* store */ \ - F(Skip) /* skip */ \ - F(Done) /* done */ \ - /* Speculative property resolution */ \ - F(InitString) /* initstring */ \ - F(FindGeneric) /* find */ \ - F(FindGenericTerminal) /* find */ \ - F(FindProperty) /* find */ \ - F(FindPropertyTerminal) /* find */ \ - F(CleanupGeneric) /* cleanup */ \ - F(ConvertGenericToReal) /* unaryop */ \ - F(ConvertGenericToBool) /* unaryop */ \ - F(ConvertGenericToString) /* unaryop */ \ - F(ConvertGenericToUrl) /* unaryop */ - -#define QML_INSTR_ENUM(I) I, -#define QML_INSTR_ADDR(I) &&op_##I, - -#ifdef QML_THREADED_INTERPRETER -# define QML_BEGIN_INSTR(I) op_##I: -# define QML_END_INSTR(I) ++instr; goto *instr->common.code; -# define QML_INSTR_HEADER void *code; -#else -# define QML_BEGIN_INSTR(I) case Instr::I: -# define QML_END_INSTR(I) break; -# define QML_INSTR_HEADER -#endif - - -using namespace QDeclarativeJS; - -namespace { -// Supported types: int, qreal, QString (needs constr/destr), QObject*, bool -struct Register { - void setUndefined() { type = 0; } - void setUnknownButDefined() { type = -1; } - void setNaN() { setqreal(qSNaN()); } - bool isUndefined() const { return type == 0; } - - void setQObject(QObject *o) { *((QObject **)data) = o; type = QMetaType::QObjectStar; } - QObject *getQObject() const { return *((QObject **)data); } - - void setqreal(qreal v) { *((qreal *)data) = v; type = QMetaType::QReal; } - qreal getqreal() const { return *((qreal *)data); } - - void setint(int v) { *((int *)data) = v; type = QMetaType::Int; } - int getint() const { return *((int *)data); } - - void setbool(bool v) { *((bool *)data) = v; type = QMetaType::Bool; } - bool getbool() const { return *((bool *)data); } - - QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); } - QString *getstringptr() { return (QString *)typeDataPtr(); } - QUrl *geturlptr() { return (QUrl *)typeDataPtr(); } - const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); } - const QString *getstringptr() const { return (QString *)typeDataPtr(); } - const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); } - - void *typeDataPtr() { return (void *)&data; } - void *typeMemory() { return (void *)data; } - const void *typeDataPtr() const { return (void *)&data; } - const void *typeMemory() const { return (void *)data; } - - int gettype() const { return type; } - void settype(int t) { type = t; } - - int type; // Optional type - void *data[2]; // Object stored here - -#ifdef REGISTER_CLEANUP_DEBUG - Register() { - type = 0; - } - - ~Register() { - int allowedTypes[] = { QMetaType::QObjectStar, QMetaType::QReal, QMetaType::Int, QMetaType::Bool, 0 }; - bool found = (type == 0); - int *ctype = allowedTypes; - while (!found && *ctype) { - found = (*ctype == type); - ++ctype; - } - if (!found) - qWarning("Register leaked of type %d", type); - } -#endif -}; -} - -class QDeclarativeCompiledBindingsPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QDeclarativeCompiledBindings) - -public: - QDeclarativeCompiledBindingsPrivate(); - virtual ~QDeclarativeCompiledBindingsPrivate(); - - struct Binding : public QDeclarativeAbstractBinding, public QDeclarativeDelayedError { - Binding() : enabled(false), updating(0), property(0), - scope(0), target(0), parent(0) {} - - // Inherited from QDeclarativeAbstractBinding - virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags flags); - virtual void update(QDeclarativePropertyPrivate::WriteFlags flags); - virtual void destroy(); - - int index:30; - bool enabled:1; - bool updating:1; - int property; - QObject *scope; - QObject *target; - - QDeclarativeCompiledBindingsPrivate *parent; - }; - - typedef QDeclarativeNotifierEndpoint Subscription; - Subscription *subscriptions; - QScriptDeclarativeClass::PersistentIdentifier *identifiers; - - void run(Binding *, QDeclarativePropertyPrivate::WriteFlags flags); - - const char *programData; - Binding *m_bindings; - quint32 *m_signalTable; - - static int methodCount; - - void init(); - void run(int instr, QDeclarativeContextData *context, - QDeclarativeDelayedError *error, QObject *scope, QObject *output, QDeclarativePropertyPrivate::WriteFlags storeFlags); - - - inline void unsubscribe(int subIndex); - inline void subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex); - inline void subscribe(QObject *o, int notifyIndex, int subIndex); - - QDeclarativePropertyCache::Data *findproperty(QObject *obj, - const QScriptDeclarativeClass::Identifier &name, - QDeclarativeEnginePrivate *enginePriv, - QDeclarativePropertyCache::Data &local); - bool findproperty(QObject *obj, - Register *output, - QDeclarativeEnginePrivate *enginePriv, - int subIdx, - const QScriptDeclarativeClass::Identifier &name, - bool isTerminal); - void findgeneric(Register *output, // value output - int subIdx, // Subscription index in config - QDeclarativeContextData *context, // Context to search in - const QScriptDeclarativeClass::Identifier &name, - bool isTerminal); -}; - -QDeclarativeCompiledBindingsPrivate::QDeclarativeCompiledBindingsPrivate() -: subscriptions(0), identifiers(0) -{ -} - -QDeclarativeCompiledBindingsPrivate::~QDeclarativeCompiledBindingsPrivate() -{ - delete [] subscriptions; subscriptions = 0; - delete [] identifiers; identifiers = 0; -} - -int QDeclarativeCompiledBindingsPrivate::methodCount = -1; - -QDeclarativeCompiledBindings::QDeclarativeCompiledBindings(const char *program, QDeclarativeContextData *context) -: QObject(*(new QDeclarativeCompiledBindingsPrivate)) -{ - Q_D(QDeclarativeCompiledBindings); - - if (d->methodCount == -1) - d->methodCount = QDeclarativeCompiledBindings::staticMetaObject.methodCount(); - - d->programData = program; - - d->init(); - - QDeclarativeAbstractExpression::setContext(context); -} - -QDeclarativeCompiledBindings::~QDeclarativeCompiledBindings() -{ - Q_D(QDeclarativeCompiledBindings); - - delete [] d->m_bindings; -} - -QDeclarativeAbstractBinding *QDeclarativeCompiledBindings::configBinding(int index, QObject *target, - QObject *scope, int property) -{ - Q_D(QDeclarativeCompiledBindings); - - QDeclarativeCompiledBindingsPrivate::Binding *rv = d->m_bindings + index; - - rv->index = index; - rv->property = property; - rv->target = target; - rv->scope = scope; - rv->parent = d; - - addref(); // This is decremented in Binding::destroy() - - return rv; -} - -void QDeclarativeCompiledBindingsPrivate::Binding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags) -{ - if (enabled != e) { - enabled = e; - - if (e) update(flags); - } -} - -void QDeclarativeCompiledBindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags) -{ - QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Binding); - parent->run(this, flags); - QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Binding); -} - -void QDeclarativeCompiledBindingsPrivate::Binding::destroy() -{ - enabled = false; - removeFromObject(); - clear(); - parent->q_func()->release(); -} - -int QDeclarativeCompiledBindings::qt_metacall(QMetaObject::Call c, int id, void **) -{ - Q_D(QDeclarativeCompiledBindings); - - if (c == QMetaObject::InvokeMetaMethod && id >= d->methodCount) { - id -= d->methodCount; - - quint32 *reeval = d->m_signalTable + d->m_signalTable[id]; - quint32 count = *reeval; - ++reeval; - for (quint32 ii = 0; ii < count; ++ii) { - d->run(d->m_bindings + reeval[ii], QDeclarativePropertyPrivate::DontRemoveBinding); - } - } - return -1; -} - -void QDeclarativeCompiledBindingsPrivate::run(Binding *binding, QDeclarativePropertyPrivate::WriteFlags flags) -{ - Q_Q(QDeclarativeCompiledBindings); - - if (!binding->enabled) - return; - - QDeclarativeContextData *context = q->QDeclarativeAbstractExpression::context(); - if (!context || !context->isValid()) - return; - - if (binding->updating) { - QString name; - if (binding->property & 0xFFFF0000) { - QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine); - - QDeclarativeValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF]; - Q_ASSERT(vt); - - name = QLatin1String(binding->target->metaObject()->property(binding->property & 0xFFFF).name()); - name.append(QLatin1String(".")); - name.append(QLatin1String(vt->metaObject()->property(binding->property >> 24).name())); - } else { - name = QLatin1String(binding->target->metaObject()->property(binding->property).name()); - } - qmlInfo(binding->target) << QCoreApplication::translate("QDeclarativeCompiledBindings", "Binding loop detected for property \"%1\"").arg(name); - return; - } - - binding->updating = true; - if (binding->property & 0xFFFF0000) { - QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine); - - QDeclarativeValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF]; - Q_ASSERT(vt); - vt->read(binding->target, binding->property & 0xFFFF); - - QObject *target = vt; - run(binding->index, context, binding, binding->scope, target, flags); - - vt->write(binding->target, binding->property & 0xFFFF, flags); - } else { - run(binding->index, context, binding, binding->scope, binding->target, flags); - } - binding->updating = false; -} - -namespace { -// This structure is exactly 8-bytes in size -struct Instr { - enum { - FOR_EACH_QML_INSTR(QML_INSTR_ENUM) - }; - - union { - struct { - QML_INSTR_HEADER - quint8 type; - quint8 packing[7]; - } common; - struct { - QML_INSTR_HEADER - quint8 type; - quint8 packing; - quint16 column; - quint32 line; - } id; - struct { - QML_INSTR_HEADER - quint8 type; - quint8 packing[3]; - quint16 subscriptions; - quint16 identifiers; - } init; - struct { - QML_INSTR_HEADER - quint8 type; - qint8 reg; - quint16 offset; - quint32 index; - } subscribe; - struct { - QML_INSTR_HEADER - quint8 type; - qint8 reg; - quint8 packing[2]; - quint32 index; - } load; - struct { - QML_INSTR_HEADER - quint8 type; - qint8 output; - qint8 reg; - quint8 exceptionId; - quint32 id; - } attached; - struct { - QML_INSTR_HEADER - quint8 type; - qint8 output; - qint8 reg; - quint8 exceptionId; - quint32 index; - } store; - struct { - QML_INSTR_HEADER - quint8 type; - qint8 output; - qint8 objectReg; - quint8 exceptionId; - quint16 subscription; - quint16 function; - } fetchAndSubscribe; - struct { - QML_INSTR_HEADER - quint8 type; - qint8 output; - qint8 objectReg; - quint8 exceptionId; - quint32 index; - } fetch; - struct { - QML_INSTR_HEADER - quint8 type; - qint8 reg; - qint8 src; - quint8 packing[5]; - } copy; - struct { - QML_INSTR_HEADER - quint8 type; - qint8 reg; - quint8 packing[6]; - } construct; - struct { - QML_INSTR_HEADER - quint8 type; - qint8 reg; - quint8 packing[2]; - float value; - } real_value; - struct { - QML_INSTR_HEADER - quint8 type; - qint8 reg; - quint8 packing[2]; - int value; - } int_value; - struct { - QML_INSTR_HEADER - quint8 type; - qint8 reg; - bool value; - quint8 packing[5]; - } bool_value; - struct { - QML_INSTR_HEADER - quint8 type; - qint8 reg; - quint16 length; - quint32 offset; - } string_value; - struct { - QML_INSTR_HEADER - quint8 type; - qint8 output; - qint8 src1; - qint8 src2; - quint8 packing[4]; - } binaryop; - struct { - QML_INSTR_HEADER - quint8 type; - qint8 output; - qint8 src; - quint8 packing[5]; - } unaryop; - struct { - QML_INSTR_HEADER - quint8 type; - qint8 reg; - quint8 packing[2]; - quint32 count; - } skip; - struct { - QML_INSTR_HEADER - quint8 type; - qint8 reg; - qint8 src; - quint8 exceptionId; - quint16 name; - quint16 subscribeIndex; - } find; - struct { - QML_INSTR_HEADER - quint8 type; - qint8 reg; - quint8 packing[6]; - } cleanup; - struct { - QML_INSTR_HEADER - quint8 type; - quint8 packing[1]; - quint16 offset; - quint32 dataIdx; - } initstring; - }; -}; - -struct Program { - quint32 bindings; - quint32 dataLength; - quint32 signalTableOffset; - quint32 exceptionDataOffset; - quint16 subscriptions; - quint16 identifiers; - quint16 instructionCount; - quint16 compiled; - - const char *data() const { return ((const char *)this) + sizeof(Program); } - const Instr *instructions() const { return (const Instr *)(data() + dataLength); } -}; -} - -struct QDeclarativeBindingCompilerPrivate -{ - struct Result { - Result() : unknownType(false), metaObject(0), type(-1), reg(-1) {} - bool operator==(const Result &o) const { - return unknownType == o.unknownType && - metaObject == o.metaObject && - type == o.type && - reg == o.reg; - } - bool operator!=(const Result &o) const { - return !(*this == o); - } - bool unknownType; - const QMetaObject *metaObject; - int type; - int reg; - - QSet subscriptionSet; - }; - - QDeclarativeBindingCompilerPrivate() : registers(0) {} - - void resetInstanceState(); - int commitCompile(); - - QDeclarativeParser::Object *context; - QDeclarativeParser::Object *component; - QDeclarativeParser::Property *destination; - QHash ids; - QDeclarativeImports imports; - QDeclarativeEnginePrivate *engine; - - QString contextName() const { return QLatin1String("$$$SCOPE_") + QString::number((quintptr)context, 16); } - - bool compile(QDeclarativeJS::AST::Node *); - - bool parseExpression(QDeclarativeJS::AST::Node *, Result &); - - bool tryName(QDeclarativeJS::AST::Node *); - bool parseName(QDeclarativeJS::AST::Node *, Result &); - - bool tryArith(QDeclarativeJS::AST::Node *); - bool parseArith(QDeclarativeJS::AST::Node *, Result &); - bool numberArith(Result &, const Result &, const Result &, QSOperator::Op op); - bool stringArith(Result &, const Result &, const Result &, QSOperator::Op op); - - bool tryLogic(QDeclarativeJS::AST::Node *); - bool parseLogic(QDeclarativeJS::AST::Node *, Result &); - - bool tryConditional(QDeclarativeJS::AST::Node *); - bool parseConditional(QDeclarativeJS::AST::Node *, Result &); - - bool tryConstant(QDeclarativeJS::AST::Node *); - bool parseConstant(QDeclarativeJS::AST::Node *, Result &); - - bool tryMethod(QDeclarativeJS::AST::Node *); - bool parseMethod(QDeclarativeJS::AST::Node *, Result &); - - bool buildName(QStringList &, QDeclarativeJS::AST::Node *, QList *nodes = 0); - bool fetch(Result &type, const QMetaObject *, int reg, int idx, const QStringList &, QDeclarativeJS::AST::ExpressionNode *); - - quint32 registers; - QHash > registerCleanups; - int acquireReg(int cleanup = Instr::Noop, int cleanupType = 0); - void registerCleanup(int reg, int cleanup, int cleanupType = 0); - void releaseReg(int); - - int registerLiteralString(const QString &); - int registerString(const QString &); - QHash > registeredStrings; - QByteArray data; - - bool subscription(const QStringList &, Result *); - int subscriptionIndex(const QStringList &); - bool subscriptionNeutral(const QSet &base, const QSet &lhs, const QSet &rhs); - - quint8 exceptionId(QDeclarativeJS::AST::ExpressionNode *); - QVector exceptions; - - QSet usedSubscriptionIds; - QSet subscriptionSet; - QHash subscriptionIds; - QVector bytecode; - - // Committed binding data - struct { - QList offsets; - QList > dependencies; - - QVector bytecode; - QByteArray data; - QHash subscriptionIds; - QVector exceptions; - - QHash > registeredStrings; - - int count() const { return offsets.count(); } - } committed; - - QByteArray buildSignalTable() const; - QByteArray buildExceptionData() const; -}; - -void QDeclarativeCompiledBindingsPrivate::unsubscribe(int subIndex) -{ - QDeclarativeCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex); - sub->disconnect(); -} - -void QDeclarativeCompiledBindingsPrivate::subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex) -{ - Q_Q(QDeclarativeCompiledBindings); - - unsubscribe(subIndex); - - if (p->idValues[idIndex]) { - QDeclarativeCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex); - sub->target = q; - sub->targetMethod = methodCount + subIndex; - sub->connect(&p->idValues[idIndex].bindings); - } -} - -void QDeclarativeCompiledBindingsPrivate::subscribe(QObject *o, int notifyIndex, int subIndex) -{ - Q_Q(QDeclarativeCompiledBindings); - - QDeclarativeCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex); - sub->target = q; - sub->targetMethod = methodCount + subIndex; - if (o) - sub->connect(o, notifyIndex); - else - sub->disconnect(); -} - -// Conversion functions - these MUST match the QtScript expression path -inline static qreal toReal(Register *reg, int type, bool *ok = 0) -{ - if (ok) *ok = true; - - if (type == QMetaType::QReal) { - return reg->getqreal(); - } else if (type == qMetaTypeId()) { - return reg->getvariantptr()->toReal(); - } else { - if (ok) *ok = false; - return 0; - } -} - -inline static QString toString(Register *reg, int type, bool *ok = 0) -{ - if (ok) *ok = true; - - if (type == QMetaType::QReal) { - return QString::number(reg->getqreal()); - } else if (type == QMetaType::Int) { - return QString::number(reg->getint()); - } else if (type == qMetaTypeId()) { - return reg->getvariantptr()->toString(); - } else if (type == QMetaType::QString) { - return *reg->getstringptr(); - } else { - if (ok) *ok = false; - return QString(); - } -} - -inline static bool toBool(Register *reg, int type, bool *ok = 0) -{ - if (ok) *ok = true; - - if (type == QMetaType::Bool) { - return reg->getbool(); - } else if (type == qMetaTypeId()) { - return reg->getvariantptr()->toBool(); - } else { - if (ok) *ok = false; - return false; - } -} - -inline static QUrl toUrl(Register *reg, int type, QDeclarativeContextData *context, bool *ok = 0) -{ - if (ok) *ok = true; - - QUrl base; - if (type == qMetaTypeId()) { - QVariant *var = reg->getvariantptr(); - int vt = var->type(); - if (vt == QVariant::Url) { - base = var->toUrl(); - } else if (vt == QVariant::ByteArray) { - base = QUrl(QString::fromUtf8(var->toByteArray())); - } else if (vt == QVariant::String) { - base = QUrl(var->toString()); - } else { - if (ok) *ok = false; - return QUrl(); - } - } else if (type == QMetaType::QString) { - base = QUrl(*reg->getstringptr()); - } else { - if (ok) *ok = false; - return QUrl(); - } - - if (!base.isEmpty() && base.isRelative()) - return context->url.resolved(base); - else - return base; -} - -static QObject *variantToQObject(const QVariant &value, bool *ok) -{ - if (ok) *ok = true; - - if (value.userType() == QMetaType::QObjectStar) { - return qvariant_cast(value); - } else { - if (ok) *ok = false; - return 0; - } -} - -bool QDeclarativeCompiledBindingsPrivate::findproperty(QObject *obj, Register *output, - QDeclarativeEnginePrivate *enginePriv, - int subIdx, const QScriptDeclarativeClass::Identifier &name, - bool isTerminal) -{ - if (!obj) { - output->setUndefined(); - return false; - } - - QDeclarativePropertyCache::Data local; - QDeclarativePropertyCache::Data *property = - QDeclarativePropertyCache::property(QDeclarativeEnginePrivate::get(enginePriv), obj, name, local); - - if (property) { - if (subIdx != -1) - subscribe(obj, property->notifyIndex, subIdx); - - if (property->flags & QDeclarativePropertyCache::Data::IsQObjectDerived) { - void *args[] = { output->typeDataPtr(), 0 }; - QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args); - output->settype(QMetaType::QObjectStar); - } else if (property->propType == qMetaTypeId()) { - QVariant v; - void *args[] = { &v, 0 }; - QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args); - - if (isTerminal) { - new (output->typeDataPtr()) QVariant(v); - output->settype(qMetaTypeId()); - } else { - bool ok; - output->setQObject(variantToQObject(v, &ok)); - if (!ok) - output->setUndefined(); - else - output->settype(QMetaType::QObjectStar); - } - - } else { - if (!isTerminal) { - output->setUndefined(); - } else if (property->propType == QMetaType::QReal) { - void *args[] = { output->typeDataPtr(), 0 }; - QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args); - output->settype(QMetaType::QReal); - } else if (property->propType == QMetaType::Int) { - void *args[] = { output->typeDataPtr(), 0 }; - QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args); - output->settype(QMetaType::Int); - } else if (property->propType == QMetaType::Bool) { - void *args[] = { output->typeDataPtr(), 0 }; - QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args); - output->settype(QMetaType::Bool); - } else if (property->propType == QMetaType::QString) { - new (output->typeDataPtr()) QString(); - void *args[] = { output->typeDataPtr(), 0 }; - QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args); - output->settype(QMetaType::QString); - } else { - new (output->typeDataPtr()) - QVariant(obj->metaObject()->property(property->coreIndex).read(obj)); - output->settype(qMetaTypeId()); - } - } - - return true; - } else { - output->setUndefined(); - return false; - } -} - -void QDeclarativeCompiledBindingsPrivate::findgeneric(Register *output, - int subIdx, - QDeclarativeContextData *context, - const QScriptDeclarativeClass::Identifier &name, - bool isTerminal) -{ - QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(context->engine); - - while (context) { - - int contextPropertyIndex = context->propertyNames?context->propertyNames->value(name):-1; - - - if (contextPropertyIndex != -1) { - - if (contextPropertyIndex < context->idValueCount) { - output->setQObject(context->idValues[contextPropertyIndex]); - output->settype(QMetaType::QObjectStar); - - if (subIdx != -1) - subscribeId(context, contextPropertyIndex, subIdx); - - } else { - QDeclarativeContextPrivate *cp = context->asQDeclarativeContextPrivate(); - const QVariant &value = cp->propertyValues.at(contextPropertyIndex); - - if (isTerminal) { - new (output->typeDataPtr()) QVariant(value); - output->settype(qMetaTypeId()); - } else { - bool ok; - output->setQObject(variantToQObject(value, &ok)); - if (!ok) { output->setUndefined(); } - else { output->settype(QMetaType::QObjectStar); } - return; - } - - if (subIdx != -1) - subscribe(context->asQDeclarativeContext(), contextPropertyIndex + cp->notifyIndex, subIdx); - - - } - - return; - } - - if (QObject *root = context->contextObject) { - - if (findproperty(root, output, enginePriv, subIdx, name, isTerminal)) - return; - - } - - context = context->parent; - } - - output->setUndefined(); -} - -void QDeclarativeCompiledBindingsPrivate::init() -{ - Program *program = (Program *)programData; - if (program->subscriptions) - subscriptions = new QDeclarativeCompiledBindingsPrivate::Subscription[program->subscriptions]; - if (program->identifiers) - identifiers = new QScriptDeclarativeClass::PersistentIdentifier[program->identifiers]; - - m_signalTable = (quint32 *)(program->data() + program->signalTableOffset); - m_bindings = new QDeclarativeCompiledBindingsPrivate::Binding[program->bindings]; -} - -static void throwException(int id, QDeclarativeDelayedError *error, - Program *program, QDeclarativeContextData *context, - const QString &description = QString()) -{ - error->error.setUrl(context->url); - if (description.isEmpty()) - error->error.setDescription(QLatin1String("TypeError: Result of expression is not an object")); - else - error->error.setDescription(description); - if (id != 0xFF) { - quint64 e = *((quint64 *)(program->data() + program->exceptionDataOffset) + id); - error->error.setLine((e >> 32) & 0xFFFFFFFF); - error->error.setColumn(e & 0xFFFFFFFF); - } else { - error->error.setLine(-1); - error->error.setColumn(-1); - } - if (!context->engine || !error->addError(QDeclarativeEnginePrivate::get(context->engine))) - QDeclarativeEnginePrivate::warning(context->engine, error->error); -} - -static void dumpInstruction(const Instr *instr) -{ - switch (instr->common.type) { - case Instr::Noop: - qWarning().nospace() << "\t" << "Noop"; - break; - case Instr::BindingId: - qWarning().nospace() << instr->id.line << ":" << instr->id.column << ":"; - break; - case Instr::Subscribe: - qWarning().nospace() << "\t" << "Subscribe" << "\t\t" << instr->subscribe.offset << "\t" << instr->subscribe.reg << "\t" << instr->subscribe.index; - break; - case Instr::SubscribeId: - qWarning().nospace() << "\t" << "SubscribeId" << "\t\t" << instr->subscribe.offset << "\t" << instr->subscribe.reg << "\t" << instr->subscribe.index; - break; - case Instr::FetchAndSubscribe: - qWarning().nospace() << "\t" << "FetchAndSubscribe" << "\t" << instr->fetchAndSubscribe.output << "\t" << instr->fetchAndSubscribe.objectReg << "\t" << instr->fetchAndSubscribe.subscription; - break; - case Instr::LoadId: - qWarning().nospace() << "\t" << "LoadId" << "\t\t\t" << instr->load.index << "\t" << instr->load.reg; - break; - case Instr::LoadScope: - qWarning().nospace() << "\t" << "LoadScope" << "\t\t" << instr->load.index << "\t" << instr->load.reg; - break; - case Instr::LoadRoot: - qWarning().nospace() << "\t" << "LoadRoot" << "\t\t" << instr->load.index << "\t" << instr->load.reg; - break; - case Instr::LoadAttached: - qWarning().nospace() << "\t" << "LoadAttached" << "\t\t" << instr->attached.output << "\t" << instr->attached.reg << "\t" << instr->attached.id; - break; - case Instr::ConvertIntToReal: - qWarning().nospace() << "\t" << "ConvertIntToReal" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; - break; - case Instr::ConvertRealToInt: - qWarning().nospace() << "\t" << "ConvertRealToInt" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; - break; - case Instr::Real: - qWarning().nospace() << "\t" << "Real" << "\t\t\t" << instr->real_value.reg << "\t" << instr->real_value.value; - break; - case Instr::Int: - qWarning().nospace() << "\t" << "Int" << "\t\t\t" << instr->int_value.reg << "\t" << instr->int_value.value; - break; - case Instr::Bool: - qWarning().nospace() << "\t" << "Bool" << "\t\t\t" << instr->bool_value.reg << "\t" << instr->bool_value.value; - break; - case Instr::String: - qWarning().nospace() << "\t" << "String" << "\t\t\t" << instr->string_value.reg << "\t" << instr->string_value.offset << "\t" << instr->string_value.length; - break; - case Instr::AddReal: - qWarning().nospace() << "\t" << "AddReal" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; - break; - case Instr::AddInt: - qWarning().nospace() << "\t" << "AddInt" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; - break; - case Instr::AddString: - qWarning().nospace() << "\t" << "AddString" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; - break; - case Instr::MinusReal: - qWarning().nospace() << "\t" << "MinusReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; - break; - case Instr::MinusInt: - qWarning().nospace() << "\t" << "MinusInt" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; - break; - case Instr::CompareReal: - qWarning().nospace() << "\t" << "CompareReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; - break; - case Instr::CompareString: - qWarning().nospace() << "\t" << "CompareString" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; - break; - case Instr::NotCompareReal: - qWarning().nospace() << "\t" << "NotCompareReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; - break; - case Instr::NotCompareString: - qWarning().nospace() << "\t" << "NotCompareString" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; - break; - case Instr::GreaterThanReal: - qWarning().nospace() << "\t" << "GreaterThanReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; - break; - case Instr::MaxReal: - qWarning().nospace() << "\t" << "MaxReal" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; - break; - case Instr::MinReal: - qWarning().nospace() << "\t" << "MinReal" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; - break; - case Instr::NewString: - qWarning().nospace() << "\t" << "NewString" << "\t\t" << instr->construct.reg; - break; - case Instr::NewUrl: - qWarning().nospace() << "\t" << "NewUrl" << "\t\t\t" << instr->construct.reg; - break; - case Instr::CleanupString: - qWarning().nospace() << "\t" << "CleanupString" << "\t\t" << instr->cleanup.reg; - break; - case Instr::CleanupUrl: - qWarning().nospace() << "\t" << "CleanupUrl" << "\t\t" << instr->cleanup.reg; - break; - case Instr::Fetch: - qWarning().nospace() << "\t" << "Fetch" << "\t\t\t" << instr->fetch.output << "\t" << instr->fetch.index << "\t" << instr->fetch.objectReg; - break; - case Instr::Store: - qWarning().nospace() << "\t" << "Store" << "\t\t\t" << instr->store.output << "\t" << instr->store.index << "\t" << instr->store.reg; - break; - case Instr::Copy: - qWarning().nospace() << "\t" << "Copy" << "\t\t\t" << instr->copy.reg << "\t" << instr->copy.src; - break; - case Instr::Skip: - qWarning().nospace() << "\t" << "Skip" << "\t\t\t" << instr->skip.reg << "\t" << instr->skip.count; - break; - case Instr::Done: - qWarning().nospace() << "\t" << "Done"; - break; - case Instr::InitString: - qWarning().nospace() << "\t" << "InitString" << "\t\t" << instr->initstring.offset << "\t" << instr->initstring.dataIdx; - break; - case Instr::FindGeneric: - qWarning().nospace() << "\t" << "FindGeneric" << "\t\t" << instr->find.reg << "\t" << instr->find.name; - break; - case Instr::FindGenericTerminal: - qWarning().nospace() << "\t" << "FindGenericTerminal" << "\t" << instr->find.reg << "\t" << instr->find.name; - break; - case Instr::FindProperty: - qWarning().nospace() << "\t" << "FindProperty" << "\t\t" << instr->find.reg << "\t" << instr->find.src << "\t" << instr->find.name; - break; - case Instr::FindPropertyTerminal: - qWarning().nospace() << "\t" << "FindPropertyTerminal" << "\t" << instr->find.reg << "\t" << instr->find.src << "\t" << instr->find.name; - break; - case Instr::CleanupGeneric: - qWarning().nospace() << "\t" << "CleanupGeneric" << "\t\t" << instr->cleanup.reg; - break; - case Instr::ConvertGenericToReal: - qWarning().nospace() << "\t" << "ConvertGenericToReal" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; - break; - case Instr::ConvertGenericToBool: - qWarning().nospace() << "\t" << "ConvertGenericToBool" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; - break; - case Instr::ConvertGenericToString: - qWarning().nospace() << "\t" << "ConvertGenericToString" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; - break; - case Instr::ConvertGenericToUrl: - qWarning().nospace() << "\t" << "ConvertGenericToUrl" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; - break; - default: - qWarning().nospace() << "\t" << "Unknown"; - break; - } -} - -void QDeclarativeCompiledBindingsPrivate::run(int instrIndex, - QDeclarativeContextData *context, QDeclarativeDelayedError *error, - QObject *scope, QObject *output, QDeclarativePropertyPrivate::WriteFlags storeFlags) -{ - Q_Q(QDeclarativeCompiledBindings); - - error->removeError(); - - Register registers[32]; - - QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(context->engine); - Program *program = (Program *)programData; - const Instr *instr = program->instructions(); - instr += instrIndex; - const char *data = program->data(); - -#ifdef QML_THREADED_INTERPRETER - static void *decode_instr[] = { - FOR_EACH_QML_INSTR(QML_INSTR_ADDR) - }; - - if (!program->compiled) { - program->compiled = true; - const Instr *inop = program->instructions(); - for (int i = 0; i < program->instructionCount; ++i) { - Instr *op = (Instr *) inop++; - op->common.code = decode_instr[op->common.type]; - } - } - - goto *instr->common.code; -#else - // return; - -#ifdef COMPILEDBINDINGS_DEBUG - qWarning().nospace() << "Begin binding run"; -#endif - - while (instr) { - switch (instr->common.type) { - -#ifdef COMPILEDBINDINGS_DEBUG - dumpInstruction(instr); -#endif - -#endif - - QML_BEGIN_INSTR(Noop) - QML_END_INSTR(Noop) - - QML_BEGIN_INSTR(BindingId) - QML_END_INSTR(BindingId) - - QML_BEGIN_INSTR(SubscribeId) - subscribeId(context, instr->subscribe.index, instr->subscribe.offset); - QML_END_INSTR(SubscribeId) - - QML_BEGIN_INSTR(Subscribe) - { - QObject *o = 0; - const Register &object = registers[instr->subscribe.reg]; - if (!object.isUndefined()) o = object.getQObject(); - subscribe(o, instr->subscribe.index, instr->subscribe.offset); - } - QML_END_INSTR(Subscribe) - - QML_BEGIN_INSTR(FetchAndSubscribe) - { - const Register &input = registers[instr->fetchAndSubscribe.objectReg]; - Register &output = registers[instr->fetchAndSubscribe.output]; - - if (input.isUndefined()) { - throwException(instr->fetchAndSubscribe.exceptionId, error, program, context); - return; - } - - QObject *object = input.getQObject(); - if (!object) { - output.setUndefined(); - } else { - int subIdx = instr->fetchAndSubscribe.subscription; - QDeclarativeCompiledBindingsPrivate::Subscription *sub = 0; - if (subIdx != -1) { - sub = (subscriptions + subIdx); - sub->target = q; - sub->targetMethod = methodCount + subIdx; - } - fastProperties()->accessor(instr->fetchAndSubscribe.function)(object, output.typeDataPtr(), sub); - } - } - QML_END_INSTR(FetchAndSubscribe) - - QML_BEGIN_INSTR(LoadId) - registers[instr->load.reg].setQObject(context->idValues[instr->load.index].data()); - QML_END_INSTR(LoadId) - - QML_BEGIN_INSTR(LoadScope) - registers[instr->load.reg].setQObject(scope); - QML_END_INSTR(LoadScope) - - QML_BEGIN_INSTR(LoadRoot) - registers[instr->load.reg].setQObject(context->contextObject); - QML_END_INSTR(LoadRoot) - - QML_BEGIN_INSTR(LoadAttached) - { - const Register &input = registers[instr->attached.reg]; - Register &output = registers[instr->attached.output]; - if (input.isUndefined()) { - throwException(instr->attached.exceptionId, error, program, context); - return; - } - - QObject *object = registers[instr->attached.reg].getQObject(); - if (!object) { - output.setUndefined(); - } else { - QObject *attached = - qmlAttachedPropertiesObjectById(instr->attached.id, - registers[instr->attached.reg].getQObject(), - true); - Q_ASSERT(attached); - output.setQObject(attached); - } - } - QML_END_INSTR(LoadAttached) - - QML_BEGIN_INSTR(ConvertIntToReal) - { - const Register &input = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - if (input.isUndefined()) output.setUndefined(); - else output.setqreal(qreal(input.getint())); - } - QML_END_INSTR(ConvertIntToReal) - - QML_BEGIN_INSTR(ConvertRealToInt) - { - const Register &input = registers[instr->unaryop.src]; - Register &output = registers[instr->unaryop.output]; - if (input.isUndefined()) output.setUndefined(); - else output.setint(qRound(input.getqreal())); - } - QML_END_INSTR(ConvertRealToInt) - - QML_BEGIN_INSTR(Real) - registers[instr->real_value.reg].setqreal(instr->real_value.value); - QML_END_INSTR(Real) - - QML_BEGIN_INSTR(Int) - registers[instr->int_value.reg].setint(instr->int_value.value); - QML_END_INSTR(Int) - - QML_BEGIN_INSTR(Bool) - registers[instr->bool_value.reg].setbool(instr->bool_value.value); - QML_END_INSTR(Bool) - - QML_BEGIN_INSTR(String) - { - Register &output = registers[instr->string_value.reg]; - new (output.getstringptr()) - QString((QChar *)(data + instr->string_value.offset), instr->string_value.length); - output.settype(QMetaType::QString); - } - QML_END_INSTR(String) - - QML_BEGIN_INSTR(AddReal) - { - const Register &lhs = registers[instr->binaryop.src1]; - const Register &rhs = registers[instr->binaryop.src2]; - Register &output = registers[instr->binaryop.output]; - if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN(); - else output.setqreal(lhs.getqreal() + rhs.getqreal()); - } - QML_END_INSTR(AddReal) - - QML_BEGIN_INSTR(AddInt) - { - const Register &lhs = registers[instr->binaryop.src1]; - const Register &rhs = registers[instr->binaryop.src2]; - Register &output = registers[instr->binaryop.output]; - if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN(); - else output.setint(lhs.getint() + rhs.getint()); - } - QML_END_INSTR(AddInt) - - QML_BEGIN_INSTR(AddString) - { - const Register &lhs = registers[instr->binaryop.src1]; - const Register &rhs = registers[instr->binaryop.src2]; - Register &output = registers[instr->binaryop.output]; - if (lhs.isUndefined() && rhs.isUndefined()) { output.setNaN(); } - else { - if (lhs.isUndefined()) - new (output.getstringptr()) - QString(QLatin1String("undefined") + *registers[instr->binaryop.src2].getstringptr()); - else if (rhs.isUndefined()) - new (output.getstringptr()) - QString(*registers[instr->binaryop.src1].getstringptr() + QLatin1String("undefined")); - else - new (output.getstringptr()) - QString(*registers[instr->binaryop.src1].getstringptr() + - *registers[instr->binaryop.src2].getstringptr()); - output.settype(QMetaType::QString); - } - } - QML_END_INSTR(AddString) - - QML_BEGIN_INSTR(MinusReal) - { - const Register &lhs = registers[instr->binaryop.src1]; - const Register &rhs = registers[instr->binaryop.src2]; - Register &output = registers[instr->binaryop.output]; - if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN(); - else output.setqreal(lhs.getqreal() - rhs.getqreal()); - } - QML_END_INSTR(MinusReal) - - QML_BEGIN_INSTR(MinusInt) - { - const Register &lhs = registers[instr->binaryop.src1]; - const Register &rhs = registers[instr->binaryop.src2]; - Register &output = registers[instr->binaryop.output]; - if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN(); - else output.setint(lhs.getint() - rhs.getint()); - } - QML_END_INSTR(MinusInt) - - QML_BEGIN_INSTR(CompareReal) - { - const Register &lhs = registers[instr->binaryop.src1]; - const Register &rhs = registers[instr->binaryop.src2]; - Register &output = registers[instr->binaryop.output]; - if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(lhs.isUndefined() == rhs.isUndefined()); - else output.setbool(lhs.getqreal() == rhs.getqreal()); - } - QML_END_INSTR(CompareReal) - - QML_BEGIN_INSTR(CompareString) - { - const Register &lhs = registers[instr->binaryop.src1]; - const Register &rhs = registers[instr->binaryop.src2]; - Register &output = registers[instr->binaryop.output]; - if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(lhs.isUndefined() == rhs.isUndefined()); - else output.setbool(*lhs.getstringptr() == *rhs.getstringptr()); - } - QML_END_INSTR(CompareString) - - QML_BEGIN_INSTR(NotCompareReal) - { - const Register &lhs = registers[instr->binaryop.src1]; - const Register &rhs = registers[instr->binaryop.src2]; - Register &output = registers[instr->binaryop.output]; - if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(lhs.isUndefined() != rhs.isUndefined()); - else output.setbool(lhs.getqreal() != rhs.getqreal()); - } - QML_END_INSTR(NotCompareReal) - - QML_BEGIN_INSTR(NotCompareString) - { - const Register &lhs = registers[instr->binaryop.src1]; - const Register &rhs = registers[instr->binaryop.src2]; - Register &output = registers[instr->binaryop.output]; - if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(lhs.isUndefined() != rhs.isUndefined()); - else output.setbool(*lhs.getstringptr() != *rhs.getstringptr()); - } - QML_END_INSTR(NotCompareString) - - QML_BEGIN_INSTR(GreaterThanReal) - { - const Register &lhs = registers[instr->binaryop.src1]; - const Register &rhs = registers[instr->binaryop.src2]; - Register &output = registers[instr->binaryop.output]; - if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(false); - else output.setbool(lhs.getqreal() > rhs.getqreal()); - } - QML_END_INSTR(GreaterThanReal) - - QML_BEGIN_INSTR(MaxReal) - { - const Register &lhs = registers[instr->binaryop.src1]; - const Register &rhs = registers[instr->binaryop.src2]; - Register &output = registers[instr->binaryop.output]; - if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN(); - else output.setqreal(qMax(lhs.getqreal(), rhs.getqreal())); - } - QML_END_INSTR(MaxReal) - - QML_BEGIN_INSTR(MinReal) - { - const Register &lhs = registers[instr->binaryop.src1]; - const Register &rhs = registers[instr->binaryop.src2]; - Register &output = registers[instr->binaryop.output]; - if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN(); - else output.setqreal(qMin(lhs.getqreal(), rhs.getqreal())); - } - QML_END_INSTR(MinReal) - - QML_BEGIN_INSTR(NewString) - { - Register &output = registers[instr->construct.reg]; - new (output.getstringptr()) QString; - output.settype(QMetaType::QString); - } - QML_END_INSTR(NewString) - - QML_BEGIN_INSTR(NewUrl) - { - Register &output = registers[instr->construct.reg]; - new (output.geturlptr()) QUrl; - output.settype(QMetaType::QUrl); - } - QML_END_INSTR(NewUrl) - - QML_BEGIN_INSTR(CleanupString) - registers[instr->cleanup.reg].getstringptr()->~QString(); -#ifdef REGISTER_CLEANUP_DEBUG - registers[instr->cleanup.reg].setUndefined(); -#endif - QML_END_INSTR(CleanupString) - - QML_BEGIN_INSTR(CleanupUrl) - registers[instr->cleanup.reg].geturlptr()->~QUrl(); -#ifdef REGISTER_CLEANUP_DEBUG - registers[instr->cleanup.reg].setUndefined(); -#endif - QML_END_INSTR(CleanupUrl) - - QML_BEGIN_INSTR(Fetch) - { - const Register &input = registers[instr->fetch.objectReg]; - Register &output = registers[instr->fetch.output]; - - if (input.isUndefined()) { - throwException(instr->fetch.exceptionId, error, program, context); - return; - } - - QObject *object = input.getQObject(); - if (!object) { - output.setUndefined(); - } else { - void *argv[] = { output.typeDataPtr(), 0 }; - QMetaObject::metacall(object, QMetaObject::ReadProperty, instr->fetch.index, argv); - } - } - QML_END_INSTR(Fetch) - - QML_BEGIN_INSTR(Store) - { - Register &data = registers[instr->store.reg]; - if (data.isUndefined()) { - throwException(instr->store.exceptionId, error, program, context, - QLatin1String("Unable to assign undefined value")); - return; - } - - int status = -1; - void *argv[] = { data.typeDataPtr(), 0, &status, &storeFlags }; - QMetaObject::metacall(output, QMetaObject::WriteProperty, - instr->store.index, argv); - } - QML_END_INSTR(Store) - - QML_BEGIN_INSTR(Copy) - registers[instr->copy.reg] = registers[instr->copy.src]; - QML_END_INSTR(Copy) - - QML_BEGIN_INSTR(Skip) - if (instr->skip.reg == -1 || !registers[instr->skip.reg].getbool()) - instr += instr->skip.count; - QML_END_INSTR(Skip) - - QML_BEGIN_INSTR(Done) - return; - QML_END_INSTR(Done) - - QML_BEGIN_INSTR(InitString) - if (!identifiers[instr->initstring.offset].identifier) { - quint32 len = *(quint32 *)(data + instr->initstring.dataIdx); - QChar *strdata = (QChar *)(data + instr->initstring.dataIdx + sizeof(quint32)); - - QString str = QString::fromRawData(strdata, len); - - identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str); - } - QML_END_INSTR(InitString) - - QML_BEGIN_INSTR(FindGenericTerminal) - // We start the search in the parent context, as we know that the - // name is not present in the current context or it would have been - // found during the static compile - findgeneric(registers + instr->find.reg, instr->find.subscribeIndex, - context->parent, - identifiers[instr->find.name].identifier, - instr->common.type == Instr::FindGenericTerminal); - QML_END_INSTR(FindGenericTerminal) - - QML_BEGIN_INSTR(FindGeneric) - // We start the search in the parent context, as we know that the - // name is not present in the current context or it would have been - // found during the static compile - findgeneric(registers + instr->find.reg, instr->find.subscribeIndex, - context->parent, - identifiers[instr->find.name].identifier, - instr->common.type == Instr::FindGenericTerminal); - QML_END_INSTR(FindGeneric) - - QML_BEGIN_INSTR(FindPropertyTerminal) - { - const Register &object = registers[instr->find.src]; - if (object.isUndefined()) { - throwException(instr->find.exceptionId, error, program, context); - return; - } - - findproperty(object.getQObject(), registers + instr->find.reg, - QDeclarativeEnginePrivate::get(context->engine), - instr->find.subscribeIndex, identifiers[instr->find.name].identifier, - instr->common.type == Instr::FindPropertyTerminal); - } - QML_END_INSTR(FindPropertyTerminal) - - QML_BEGIN_INSTR(FindProperty) - { - const Register &object = registers[instr->find.src]; - if (object.isUndefined()) { - throwException(instr->find.exceptionId, error, program, context); - return; - } - - findproperty(object.getQObject(), registers + instr->find.reg, - QDeclarativeEnginePrivate::get(context->engine), - instr->find.subscribeIndex, identifiers[instr->find.name].identifier, - instr->common.type == Instr::FindPropertyTerminal); - } - QML_END_INSTR(FindProperty) - - QML_BEGIN_INSTR(CleanupGeneric) - { - int type = registers[instr->cleanup.reg].gettype(); - if (type == qMetaTypeId()) { - registers[instr->cleanup.reg].getvariantptr()->~QVariant(); -#ifdef REGISTER_CLEANUP_DEBUG - registers[instr->cleanup.reg].setUndefined(); -#endif - } else if (type == QMetaType::QString) { - registers[instr->cleanup.reg].getstringptr()->~QString(); -#ifdef REGISTER_CLEANUP_DEBUG - registers[instr->cleanup.reg].setUndefined(); -#endif - } else if (type == QMetaType::QUrl) { - registers[instr->cleanup.reg].geturlptr()->~QUrl(); -#ifdef REGISTER_CLEANUP_DEBUG - registers[instr->cleanup.reg].setUndefined(); -#endif - } - } - QML_END_INSTR(CleanupGeneric) - - QML_BEGIN_INSTR(ConvertGenericToReal) - { - Register &output = registers[instr->unaryop.output]; - Register &input = registers[instr->unaryop.src]; - bool ok = true; - output.setqreal(toReal(&input, input.gettype(), &ok)); - if (!ok) output.setUndefined(); - } - QML_END_INSTR(ConvertGenericToReal) - - QML_BEGIN_INSTR(ConvertGenericToBool) - { - Register &output = registers[instr->unaryop.output]; - Register &input = registers[instr->unaryop.src]; - bool ok = true; - output.setbool(toBool(&input, input.gettype(), &ok)); - if (!ok) output.setUndefined(); - } - QML_END_INSTR(ConvertGenericToBool) - - QML_BEGIN_INSTR(ConvertGenericToString) - { - Register &output = registers[instr->unaryop.output]; - Register &input = registers[instr->unaryop.src]; - bool ok = true; - QString str = toString(&input, input.gettype(), &ok); - if (ok) { new (output.getstringptr()) QString(str); output.settype(QMetaType::QString); } - else { output.setUndefined(); } - } - QML_END_INSTR(ConvertGenericToString) - - QML_BEGIN_INSTR(ConvertGenericToUrl) - { - Register &output = registers[instr->unaryop.output]; - Register &input = registers[instr->unaryop.src]; - bool ok = true; - QUrl url = toUrl(&input, input.gettype(), context, &ok); - if (ok) { new (output.geturlptr()) QUrl(url); output.settype(QMetaType::QUrl); } - else { output.setUndefined(); } - } - QML_END_INSTR(ConvertGenericToUrl) - -#ifdef QML_THREADED_INTERPRETER - // nothing to do -#else - default: - qFatal("EEK"); - break; - } // switch - - ++instr; - } // while -#endif -} - -void QDeclarativeBindingCompiler::dump(const QByteArray &programData) -{ - const Program *program = (const Program *)programData.constData(); - - qWarning() << "Program.bindings:" << program->bindings; - qWarning() << "Program.dataLength:" << program->dataLength; - qWarning() << "Program.subscriptions:" << program->subscriptions; - qWarning() << "Program.indentifiers:" << program->identifiers; - - int count = program->instructionCount; - const Instr *instr = program->instructions(); - - while (count--) { - - dumpInstruction(instr); - ++instr; - } -} - -/*! -Clear the state associated with attempting to compile a specific binding. -This does not clear the global "committed binding" states. -*/ -void QDeclarativeBindingCompilerPrivate::resetInstanceState() -{ - registers = 0; - registerCleanups.clear(); - data = committed.data; - exceptions = committed.exceptions; - usedSubscriptionIds.clear(); - subscriptionSet.clear(); - subscriptionIds = committed.subscriptionIds; - registeredStrings = committed.registeredStrings; - bytecode.clear(); -} - -/*! -Mark the last compile as successful, and add it to the "committed data" -section. - -Returns the index for the committed binding. -*/ -int QDeclarativeBindingCompilerPrivate::commitCompile() -{ - int rv = committed.count(); - committed.offsets << committed.bytecode.count(); - committed.dependencies << usedSubscriptionIds; - committed.bytecode << bytecode; - committed.data = data; - committed.exceptions = exceptions; - committed.subscriptionIds = subscriptionIds; - committed.registeredStrings = registeredStrings; - return rv; -} - -bool QDeclarativeBindingCompilerPrivate::compile(QDeclarativeJS::AST::Node *node) -{ - resetInstanceState(); - - if (destination->type == -1) - return false; - - if (bindingsDump()) { - QDeclarativeJS::AST::ExpressionNode *n = node->expressionCast(); - if (n) { - Instr id; - id.common.type = Instr::BindingId; - id.id.column = n->firstSourceLocation().startColumn; - id.id.line = n->firstSourceLocation().startLine; - bytecode << id; - } - } - - Result type; - - if (!parseExpression(node, type)) - return false; - - if (subscriptionSet.count() > 0xFFFF || - registeredStrings.count() > 0xFFFF) - return false; - - if (type.unknownType) { - if (!qmlExperimental()) - return false; - - if (destination->type != QMetaType::QReal && - destination->type != QVariant::String && - destination->type != QMetaType::Bool && - destination->type != QVariant::Url) - return false; - - int convertReg = acquireReg(); - if (convertReg == -1) - return false; - - if (destination->type == QMetaType::QReal) { - Instr convert; - convert.common.type = Instr::ConvertGenericToReal; - convert.unaryop.output = convertReg; - convert.unaryop.src = type.reg; - bytecode << convert; - } else if (destination->type == QVariant::String) { - Instr convert; - convert.common.type = Instr::ConvertGenericToString; - convert.unaryop.output = convertReg; - convert.unaryop.src = type.reg; - bytecode << convert; - } else if (destination->type == QMetaType::Bool) { - Instr convert; - convert.common.type = Instr::ConvertGenericToBool; - convert.unaryop.output = convertReg; - convert.unaryop.src = type.reg; - bytecode << convert; - } else if (destination->type == QVariant::Url) { - Instr convert; - convert.common.type = Instr::ConvertGenericToUrl; - convert.unaryop.output = convertReg; - convert.unaryop.src = type.reg; - bytecode << convert; - } - - Instr cleanup; - cleanup.common.type = Instr::CleanupGeneric; - cleanup.cleanup.reg = type.reg; - bytecode << cleanup; - - Instr instr; - instr.common.type = Instr::Store; - instr.store.output = 0; - instr.store.index = destination->index; - instr.store.reg = convertReg; - instr.store.exceptionId = exceptionId(node->expressionCast()); - bytecode << instr; - - if (destination->type == QVariant::String) { - Instr cleanup; - cleanup.common.type = Instr::CleanupString; - cleanup.cleanup.reg = convertReg; - bytecode << cleanup; - } else if (destination->type == QVariant::Url) { - Instr cleanup; - cleanup.common.type = Instr::CleanupUrl; - cleanup.cleanup.reg = convertReg; - bytecode << cleanup; - } - - releaseReg(convertReg); - - Instr done; - done.common.type = Instr::Done; - bytecode << done; - - } else { - // Can we store the final value? - if (type.type == QVariant::Int && - destination->type == QMetaType::QReal) { - Instr instr; - instr.common.type = Instr::ConvertIntToReal; - instr.unaryop.output = type.reg; - instr.unaryop.src = type.reg; - bytecode << instr; - type.type = QMetaType::QReal; - } else if (type.type == QMetaType::QReal && - destination->type == QVariant::Int) { - Instr instr; - instr.common.type = Instr::ConvertRealToInt; - instr.unaryop.output = type.reg; - instr.unaryop.src = type.reg; - bytecode << instr; - type.type = QVariant::Int; - } else if (type.type == destination->type) { - } else { - const QMetaObject *from = type.metaObject; - const QMetaObject *to = engine->rawMetaObjectForType(destination->type); - - if (QDeclarativePropertyPrivate::canConvert(from, to)) - type.type = destination->type; - } - - if (type.type == destination->type) { - Instr instr; - instr.common.type = Instr::Store; - instr.store.output = 0; - instr.store.index = destination->index; - instr.store.reg = type.reg; - instr.store.exceptionId = exceptionId(node->expressionCast()); - bytecode << instr; - - releaseReg(type.reg); - - Instr done; - done.common.type = Instr::Done; - bytecode << done; - } else { - return false; - } - } - - return true; -} - -bool QDeclarativeBindingCompilerPrivate::parseExpression(QDeclarativeJS::AST::Node *node, Result &type) -{ - while (node->kind == AST::Node::Kind_NestedExpression) - node = static_cast(node)->expression; - - if (tryArith(node)) { - if (!parseArith(node, type)) return false; - } else if (tryLogic(node)) { - if (!parseLogic(node, type)) return false; - } else if (tryConditional(node)) { - if (!parseConditional(node, type)) return false; - } else if (tryName(node)) { - if (!parseName(node, type)) return false; - } else if (tryConstant(node)) { - if (!parseConstant(node, type)) return false; - } else if (tryMethod(node)) { - if (!parseMethod(node, type)) return false; - } else { - return false; - } - return true; -} - -bool QDeclarativeBindingCompilerPrivate::tryName(QDeclarativeJS::AST::Node *node) -{ - return node->kind == AST::Node::Kind_IdentifierExpression || - node->kind == AST::Node::Kind_FieldMemberExpression; -} - -bool QDeclarativeBindingCompilerPrivate::parseName(AST::Node *node, Result &type) -{ - QStringList nameParts; - QList nameNodes; - if (!buildName(nameParts, node, &nameNodes)) - return false; - - int reg = acquireReg(); - if (reg == -1) - return false; - type.reg = reg; - - QDeclarativeParser::Object *absType = 0; - - QStringList subscribeName; - - bool wasAttachedObject = false; - - for (int ii = 0; ii < nameParts.count(); ++ii) { - const QString &name = nameParts.at(ii); - - // We don't handle signal properties or attached properties - if (name.length() > 2 && name.startsWith(QLatin1String("on")) && - name.at(2).isUpper()) - return false; - - QDeclarativeType *attachType = 0; - if (name.at(0).isUpper()) { - // Could be an attached property - if (ii == nameParts.count() - 1) - return false; - if (nameParts.at(ii + 1).at(0).isUpper()) - return false; - - QDeclarativeImportedNamespace *ns = 0; - if (!imports.resolveType(name.toUtf8(), &attachType, 0, 0, 0, &ns)) - return false; - if (ns || !attachType || !attachType->attachedPropertiesType()) - return false; - - wasAttachedObject = true; - } - - if (ii == 0) { - - if (attachType) { - Instr instr; - instr.common.type = Instr::LoadScope; - instr.load.index = 0; - instr.load.reg = reg; - bytecode << instr; - - Instr attach; - attach.common.type = Instr::LoadAttached; - attach.attached.output = reg; - attach.attached.reg = reg; - attach.attached.id = attachType->attachedPropertiesId(); - attach.attached.exceptionId = exceptionId(nameNodes.at(ii)); - bytecode << attach; - - subscribeName << contextName(); - subscribeName << QLatin1String("$$$ATTACH_") + name; - - absType = 0; - type.metaObject = attachType->attachedPropertiesType(); - - continue; - } else if (ids.contains(name)) { - QDeclarativeParser::Object *idObject = ids.value(name); - absType = idObject; - type.metaObject = absType->metaObject(); - - // We check if the id object is the root or - // scope object to avoid a subscription - if (idObject == component) { - Instr instr; - instr.common.type = Instr::LoadRoot; - instr.load.index = 0; - instr.load.reg = reg; - bytecode << instr; - } else if (idObject == context) { - Instr instr; - instr.common.type = Instr::LoadScope; - instr.load.index = 0; - instr.load.reg = reg; - bytecode << instr; - } else { - Instr instr; - instr.common.type = Instr::LoadId; - instr.load.index = idObject->idIndex; - instr.load.reg = reg; - bytecode << instr; - - subscribeName << QLatin1String("$$$ID_") + name; - - if (subscription(subscribeName, &type)) { - Instr sub; - sub.common.type = Instr::SubscribeId; - sub.subscribe.offset = subscriptionIndex(subscribeName); - sub.subscribe.reg = reg; - sub.subscribe.index = instr.load.index; - bytecode << sub; - } - } - - } else { - - QByteArray utf8Name = name.toUtf8(); - const char *cname = utf8Name.constData(); - - int d0Idx = (context == component)?-1:context->metaObject()->indexOfProperty(cname); - int d1Idx = -1; - if (d0Idx == -1) - d1Idx = component->metaObject()->indexOfProperty(cname); - - if (d0Idx != -1) { - Instr instr; - instr.common.type = Instr::LoadScope; - instr.load.index = 0; - instr.load.reg = reg; - bytecode << instr; - - subscribeName << contextName(); - subscribeName << name; - - if (!fetch(type, context->metaObject(), reg, d0Idx, subscribeName, nameNodes.at(ii))) - return false; - } else if(d1Idx != -1) { - Instr instr; - instr.common.type = Instr::LoadRoot; - instr.load.index = 0; - instr.load.reg = reg; - bytecode << instr; - - subscribeName << QLatin1String("$$$ROOT"); - subscribeName << name; - - if (!fetch(type, component->metaObject(), reg, d1Idx, subscribeName, nameNodes.at(ii))) - return false; - } else if (qmlExperimental()) { - Instr find; - if (nameParts.count() == 1) - find.common.type = Instr::FindGenericTerminal; - else - find.common.type = Instr::FindGeneric; - - find.find.reg = reg; - find.find.src = -1; - find.find.name = registerString(name); - find.find.exceptionId = exceptionId(nameNodes.at(ii)); - - subscribeName << QString(QLatin1String("$$$Generic_") + name); - if (subscription(subscribeName, &type)) - find.find.subscribeIndex = subscriptionIndex(subscribeName); - else - find.find.subscribeIndex = -1; - - bytecode << find; - type.unknownType = true; - } - - if (!type.unknownType && type.type == -1) - return false; // Couldn't fetch that type - } - - } else { - - if (attachType) { - Instr attach; - attach.common.type = Instr::LoadAttached; - attach.attached.output = reg; - attach.attached.reg = reg; - attach.attached.id = attachType->attachedPropertiesId(); - bytecode << attach; - - absType = 0; - type.metaObject = attachType->attachedPropertiesType(); - - subscribeName << QLatin1String("$$$ATTACH_") + name; - continue; - } - - const QMetaObject *mo = 0; - if (absType) - mo = absType->metaObject(); - else if (type.metaObject) - mo = type.metaObject; - - QByteArray utf8Name = name.toUtf8(); - const char *cname = utf8Name.constData(); - int idx = mo?mo->indexOfProperty(cname):-1; - if (absType && idx == -1) - return false; - - subscribeName << name; - - if (absType || (wasAttachedObject && idx != -1) || (mo && mo->property(idx).isFinal())) { - absType = 0; - if (!fetch(type, mo, reg, idx, subscribeName, nameNodes.at(ii))) - return false; - } else { - - Instr prop; - if (ii == nameParts.count() -1 ) - prop.common.type = Instr::FindPropertyTerminal; - else - prop.common.type = Instr::FindProperty; - - prop.find.reg = reg; - prop.find.src = reg; - prop.find.name = registerString(name); - prop.find.exceptionId = exceptionId(nameNodes.at(ii)); - - if (subscription(subscribeName, &type)) - prop.find.subscribeIndex = subscriptionIndex(subscribeName); - else - prop.find.subscribeIndex = -1; - - type.unknownType = true; - type.metaObject = 0; - type.type = -1; - type.reg = reg; - bytecode << prop; - } - } - - wasAttachedObject = false; - } - - return true; -} - -bool QDeclarativeBindingCompilerPrivate::tryArith(QDeclarativeJS::AST::Node *node) -{ - if (node->kind != AST::Node::Kind_BinaryExpression) - return false; - - AST::BinaryExpression *expression = static_cast(node); - if (expression->op == QSOperator::Add || - expression->op == QSOperator::Sub) - return true; - else - return false; -} - -bool QDeclarativeBindingCompilerPrivate::parseArith(QDeclarativeJS::AST::Node *node, Result &type) -{ - AST::BinaryExpression *expression = static_cast(node); - - type.reg = acquireReg(); - if (type.reg == -1) - return false; - - Result lhs; - Result rhs; - - if (!parseExpression(expression->left, lhs)) return false; - if (!parseExpression(expression->right, rhs)) return false; - - if ((lhs.type == QVariant::Int || lhs.type == QMetaType::QReal) && - (rhs.type == QVariant::Int || rhs.type == QMetaType::QReal)) - return numberArith(type, lhs, rhs, (QSOperator::Op)expression->op); - else if(expression->op == QSOperator::Sub) - return numberArith(type, lhs, rhs, (QSOperator::Op)expression->op); - else if ((lhs.type == QMetaType::QString || lhs.unknownType) && - (rhs.type == QMetaType::QString || rhs.unknownType) && - (lhs.type == QMetaType::QString || rhs.type == QMetaType::QString)) - return stringArith(type, lhs, rhs, (QSOperator::Op)expression->op); - else - return false; -} - -bool QDeclarativeBindingCompilerPrivate::numberArith(Result &type, const Result &lhs, const Result &rhs, QSOperator::Op op) -{ - bool nativeReal = rhs.type == QMetaType::QReal || - lhs.type == QMetaType::QReal || - lhs.unknownType || - rhs.unknownType; - - if (nativeReal && lhs.type == QMetaType::Int) { - Instr convert; - convert.common.type = Instr::ConvertIntToReal; - convert.unaryop.output = lhs.reg; - convert.unaryop.src = lhs.reg; - bytecode << convert; - } - - if (nativeReal && rhs.type == QMetaType::Int) { - Instr convert; - convert.common.type = Instr::ConvertIntToReal; - convert.unaryop.output = rhs.reg; - convert.unaryop.src = rhs.reg; - bytecode << convert; - } - - int lhsTmp = -1; - int rhsTmp = -1; - - if (lhs.unknownType) { - if (!qmlExperimental()) - return false; - - lhsTmp = acquireReg(); - if (lhsTmp == -1) - return false; - - Instr conv; - conv.common.type = Instr::ConvertGenericToReal; - conv.unaryop.output = lhsTmp; - conv.unaryop.src = lhs.reg; - bytecode << conv; - } - - if (rhs.unknownType) { - if (!qmlExperimental()) - return false; - - rhsTmp = acquireReg(); - if (rhsTmp == -1) - return false; - - Instr conv; - conv.common.type = Instr::ConvertGenericToReal; - conv.unaryop.output = rhsTmp; - conv.unaryop.src = rhs.reg; - bytecode << conv; - } - - Instr arith; - if (op == QSOperator::Add) { - arith.common.type = nativeReal?Instr::AddReal:Instr::AddInt; - } else if (op == QSOperator::Sub) { - arith.common.type = nativeReal?Instr::MinusReal:Instr::MinusInt; - } else { - qFatal("Unsupported arithmetic operator"); - } - - arith.binaryop.output = type.reg; - arith.binaryop.src1 = (lhsTmp == -1)?lhs.reg:lhsTmp; - arith.binaryop.src2 = (rhsTmp == -1)?rhs.reg:rhsTmp; - bytecode << arith; - - type.metaObject = 0; - type.type = nativeReal?QMetaType::QReal:QMetaType::Int; - type.subscriptionSet.unite(lhs.subscriptionSet); - type.subscriptionSet.unite(rhs.subscriptionSet); - - if (lhsTmp != -1) releaseReg(lhsTmp); - if (rhsTmp != -1) releaseReg(rhsTmp); - releaseReg(lhs.reg); - releaseReg(rhs.reg); - - return true; -} - -bool QDeclarativeBindingCompilerPrivate::stringArith(Result &type, const Result &lhs, const Result &rhs, QSOperator::Op op) -{ - if (op != QSOperator::Add) - return false; - - int lhsTmp = -1; - int rhsTmp = -1; - - if (lhs.unknownType) { - if (!qmlExperimental()) - return false; - - lhsTmp = acquireReg(Instr::CleanupString); - if (lhsTmp == -1) - return false; - - Instr convert; - convert.common.type = Instr::ConvertGenericToString; - convert.unaryop.output = lhsTmp; - convert.unaryop.src = lhs.reg; - bytecode << convert; - } - - if (rhs.unknownType) { - if (!qmlExperimental()) - return false; - - rhsTmp = acquireReg(Instr::CleanupString); - if (rhsTmp == -1) - return false; - - Instr convert; - convert.common.type = Instr::ConvertGenericToString; - convert.unaryop.output = rhsTmp; - convert.unaryop.src = rhs.reg; - bytecode << convert; - } - - type.reg = acquireReg(Instr::CleanupString); - if (type.reg == -1) - return false; - - type.type = QMetaType::QString; - - Instr add; - add.common.type = Instr::AddString; - add.binaryop.output = type.reg; - add.binaryop.src1 = (lhsTmp == -1)?lhs.reg:lhsTmp; - add.binaryop.src2 = (rhsTmp == -1)?rhs.reg:rhsTmp; - bytecode << add; - - if (lhsTmp != -1) releaseReg(lhsTmp); - if (rhsTmp != -1) releaseReg(rhsTmp); - releaseReg(lhs.reg); - releaseReg(rhs.reg); - - return true; -} - -bool QDeclarativeBindingCompilerPrivate::tryLogic(QDeclarativeJS::AST::Node *node) -{ - if (node->kind != AST::Node::Kind_BinaryExpression) - return false; - - AST::BinaryExpression *expression = static_cast(node); - if (expression->op == QSOperator::Gt || - expression->op == QSOperator::Equal || - expression->op == QSOperator::NotEqual) - return true; - else - return false; -} - -bool QDeclarativeBindingCompilerPrivate::parseLogic(QDeclarativeJS::AST::Node *node, Result &type) -{ - AST::BinaryExpression *expression = static_cast(node); - - Result lhs; - Result rhs; - - if (!parseExpression(expression->left, lhs)) return false; - if (!parseExpression(expression->right, rhs)) return false; - - type.reg = acquireReg(); - if (type.reg == -1) - return false; - - type.metaObject = 0; - type.type = QVariant::Bool; - - if (lhs.type == QMetaType::QReal && rhs.type == QMetaType::QReal) { - - Instr op; - if (expression->op == QSOperator::Gt) - op.common.type = Instr::GreaterThanReal; - else if (expression->op == QSOperator::Equal) - op.common.type = Instr::CompareReal; - else if (expression->op == QSOperator::NotEqual) - op.common.type = Instr::NotCompareReal; - else - return false; - op.binaryop.output = type.reg; - op.binaryop.src1 = lhs.reg; - op.binaryop.src2 = rhs.reg; - bytecode << op; - - - } else if (lhs.type == QMetaType::QString && rhs.type == QMetaType::QString) { - - Instr op; - if (expression->op == QSOperator::Equal) - op.common.type = Instr::CompareString; - else if (expression->op == QSOperator::NotEqual) - op.common.type = Instr::NotCompareString; - else - return false; - op.binaryop.output = type.reg; - op.binaryop.src1 = lhs.reg; - op.binaryop.src2 = rhs.reg; - bytecode << op; - - } else { - return false; - } - - releaseReg(lhs.reg); - releaseReg(rhs.reg); - - return true; -} - -bool QDeclarativeBindingCompilerPrivate::tryConditional(QDeclarativeJS::AST::Node *node) -{ - return (node->kind == AST::Node::Kind_ConditionalExpression); -} - -bool QDeclarativeBindingCompilerPrivate::parseConditional(QDeclarativeJS::AST::Node *node, Result &type) -{ - AST::ConditionalExpression *expression = static_cast(node); - - AST::Node *test = expression->expression; - if (test->kind == AST::Node::Kind_NestedExpression) - test = static_cast(test)->expression; - - Result etype; - if (!parseExpression(test, etype)) return false; - - if (etype.type != QVariant::Bool) - return false; - - Instr skip; - skip.common.type = Instr::Skip; - skip.skip.reg = etype.reg; - skip.skip.count = 0; - int skipIdx = bytecode.count(); - bytecode << skip; - - // Release to allow reuse of reg - releaseReg(etype.reg); - - QSet preSubSet = subscriptionSet; - - // int preConditionalSubscriptions = subscriptionSet.count(); - - Result ok; - if (!parseExpression(expression->ok, ok)) return false; - if (ok.unknownType) return false; - - int skipIdx2 = bytecode.count(); - skip.skip.reg = -1; - bytecode << skip; - - // Release to allow reuse of reg - releaseReg(ok.reg); - bytecode[skipIdx].skip.count = bytecode.count() - skipIdx - 1; - - subscriptionSet = preSubSet; - - Result ko; - if (!parseExpression(expression->ko, ko)) return false; - if (ko.unknownType) return false; - - // Release to allow reuse of reg - releaseReg(ko.reg); - bytecode[skipIdx2].skip.count = bytecode.count() - skipIdx2 - 1; - - if (ok != ko) - return false; // Must be same type and in same register - - subscriptionSet = preSubSet; - - if (!subscriptionNeutral(subscriptionSet, ok.subscriptionSet, ko.subscriptionSet)) - return false; // Conditionals cannot introduce new subscriptions - - type = ok; - - return true; -} - -bool QDeclarativeBindingCompilerPrivate::tryConstant(QDeclarativeJS::AST::Node *node) -{ - return node->kind == AST::Node::Kind_TrueLiteral || - node->kind == AST::Node::Kind_FalseLiteral || - node->kind == AST::Node::Kind_NumericLiteral || - node->kind == AST::Node::Kind_StringLiteral; -} - -bool QDeclarativeBindingCompilerPrivate::parseConstant(QDeclarativeJS::AST::Node *node, Result &type) -{ - type.metaObject = 0; - type.type = -1; - type.reg = acquireReg(); - if (type.reg == -1) - return false; - - if (node->kind == AST::Node::Kind_TrueLiteral) { - type.type = QVariant::Bool; - Instr instr; - instr.common.type = Instr::Bool; - instr.bool_value.reg = type.reg; - instr.bool_value.value = true; - bytecode << instr; - return true; - } else if (node->kind == AST::Node::Kind_FalseLiteral) { - type.type = QVariant::Bool; - Instr instr; - instr.common.type = Instr::Bool; - instr.bool_value.reg = type.reg; - instr.bool_value.value = false; - bytecode << instr; - return true; - } else if (node->kind == AST::Node::Kind_NumericLiteral) { - qreal value = qreal(static_cast(node)->value); - - if (qreal(float(value)) != value) - return false; - - type.type = QMetaType::QReal; - Instr instr; - instr.common.type = Instr::Real; - instr.real_value.reg = type.reg; - instr.real_value.value = float(value); - bytecode << instr; - return true; - } else if (node->kind == AST::Node::Kind_StringLiteral) { - QString str = static_cast(node)->value->asString(); - type.type = QMetaType::QString; - type.reg = registerLiteralString(str); - return true; - } else { - return false; - } -} - -bool QDeclarativeBindingCompilerPrivate::tryMethod(QDeclarativeJS::AST::Node *node) -{ - return node->kind == AST::Node::Kind_CallExpression; -} - -bool QDeclarativeBindingCompilerPrivate::parseMethod(QDeclarativeJS::AST::Node *node, Result &result) -{ - AST::CallExpression *expr = static_cast(node); - - QStringList name; - if (!buildName(name, expr->base)) - return false; - - if (name.count() != 2 || name.at(0) != QLatin1String("Math")) - return false; - - QString method = name.at(1); - - AST::ArgumentList *args = expr->arguments; - if (!args) return false; - AST::ExpressionNode *arg0 = args->expression; - args = args->next; - if (!args) return false; - AST::ExpressionNode *arg1 = args->expression; - if (args->next != 0) return false; - if (!arg0 || !arg1) return false; - - Result r0; - if (!parseExpression(arg0, r0)) return false; - Result r1; - if (!parseExpression(arg1, r1)) return false; - - if (r0.type != QMetaType::QReal || r1.type != QMetaType::QReal) - return false; - - Instr op; - if (method == QLatin1String("max")) { - op.common.type = Instr::MaxReal; - } else if (method == QLatin1String("min")) { - op.common.type = Instr::MinReal; - } else { - return false; - } - // We release early to reuse registers - releaseReg(r0.reg); - releaseReg(r1.reg); - - op.binaryop.output = acquireReg(); - if (op.binaryop.output == -1) - return false; - - op.binaryop.src1 = r0.reg; - op.binaryop.src2 = r1.reg; - bytecode << op; - - result.type = QMetaType::QReal; - result.reg = op.binaryop.output; - - return true; -} - -bool QDeclarativeBindingCompilerPrivate::buildName(QStringList &name, - QDeclarativeJS::AST::Node *node, - QList *nodes) -{ - if (node->kind == AST::Node::Kind_IdentifierExpression) { - name << static_cast(node)->name->asString(); - if (nodes) *nodes << static_cast(node); - } else if (node->kind == AST::Node::Kind_FieldMemberExpression) { - AST::FieldMemberExpression *expr = - static_cast(node); - - if (!buildName(name, expr->base, nodes)) - return false; - - name << expr->name->asString(); - if (nodes) *nodes << expr; - } else { - return false; - } - - return true; -} - -bool QDeclarativeBindingCompilerPrivate::fetch(Result &rv, const QMetaObject *mo, int reg, - int idx, const QStringList &subName, - QDeclarativeJS::AST::ExpressionNode *node) -{ - QMetaProperty prop = mo->property(idx); - rv.metaObject = 0; - rv.type = 0; - - //XXX binding optimizer doesn't handle properties with a revision - if (prop.revision() > 0) - return false; - - int fastFetchIndex = fastProperties()->accessorIndexForProperty(mo, idx); - - Instr fetch; - - if (!qmlDisableFastProperties() && fastFetchIndex != -1) { - fetch.common.type = Instr::FetchAndSubscribe; - fetch.fetchAndSubscribe.objectReg = reg; - fetch.fetchAndSubscribe.output = reg; - fetch.fetchAndSubscribe.function = fastFetchIndex; - fetch.fetchAndSubscribe.subscription = subscriptionIndex(subName); - fetch.fetchAndSubscribe.exceptionId = exceptionId(node); - } else { - if (subscription(subName, &rv) && prop.hasNotifySignal() && prop.notifySignalIndex() != -1) { - Instr sub; - sub.common.type = Instr::Subscribe; - sub.subscribe.offset = subscriptionIndex(subName); - sub.subscribe.reg = reg; - sub.subscribe.index = prop.notifySignalIndex(); - bytecode << sub; - } - - fetch.common.type = Instr::Fetch; - fetch.fetch.objectReg = reg; - fetch.fetch.index = idx; - fetch.fetch.output = reg; - fetch.fetch.exceptionId = exceptionId(node); - } - - rv.type = prop.userType(); - rv.metaObject = engine->metaObjectForType(rv.type); - rv.reg = reg; - - if (rv.type == QMetaType::QString) { - int tmp = acquireReg(); - if (tmp == -1) - return false; - Instr copy; - copy.common.type = Instr::Copy; - copy.copy.reg = tmp; - copy.copy.src = reg; - bytecode << copy; - releaseReg(tmp); - fetch.fetch.objectReg = tmp; - - Instr setup; - setup.common.type = Instr::NewString; - setup.construct.reg = reg; - bytecode << setup; - registerCleanup(reg, Instr::CleanupString); - } - - bytecode << fetch; - - if (!rv.metaObject && - rv.type != QMetaType::QReal && - rv.type != QMetaType::Int && - rv.type != QMetaType::Bool && - rv.type != qMetaTypeId() && - rv.type != QMetaType::QString) { - rv.metaObject = 0; - rv.type = 0; - return false; // Unsupported type (string not supported yet); - } - - return true; -} - -void QDeclarativeBindingCompilerPrivate::registerCleanup(int reg, int cleanup, int cleanupType) -{ - registerCleanups.insert(reg, qMakePair(cleanup, cleanupType)); -} - -int QDeclarativeBindingCompilerPrivate::acquireReg(int cleanup, int cleanupType) -{ - for (int ii = 0; ii < 32; ++ii) { - if (!(registers & (1 << ii))) { - registers |= (1 << ii); - - if (cleanup != Instr::Noop) - registerCleanup(ii, cleanup, cleanupType); - - return ii; - } - } - return -1; -} - -void QDeclarativeBindingCompilerPrivate::releaseReg(int reg) -{ - Q_ASSERT(reg >= 0 && reg <= 31); - - if (registerCleanups.contains(reg)) { - QPair c = registerCleanups[reg]; - registerCleanups.remove(reg); - Instr cleanup; - cleanup.common.type = (quint8)c.first; - cleanup.cleanup.reg = reg; - bytecode << cleanup; - } - - quint32 mask = 1 << reg; - registers &= ~mask; -} - -// Returns a reg -int QDeclarativeBindingCompilerPrivate::registerLiteralString(const QString &str) -{ - QByteArray strdata((const char *)str.constData(), str.length() * sizeof(QChar)); - int offset = data.count(); - data += strdata; - - int reg = acquireReg(Instr::CleanupString); - if (reg == -1) - return false; - - Instr string; - string.common.type = Instr::String; - string.string_value.reg = reg; - string.string_value.offset = offset; - string.string_value.length = str.length(); - bytecode << string; - - return reg; -} - -// Returns an identifier offset -int QDeclarativeBindingCompilerPrivate::registerString(const QString &string) -{ - Q_ASSERT(!string.isEmpty()); - - QHash >::ConstIterator iter = registeredStrings.find(string); - - if (iter == registeredStrings.end()) { - quint32 len = string.length(); - QByteArray lendata((const char *)&len, sizeof(quint32)); - QByteArray strdata((const char *)string.constData(), string.length() * sizeof(QChar)); - strdata.prepend(lendata); - int rv = data.count(); - data += strdata; - - iter = registeredStrings.insert(string, qMakePair(registeredStrings.count(), rv)); - } - - Instr reg; - reg.common.type = Instr::InitString; - reg.initstring.offset = iter->first; - reg.initstring.dataIdx = iter->second; - bytecode << reg; - return reg.initstring.offset; -} - -bool QDeclarativeBindingCompilerPrivate::subscription(const QStringList &sub, Result *result) -{ - QString str = sub.join(QLatin1String(".")); - result->subscriptionSet.insert(str); - - if (subscriptionSet.contains(str)) { - return false; - } else { - subscriptionSet.insert(str); - return true; - } -} - -int QDeclarativeBindingCompilerPrivate::subscriptionIndex(const QStringList &sub) -{ - QString str = sub.join(QLatin1String(".")); - QHash::ConstIterator iter = subscriptionIds.find(str); - if (iter == subscriptionIds.end()) - iter = subscriptionIds.insert(str, subscriptionIds.count()); - usedSubscriptionIds.insert(*iter); - return *iter; -} - -/* - Returns true if lhs contains no subscriptions that aren't also in base or rhs AND - rhs contains no subscriptions that aren't also in base or lhs. -*/ -bool QDeclarativeBindingCompilerPrivate::subscriptionNeutral(const QSet &base, - const QSet &lhs, - const QSet &rhs) -{ - QSet difflhs = lhs; - difflhs.subtract(rhs); - QSet diffrhs = rhs; - diffrhs.subtract(lhs); - - difflhs.unite(diffrhs); - difflhs.subtract(base); - - return difflhs.isEmpty(); -} - -quint8 QDeclarativeBindingCompilerPrivate::exceptionId(QDeclarativeJS::AST::ExpressionNode *n) -{ - quint8 rv = 0xFF; - if (n && exceptions.count() < 0xFF) { - rv = (quint8)exceptions.count(); - QDeclarativeJS::AST::SourceLocation l = n->firstSourceLocation(); - quint64 e = l.startLine; - e <<= 32; - e |= l.startColumn; - exceptions.append(e); - } - return rv; -} - -QDeclarativeBindingCompiler::QDeclarativeBindingCompiler() -: d(new QDeclarativeBindingCompilerPrivate) -{ -} - -QDeclarativeBindingCompiler::~QDeclarativeBindingCompiler() -{ - delete d; d = 0; -} - -/* -Returns true if any bindings were compiled. -*/ -bool QDeclarativeBindingCompiler::isValid() const -{ - return !d->committed.bytecode.isEmpty(); -} - -/* --1 on failure, otherwise the binding index to use. -*/ -int QDeclarativeBindingCompiler::compile(const Expression &expression, QDeclarativeEnginePrivate *engine) -{ - if (!expression.expression.asAST()) return false; - - if (!qmlExperimental() && expression.property->isValueTypeSubProperty) - return -1; - - if (qmlDisableOptimizer()) - return -1; - - d->context = expression.context; - d->component = expression.component; - d->destination = expression.property; - d->ids = expression.ids; - d->imports = expression.imports; - d->engine = engine; - - if (d->compile(expression.expression.asAST())) { - return d->commitCompile(); - } else { - return -1; - } -} - - -QByteArray QDeclarativeBindingCompilerPrivate::buildSignalTable() const -{ - QHash > table; - - for (int ii = 0; ii < committed.count(); ++ii) { - const QSet &deps = committed.dependencies.at(ii); - for (QSet::ConstIterator iter = deps.begin(); iter != deps.end(); ++iter) - table[*iter].append(ii); - } - - QVector header; - QVector data; - for (int ii = 0; ii < committed.subscriptionIds.count(); ++ii) { - header.append(committed.subscriptionIds.count() + data.count()); - const QList &bindings = table[ii]; - data.append(bindings.count()); - for (int jj = 0; jj < bindings.count(); ++jj) - data.append(bindings.at(jj)); - } - header << data; - - return QByteArray((const char *)header.constData(), header.count() * sizeof(quint32)); -} - -QByteArray QDeclarativeBindingCompilerPrivate::buildExceptionData() const -{ - QByteArray rv; - rv.resize(committed.exceptions.count() * sizeof(quint64)); - ::memcpy(rv.data(), committed.exceptions.constData(), rv.size()); - return rv; -} - -/* -Returns the compiled program. -*/ -QByteArray QDeclarativeBindingCompiler::program() const -{ - QByteArray programData; - - if (isValid()) { - Program prog; - prog.bindings = d->committed.count(); - - QVector bytecode; - Instr skip; - skip.common.type = Instr::Skip; - skip.skip.reg = -1; - for (int ii = 0; ii < d->committed.count(); ++ii) { - skip.skip.count = d->committed.count() - ii - 1; - skip.skip.count+= d->committed.offsets.at(ii); - bytecode << skip; - } - bytecode << d->committed.bytecode; - - QByteArray data = d->committed.data; - while (data.count() % 4) data.append('\0'); - prog.signalTableOffset = data.count(); - data += d->buildSignalTable(); - while (data.count() % 4) data.append('\0'); - prog.exceptionDataOffset = data.count(); - data += d->buildExceptionData(); - - prog.dataLength = 4 * ((data.size() + 3) / 4); - prog.subscriptions = d->committed.subscriptionIds.count(); - prog.identifiers = d->committed.registeredStrings.count(); - prog.instructionCount = bytecode.count(); - prog.compiled = false; - int size = sizeof(Program) + bytecode.count() * sizeof(Instr); - size += prog.dataLength; - - programData.resize(size); - memcpy(programData.data(), &prog, sizeof(Program)); - if (prog.dataLength) - memcpy((char *)((Program *)programData.data())->data(), data.constData(), - data.size()); - memcpy((char *)((Program *)programData.data())->instructions(), bytecode.constData(), - bytecode.count() * sizeof(Instr)); - } - - return programData; -} - - - -QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecompiledbindings_p.h b/src/declarative/qml/qdeclarativecompiledbindings_p.h deleted file mode 100644 index f3d8b4b804..0000000000 --- a/src/declarative/qml/qdeclarativecompiledbindings_p.h +++ /dev/null @@ -1,116 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QDECLARATIVEBINDINGOPTIMIZATIONS_P_H -#define QDECLARATIVEBINDINGOPTIMIZATIONS_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 "private/qdeclarativeexpression_p.h" -#include "private/qdeclarativebinding_p.h" - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -struct QDeclarativeBindingCompilerPrivate; -class QDeclarativeBindingCompiler -{ -public: - QDeclarativeBindingCompiler(); - ~QDeclarativeBindingCompiler(); - - // Returns true if bindings were compiled - bool isValid() const; - - struct Expression - { - QDeclarativeParser::Object *component; - QDeclarativeParser::Object *context; - QDeclarativeParser::Property *property; - QDeclarativeParser::Variant expression; - QHash ids; - QDeclarativeImports imports; - }; - - // -1 on failure, otherwise the binding index to use - int compile(const Expression &, QDeclarativeEnginePrivate *); - - // Returns the compiled program - QByteArray program() const; - - static void dump(const QByteArray &); -private: - QDeclarativeBindingCompilerPrivate *d; -}; - -class QDeclarativeCompiledBindingsPrivate; -class QDeclarativeCompiledBindings : public QObject, public QDeclarativeAbstractExpression, public QDeclarativeRefCount -{ -public: - QDeclarativeCompiledBindings(const char *program, QDeclarativeContextData *context); - virtual ~QDeclarativeCompiledBindings(); - - QDeclarativeAbstractBinding *configBinding(int index, QObject *target, QObject *scope, int property); - -protected: - int qt_metacall(QMetaObject::Call, int, void **); - -private: - Q_DISABLE_COPY(QDeclarativeCompiledBindings) - Q_DECLARE_PRIVATE(QDeclarativeCompiledBindings) -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QDECLARATIVEBINDINGOPTIMIZATIONS_P_H - diff --git a/src/declarative/qml/qdeclarativecompileddata.cpp b/src/declarative/qml/qdeclarativecompileddata.cpp index 03deea1e36..3d1e9255ad 100644 --- a/src/declarative/qml/qdeclarativecompileddata.cpp +++ b/src/declarative/qml/qdeclarativecompileddata.cpp @@ -181,6 +181,9 @@ QDeclarativeCompiledData::~QDeclarativeCompiledData() for (int ii = 0; ii < contextCaches.count(); ++ii) contextCaches.at(ii)->release(); + for (int ii = 0; ii < scripts.count(); ++ii) + scripts.at(ii)->release(); + if (importCache) importCache->release(); diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index f57f842004..d325ac48dd 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -63,7 +63,7 @@ #include "private/qdeclarativeglobal_p.h" #include "private/qdeclarativescriptparser_p.h" #include "private/qdeclarativebinding_p.h" -#include "private/qdeclarativecompiledbindings_p.h" +#include "private/qdeclarativev4compiler_p.h" #include "private/qdeclarativeglobalscriptclass_p.h" #include @@ -79,7 +79,6 @@ QT_BEGIN_NAMESPACE DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP); DEFINE_BOOL_CONFIG_OPTION(compilerStatDump, QML_COMPILER_STATS); -DEFINE_BOOL_CONFIG_OPTION(bindingsDump, QML_BINDINGS_DUMP); using namespace QDeclarativeParser; @@ -201,6 +200,9 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, case QVariant::String: if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: string 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; @@ -320,16 +322,20 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, QDeclarativeParser::Value *v) { - QString string = v->value.asString(); - QDeclarativeInstruction instr; instr.line = v->location.start.line; if (prop.isEnumType()) { int value; - if (prop.isFlagType()) { - value = prop.enumerator().keysToValue(string.toUtf8().constData()); - } else - value = prop.enumerator().keyToValue(string.toUtf8().constData()); + if (v->value.isNumber()) { + // Preresolved enum + value = (int)v->value.asNumber(); + } else { + // Must be a string + if (prop.isFlagType()) { + value = prop.enumerator().keysToValue(v->value.asString().toUtf8().constData()); + } else + value = prop.enumerator().keyToValue(v->value.asString().toUtf8().constData()); + } instr.type = QDeclarativeInstruction::StoreInteger; instr.storeInteger.propertyIndex = prop.propertyIndex(); @@ -338,6 +344,8 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, return; } + QString string = v->value.asString(); + int type = prop.userType(); switch(type) { case -1: @@ -371,6 +379,13 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, instr.storeString.value = output->indexForString(string); } break; + case QVariant::ByteArray: + { + instr.type = QDeclarativeInstruction::StoreByteArray; + instr.storeByteArray.propertyIndex = prop.propertyIndex(); + instr.storeByteArray.value = output->indexForByteArray(string.toLatin1()); + } + break; case QVariant::Url: { instr.type = QDeclarativeInstruction::StoreUrl; @@ -642,6 +657,31 @@ void QDeclarativeCompiler::compileTree(QDeclarativeParser::Object *tree) compileState.root = tree; componentStat.lineNumber = tree->location.start.line; + // Build global import scripts + QStringList importedScriptIndexes; + + foreach (const QDeclarativeTypeData::ScriptReference &script, unit->resolvedScripts()) { + importedScriptIndexes.append(script.qualifier); + + QDeclarativeInstruction import; + import.type = QDeclarativeInstruction::StoreImportedScript; + import.line = 0; + import.storeScript.value = output->scripts.count(); + + QDeclarativeScriptData *scriptData = script.script->scriptData(); + scriptData->addref(); + output->scripts << scriptData; + output->bytecode << import; + } + + // We generate the importCache before we build the tree so that + // it can be used in the binding compiler. Given we "expect" the + // QML compilation to succeed, this isn't a waste. + output->importCache = new QDeclarativeTypeNameCache(engine); + for (int ii = 0; ii < importedScriptIndexes.count(); ++ii) + output->importCache->add(importedScriptIndexes.at(ii), ii); + unit->imports().populateCache(output->importCache, engine); + if (!buildObject(tree, BindingContext()) || !completeComponentBuild()) return; @@ -657,38 +697,6 @@ void QDeclarativeCompiler::compileTree(QDeclarativeParser::Object *tree) init.init.compiledBinding = output->indexForByteArray(compileState.compiledBindingData); output->bytecode << init; - // Build global import scripts - QHash importedScripts; - QStringList importedScriptIndexes; - - foreach (const QDeclarativeTypeData::ScriptReference &script, unit->resolvedScripts()) { - QString scriptCode = script.script->scriptSource(); - Object::ScriptBlock::Pragmas pragmas = script.script->pragmas(); - - Q_ASSERT(!importedScripts.contains(script.qualifier)); - - if (!scriptCode.isEmpty()) { - Object::ScriptBlock &scriptBlock = importedScripts[script.qualifier]; - - scriptBlock.code = scriptCode; - scriptBlock.file = script.script->finalUrl().toString(); - scriptBlock.pragmas = pragmas; - } - } - - for (QHash::Iterator iter = importedScripts.begin(); - iter != importedScripts.end(); ++iter) { - - importedScriptIndexes.append(iter.key()); - - QDeclarativeInstruction import; - import.type = QDeclarativeInstruction::StoreImportedScript; - import.line = 0; - import.storeScript.value = output->scripts.count(); - output->scripts << *iter; - output->bytecode << import; - } - genObject(tree); QDeclarativeInstruction def; @@ -696,13 +704,6 @@ void QDeclarativeCompiler::compileTree(QDeclarativeParser::Object *tree) def.type = QDeclarativeInstruction::SetDefault; output->bytecode << def; - output->importCache = new QDeclarativeTypeNameCache(engine); - - for (int ii = 0; ii < importedScriptIndexes.count(); ++ii) - output->importCache->add(importedScriptIndexes.at(ii), ii); - - unit->imports().populateCache(output->importCache, engine); - Q_ASSERT(tree->metatype); if (tree->metadata.isEmpty()) { @@ -1283,6 +1284,7 @@ bool QDeclarativeCompiler::buildComponentFromRoot(QDeclarativeParser::Object *ob compileState = ComponentCompileState(); compileState.root = obj; + compileState.nested = true; componentStat = ComponentStat(); componentStat.lineNumber = obj->location.start.line; @@ -1442,8 +1444,6 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, unit->imports().resolveType(prop->name, &type, 0, 0, 0, &typeNamespace); if (typeNamespace) { - // ### We might need to indicate that this property is a namespace - // for the DOM API COMPILE_CHECK(buildPropertyInNamespace(typeNamespace, prop, obj, ctxt)); return true; @@ -2227,20 +2227,35 @@ bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop objTypeName = objType->qmlTypeName(); } - if (!type || objTypeName != type->qmlTypeName()) + if (!type) return true; QString enumValue = parts.at(1); - int value; - if (prop.isFlagType()) { - value = prop.enumerator().keysToValue(enumValue.toUtf8().constData()); - } else - value = prop.enumerator().keyToValue(enumValue.toUtf8().constData()); + int value = -1; + + if (objTypeName == type->qmlTypeName()) { + // When these two match, we can short cut the search + if (prop.isFlagType()) { + value = prop.enumerator().keysToValue(enumValue.toUtf8().constData()); + } else { + value = prop.enumerator().keyToValue(enumValue.toUtf8().constData()); + } + } else { + // Otherwise we have to search the whole type + // This matches the logic in QDeclarativeTypeNameScriptClass + QByteArray enumName = enumValue.toUtf8(); + const QMetaObject *metaObject = type->baseMetaObject(); + for (int ii = metaObject->enumeratorCount() - 1; value == -1 && ii >= 0; --ii) { + QMetaEnum e = metaObject->enumerator(ii); + value = e.keyToValue(enumName.constData()); + } + } + if (value == -1) return true; v->type = Value::Literal; - v->value = QDeclarativeParser::Variant(enumValue); + v->value = QDeclarativeParser::Variant((double)value); *isAssignment = true; return true; @@ -2412,7 +2427,7 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn newClassName.append("_QML_"); int idx = classIndexCounter()->fetchAndAddRelaxed(1); newClassName.append(QByteArray::number(idx)); - if (compileState.root == obj) { + if (compileState.root == obj && !compileState.nested) { QString path = output->url.path(); int lastSlash = path.lastIndexOf(QLatin1Char('/')); if (lastSlash > -1) { @@ -2888,25 +2903,26 @@ bool QDeclarativeCompiler::completeComponentBuild() COMPILE_CHECK(buildDynamicMeta(aliasObject, ResolveAliases)); } - QDeclarativeBindingCompiler::Expression expr; + QDeclarativeV4Compiler::Expression expr; expr.component = compileState.root; expr.ids = compileState.ids; + expr.importCache = output->importCache; + expr.imports = unit->imports(); - QDeclarativeBindingCompiler bindingCompiler; + QDeclarativeV4Compiler bindingCompiler; for (QHash::Iterator iter = compileState.bindings.begin(); iter != compileState.bindings.end(); ++iter) { BindingReference &binding = *iter; - expr.context = binding.bindingContext.object; - expr.property = binding.property; - expr.expression = binding.expression; - expr.imports = unit->imports(); - // ### We don't currently optimize for bindings on alias's - because // of the solution to QTBUG-13719 if (!binding.property->isAlias) { + expr.context = binding.bindingContext.object; + expr.property = binding.property; + expr.expression = binding.expression; + int index = bindingCompiler.compile(expr, enginePrivate); if (index != -1) { binding.dataType = BindingReference::Experimental; @@ -2947,11 +2963,8 @@ bool QDeclarativeCompiler::completeComponentBuild() componentStat.scriptBindings.append(iter.key()->location); } - if (bindingCompiler.isValid()) { + if (bindingCompiler.isValid()) compileState.compiledBindingData = bindingCompiler.program(); - if (bindingsDump()) - QDeclarativeBindingCompiler::dump(compileState.compiledBindingData); - } saveComponentState(); diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h index 93b6a0961e..49bab759be 100644 --- a/src/declarative/qml/qdeclarativecompiler_p.h +++ b/src/declarative/qml/qdeclarativecompiler_p.h @@ -122,7 +122,7 @@ public: QList cachedClosures; QList propertyCaches; QList contextCaches; - QList scripts; + QList scripts; QList urls; void dumpInstructions(); @@ -305,11 +305,12 @@ private: struct ComponentCompileState { ComponentCompileState() - : parserStatusCount(0), pushedProperties(0), root(0) {} + : parserStatusCount(0), pushedProperties(0), nested(false), root(0) {} QHash ids; QHash idIndexes; int parserStatusCount; int pushedProperties; + bool nested; QByteArray compiledBindingData; diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index 8238252db2..aa1bbd156f 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -836,6 +836,34 @@ QDeclarativeComponentPrivate::beginCreate(QDeclarativeContextData *context, cons return begin(context, creationContext, cc, start, count, &state, 0, bindings); } +/* + Try to do what's necessary for a reasonable display of the type + name, but no more (just enough for the client to do more extensive cleanup). + + Should only be called when debugging is enabled. +*/ +static inline QString buildTypeNameForDebug(const QMetaObject *metaObject) +{ + static const QString qmlMarker(QLatin1String("_QML")); + static const QChar underscore(QLatin1Char('_')); + static const QChar asterisk(QLatin1Char('*')); + QDeclarativeType *type = QDeclarativeMetaType::qmlType(metaObject); + QString typeName = type ? QLatin1String(type->qmlTypeName()) : QLatin1String(metaObject->className()); + if (!type) { + //### optimize further? + int marker = typeName.indexOf(qmlMarker); + if (marker != -1 && marker < typeName.count() - 1) { + if (typeName[marker + 1] == underscore) { + const QString className = typeName.left(marker) + asterisk; + type = QDeclarativeMetaType::qmlType(QMetaType::type(className.toLatin1())); + if (type) + typeName = QLatin1String(type->qmlTypeName()); + } + } + } + return typeName; +} + QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentContext, QDeclarativeContextData *componentCreationContext, QDeclarativeCompiledData *component, int start, int count, @@ -848,10 +876,8 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentCon Q_ASSERT(!isRoot || state); // Either this isn't a root component, or a state data must be provided Q_ASSERT((state != 0) ^ (errors != 0)); // One of state or errors (but not both) must be provided - if (isRoot) { + if (isRoot) QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating); - QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, component->url); - } QDeclarativeContextData *ctxt = new QDeclarativeContextData; ctxt->isInternal = true; @@ -868,7 +894,9 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentCon enginePriv->inBeginCreate = true; QDeclarativeVME vme; + enginePriv->referenceScarceResources(); // "hold" scarce resources in memory during evaluation. QObject *rv = vme.run(ctxt, component, start, count, bindings); + enginePriv->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete. if (vme.isError()) { if(errors) *errors = vme.errors(); @@ -897,6 +925,11 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentCon if (!parentContext->isInternal) parentContext->asQDeclarativeContextPrivate()->instances.append(rv); QDeclarativeEngineDebugServer::instance()->objectCreated(parentContext->engine, rv); + if (isRoot) { + QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, buildTypeNameForDebug(rv->metaObject())); + QDeclarativeData *data = QDeclarativeData::get(rv); + QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Creating, component->url, data ? data->lineNumber : -1); + } } return rv; diff --git a/src/declarative/qml/qdeclarativecomponent.h b/src/declarative/qml/qdeclarativecomponent.h index 9a60a8b4f7..f46ffdf2cf 100644 --- a/src/declarative/qml/qdeclarativecomponent.h +++ b/src/declarative/qml/qdeclarativecomponent.h @@ -117,7 +117,6 @@ private: Q_DISABLE_COPY(QDeclarativeComponent) friend class QDeclarativeVME; - friend class QDeclarativeCompositeTypeData; friend class QDeclarativeTypeData; }; diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp index 7637b72eb3..4f0d704d95 100644 --- a/src/declarative/qml/qdeclarativecontext.cpp +++ b/src/declarative/qml/qdeclarativecontext.cpp @@ -46,9 +46,9 @@ #include "private/qdeclarativeexpression_p.h" #include "private/qdeclarativeengine_p.h" #include "qdeclarativeengine.h" -#include "private/qdeclarativecompiledbindings_p.h" #include "qdeclarativeinfo.h" #include "private/qdeclarativeglobalscriptclass_p.h" +#include "private/qdeclarativev4bindings_p.h" #include #include @@ -498,7 +498,7 @@ QObject *QDeclarativeContextPrivate::context_at(QDeclarativeListPropertyinvalidate(); + while (childContexts) { + if (childContexts->ownedByParent) { + childContexts->destroy(); + } else { + childContexts->invalidate(); + } + } while (componentAttached) { QDeclarativeComponentAttached *a = componentAttached; @@ -614,7 +619,7 @@ void QDeclarativeContextData::destroy() delete this; } -void QDeclarativeContextData::setParent(QDeclarativeContextData *p) +void QDeclarativeContextData::setParent(QDeclarativeContextData *p, bool parentTakesOwnership) { if (p) { parent = p; @@ -623,6 +628,7 @@ void QDeclarativeContextData::setParent(QDeclarativeContextData *p) if (nextChild) nextChild->prevChild = &nextChild; prevChild = &p->childContexts; p->childContexts = this; + ownedByParent = parentTakesOwnership; } } @@ -662,72 +668,6 @@ void QDeclarativeContextData::addObject(QObject *o) contextObjects = data; } -void QDeclarativeContextData::addImportedScript(const QDeclarativeParser::Object::ScriptBlock &script) -{ - if (!engine) - return; - - QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine); - QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); - - const QString &code = script.code; - const QString &url = script.file; - const QDeclarativeParser::Object::ScriptBlock::Pragmas &pragmas = script.pragmas; - - Q_ASSERT(!url.isEmpty()); - - if (pragmas & QDeclarativeParser::Object::ScriptBlock::Shared) { - - QHash::Iterator iter = enginePriv->m_sharedScriptImports.find(url); - if (iter == enginePriv->m_sharedScriptImports.end()) { - QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); - - scriptContext->pushScope(enginePriv->contextClass->newUrlContext(url)); - scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject()); - - QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine); - scriptContext->pushScope(scope); - - scriptEngine->evaluate(code, url, 1); - - if (scriptEngine->hasUncaughtException()) { - QDeclarativeError error; - QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error); - enginePriv->warning(error); - } - - scriptEngine->popContext(); - - iter = enginePriv->m_sharedScriptImports.insert(url, scope); - } - - importedScripts.append(*iter); - - } else { - - QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); - - scriptContext->pushScope(enginePriv->contextClass->newUrlContext(this, 0, url)); - scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject()); - - QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine); - scriptContext->pushScope(scope); - - scriptEngine->evaluate(code, url, 1); - - if (scriptEngine->hasUncaughtException()) { - QDeclarativeError error; - QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error); - enginePriv->warning(error); - } - - scriptEngine->popContext(); - - importedScripts.append(scope); - - } -} - void QDeclarativeContextData::setIdProperty(int idx, QObject *obj) { idValues[idx] = obj; diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h index b7e4c6aa7c..29ca091fc2 100644 --- a/src/declarative/qml/qdeclarativecontext_p.h +++ b/src/declarative/qml/qdeclarativecontext_p.h @@ -77,7 +77,7 @@ class QDeclarativeEngine; class QDeclarativeExpression; class QDeclarativeExpressionPrivate; class QDeclarativeAbstractExpression; -class QDeclarativeCompiledBindings; +class QDeclarativeV4Bindings; class QDeclarativeContextData; class QDeclarativeContextPrivate : public QObjectPrivate @@ -124,7 +124,7 @@ public: QDeclarativeContextData *parent; QDeclarativeEngine *engine; - void setParent(QDeclarativeContextData *); + void setParent(QDeclarativeContextData *, bool parentTakesOwnership = false); void refreshExpressions(); void addObject(QObject *); @@ -135,7 +135,9 @@ public: // If internal is false publicContext owns this. QDeclarativeContext *asQDeclarativeContext(); QDeclarativeContextPrivate *asQDeclarativeContextPrivate(); - bool isInternal; + quint32 isInternal:1; + quint32 ownedByParent:1; // unrelated to isInternal; parent context deletes children if true. + quint32 dummy:30; QDeclarativeContext *publicContext; // Property name cache @@ -146,7 +148,6 @@ public: // Any script blocks that exist on this context QList importedScripts; - void addImportedScript(const QDeclarativeParser::Object::ScriptBlock &script); // Context base url QUrl url; @@ -188,7 +189,7 @@ public: void setIdPropertyData(QDeclarativeIntegerCache *); // Optimized binding pointer - QDeclarativeCompiledBindings *optimizedBindings; + QDeclarativeV4Bindings *optimizedBindings; // Linked contexts. this owns linkedContext. QDeclarativeContextData *linkedContext; diff --git a/src/declarative/qml/qdeclarativedirparser.cpp b/src/declarative/qml/qdeclarativedirparser.cpp index b5ad33d63e..97f7f4dda8 100644 --- a/src/declarative/qml/qdeclarativedirparser.cpp +++ b/src/declarative/qml/qdeclarativedirparser.cpp @@ -142,7 +142,7 @@ bool QDeclarativeDirParser::parse() } else if (sections[0] == QLatin1String("plugin")) { if (sectionCount < 2) { reportError(lineNumber, -1, - QString::fromUtf8("plugin directive requires 2 arguments, but %1 were provided").arg(sectionCount + 1)); + QString::fromUtf8("plugin directive requires one or two arguments, but %1 were provided").arg(sectionCount - 1)); continue; } @@ -154,12 +154,22 @@ bool QDeclarativeDirParser::parse() } else if (sections[0] == QLatin1String("internal")) { if (sectionCount != 3) { reportError(lineNumber, -1, - QString::fromUtf8("internal types require 2 arguments, but %1 were provided").arg(sectionCount + 1)); + QString::fromUtf8("internal types require 2 arguments, but %1 were provided").arg(sectionCount - 1)); continue; } Component entry(sections[1], sections[2], -1, -1); entry.internal = true; _components.append(entry); + } else if (sections[0] == QLatin1String("typeinfo")) { + if (sectionCount != 2) { + reportError(lineNumber, -1, + QString::fromUtf8("typeinfo requires 1 argument, but %1 were provided").arg(sectionCount - 1)); + continue; + } +#ifdef QT_CREATOR + TypeInfo typeInfo(sections[1]); + _typeInfos.append(typeInfo); +#endif } else if (sectionCount == 2) { // No version specified (should only be used for relative qmldir files) @@ -189,7 +199,7 @@ bool QDeclarativeDirParser::parse() } } else { reportError(lineNumber, -1, - QString::fromUtf8("a component declaration requires 3 arguments, but %1 were provided").arg(sectionCount + 1)); + QString::fromUtf8("a component declaration requires two or three arguments, but %1 were provided").arg(sectionCount)); } } @@ -229,4 +239,11 @@ QList QDeclarativeDirParser::components() cons return _components; } +#ifdef QT_CREATOR +QList QDeclarativeDirParser::typeInfos() const +{ + return _typeInfos; +} +#endif + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativedirparser_p.h b/src/declarative/qml/qdeclarativedirparser_p.h index 95f14bc487..d09b90e7a2 100644 --- a/src/declarative/qml/qdeclarativedirparser_p.h +++ b/src/declarative/qml/qdeclarativedirparser_p.h @@ -109,6 +109,19 @@ public: QList components() const; QList plugins() const; +#ifdef QT_CREATOR + struct TypeInfo + { + TypeInfo() {} + TypeInfo(const QString &fileName) + : fileName(fileName) {} + + QString fileName; + }; + + QList typeInfos() const; +#endif + private: void reportError(int line, int column, const QString &message); @@ -118,6 +131,9 @@ private: QString _source; QList _components; QList _plugins; +#ifdef QT_CREATOR + QList _typeInfos; +#endif unsigned _isParsed: 1; }; diff --git a/src/declarative/qml/qdeclarativedom.cpp b/src/declarative/qml/qdeclarativedom.cpp deleted file mode 100644 index f1296aaf18..0000000000 --- a/src/declarative/qml/qdeclarativedom.cpp +++ /dev/null @@ -1,1835 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "private/qdeclarativedom_p.h" -#include "private/qdeclarativedom_p_p.h" - -#include "private/qdeclarativecompiler_p.h" -#include "private/qdeclarativeengine_p.h" -#include "private/qdeclarativescriptparser_p.h" -#include "private/qdeclarativeglobal_p.h" - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -QDeclarativeDomDocumentPrivate::QDeclarativeDomDocumentPrivate() -: root(0) -{ -} - -QDeclarativeDomDocumentPrivate::~QDeclarativeDomDocumentPrivate() -{ - if (root) root->release(); -} - -/*! - \class QDeclarativeDomDocument - \internal - \brief The QDeclarativeDomDocument class represents the root of a QML document - - A QML document is a self-contained snippet of QML, usually contained in a - single file. Each document has a root object, accessible through - QDeclarativeDomDocument::rootObject(). - - The QDeclarativeDomDocument class allows the programmer to inspect a QML document by - calling QDeclarativeDomDocument::load(). - - The following example loads a QML file from disk, and prints out its root - object type and the properties assigned in the root object. - \code - QFile file(inputFileName); - file.open(QIODevice::ReadOnly); - QByteArray xmlData = file.readAll(); - - QDeclarativeDomDocument document; - document.load(qmlengine, xmlData); - - QDeclarativeDomObject rootObject = document.rootObject(); - qDebug() << rootObject.objectType(); - foreach(QDeclarativeDomProperty property, rootObject.properties()) - qDebug() << property.propertyName(); - \endcode -*/ - -/*! - Construct an empty QDeclarativeDomDocument. -*/ -QDeclarativeDomDocument::QDeclarativeDomDocument() -: d(new QDeclarativeDomDocumentPrivate) -{ -} - -/*! - Create a copy of \a other QDeclarativeDomDocument. -*/ -QDeclarativeDomDocument::QDeclarativeDomDocument(const QDeclarativeDomDocument &other) -: d(other.d) -{ -} - -/*! - Destroy the QDeclarativeDomDocument -*/ -QDeclarativeDomDocument::~QDeclarativeDomDocument() -{ -} - -/*! - Assign \a other to this QDeclarativeDomDocument. -*/ -QDeclarativeDomDocument &QDeclarativeDomDocument::operator=(const QDeclarativeDomDocument &other) -{ - d = other.d; - return *this; -} - -/*! - Returns all import statements in qml. -*/ -QList QDeclarativeDomDocument::imports() const -{ - return d->imports; -} - -/*! - Loads a QDeclarativeDomDocument from \a data. \a data should be valid QML - data. On success, true is returned. If the \a data is malformed, false - is returned and QDeclarativeDomDocument::errors() contains an error description. - - \sa QDeclarativeDomDocument::loadError() -*/ -bool QDeclarativeDomDocument::load(QDeclarativeEngine *engine, const QByteArray &data, const QUrl &url) -{ - d->errors.clear(); - d->imports.clear(); - - QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); - QDeclarativeTypeData *td = ep->typeLoader.get(data, url, QDeclarativeTypeLoader::PreserveParser); - - if(td->isError()) { - d->errors = td->errors(); - td->release(); - return false; - } else if(!td->isCompleteOrError()) { - QDeclarativeError error; - error.setDescription(QLatin1String("QDeclarativeDomDocument supports local types only")); - d->errors << error; - td->release(); - return false; - } - - for (int i = 0; i < td->parser().imports().size(); ++i) { - QDeclarativeScriptParser::Import parserImport = td->parser().imports().at(i); - QDeclarativeDomImport domImport; - domImport.d->type = static_cast(parserImport.type); - domImport.d->uri = parserImport.uri; - domImport.d->qualifier = parserImport.qualifier; - domImport.d->version = parserImport.version; - d->imports += domImport; - } - - if (td->parser().tree()) { - d->root = td->parser().tree(); - d->root->addref(); - } - - td->release(); - return true; -} - -/*! - Returns the last load errors. The load errors will be reset after a - successful call to load(). - - \sa load() -*/ -QList QDeclarativeDomDocument::errors() const -{ - return d->errors; -} - -/*! - Returns the document's root object, or an invalid QDeclarativeDomObject if the - document has no root. - - In the sample QML below, the root object will be the QDeclarativeItem type. - \qml -Item { - Text { - text: "Hello World" - } -} - \endqml -*/ -QDeclarativeDomObject QDeclarativeDomDocument::rootObject() const -{ - QDeclarativeDomObject rv; - rv.d->object = d->root; - if (rv.d->object) rv.d->object->addref(); - return rv; -} - -QDeclarativeDomPropertyPrivate::QDeclarativeDomPropertyPrivate() -: property(0) -{ -} - -QDeclarativeDomPropertyPrivate::~QDeclarativeDomPropertyPrivate() -{ - if (property) property->release(); -} - -QDeclarativeDomDynamicPropertyPrivate::QDeclarativeDomDynamicPropertyPrivate(): - valid(false) -{ -} - -QDeclarativeDomDynamicPropertyPrivate::~QDeclarativeDomDynamicPropertyPrivate() -{ - if (valid && property.defaultValue) property.defaultValue->release(); -} - -/*! - \class QDeclarativeDomProperty - \internal - \brief The QDeclarativeDomProperty class represents one property assignment in the - QML DOM tree - - Properties in QML can be assigned QML \l {QDeclarativeDomValue}{values}. - - \sa QDeclarativeDomObject -*/ - -/*! - Construct an invalid QDeclarativeDomProperty. -*/ -QDeclarativeDomProperty::QDeclarativeDomProperty() -: d(new QDeclarativeDomPropertyPrivate) -{ -} - -/*! - Create a copy of \a other QDeclarativeDomProperty. -*/ -QDeclarativeDomProperty::QDeclarativeDomProperty(const QDeclarativeDomProperty &other) -: d(other.d) -{ -} - -/*! - Destroy the QDeclarativeDomProperty. -*/ -QDeclarativeDomProperty::~QDeclarativeDomProperty() -{ -} - -/*! - Assign \a other to this QDeclarativeDomProperty. -*/ -QDeclarativeDomProperty &QDeclarativeDomProperty::operator=(const QDeclarativeDomProperty &other) -{ - d = other.d; - return *this; -} - -/*! - Returns true if this is a valid QDeclarativeDomProperty, false otherwise. -*/ -bool QDeclarativeDomProperty::isValid() const -{ - return d->property != 0; -} - - -/*! - Return the name of this property. - - \qml -Text { - x: 10 - y: 10 - font.bold: true -} - \endqml - - As illustrated above, a property name can be a simple string, such as "x" or - "y", or a more complex "dot property", such as "font.bold". In both cases - the full name is returned ("x", "y" and "font.bold") by this method. - - For dot properties, a split version of the name can be accessed by calling - QDeclarativeDomProperty::propertyNameParts(). - - \sa QDeclarativeDomProperty::propertyNameParts() -*/ -QByteArray QDeclarativeDomProperty::propertyName() const -{ - return d->propertyName; -} - -/*! - Return the name of this property, split into multiple parts in the case - of dot properties. - - \qml -Text { - x: 10 - y: 10 - font.bold: true -} - \endqml - - For each of the properties shown above, this method would return ("x"), - ("y") and ("font", "bold"). - - \sa QDeclarativeDomProperty::propertyName() -*/ -QList QDeclarativeDomProperty::propertyNameParts() const -{ - if (d->propertyName.isEmpty()) return QList(); - else return d->propertyName.split('.'); -} - -/*! - Return true if this property is used as a default property in the QML - document. - - \code - -hello - \endcode - - The above two examples return the same DOM tree, except that the second has - the default property flag set on the text property. Observe that whether - or not a property has isDefaultProperty set is determined by how the - property is used, and not only by whether the property is the types default - property. -*/ -bool QDeclarativeDomProperty::isDefaultProperty() const -{ - return d->property && d->property->isDefault; -} - -/*! - Returns the QDeclarativeDomValue that is assigned to this property, or an invalid - QDeclarativeDomValue if no value is assigned. -*/ -QDeclarativeDomValue QDeclarativeDomProperty::value() const -{ - QDeclarativeDomValue rv; - if (d->property) { - rv.d->property = d->property; - if (d->property->values.count()) - rv.d->value = d->property->values.at(0); - else - rv.d->value = d->property->onValues.at(0); - rv.d->property->addref(); - rv.d->value->addref(); - } - return rv; -} - -/*! - Returns the position in the input data where the property ID startd, or -1 if - the property is invalid. -*/ -int QDeclarativeDomProperty::position() const -{ - if (d && d->property) { - return d->property->location.range.offset; - } else - return -1; -} - -/*! - Returns the length in the input data from where the property ID started upto - the end of it, or -1 if the property is invalid. -*/ -int QDeclarativeDomProperty::length() const -{ - if (d && d->property) - return d->property->location.range.length; - else - return -1; -} - -/*! - Construct an invalid QDeclarativeDomDynamicProperty. -*/ -QDeclarativeDomDynamicProperty::QDeclarativeDomDynamicProperty(): - d(new QDeclarativeDomDynamicPropertyPrivate) -{ -} - -/*! - Create a copy of \a other QDeclarativeDomDynamicProperty. -*/ -QDeclarativeDomDynamicProperty::QDeclarativeDomDynamicProperty(const QDeclarativeDomDynamicProperty &other): - d(other.d) -{ -} - -/*! - Destroy the QDeclarativeDomDynamicProperty. -*/ -QDeclarativeDomDynamicProperty::~QDeclarativeDomDynamicProperty() -{ -} - -/*! - Assign \a other to this QDeclarativeDomDynamicProperty. -*/ -QDeclarativeDomDynamicProperty &QDeclarativeDomDynamicProperty::operator=(const QDeclarativeDomDynamicProperty &other) -{ - d = other.d; - return *this; -} - -bool QDeclarativeDomDynamicProperty::isValid() const -{ - return d && d->valid; -} - -/*! - Return the name of this dynamic property. - - \qml -Item { - property int count: 10; -} - \endqml - - As illustrated above, a dynamic property name can have a name and a - default value ("10"). -*/ -QByteArray QDeclarativeDomDynamicProperty::propertyName() const -{ - if (isValid()) - return d->property.name; - else - return QByteArray(); -} - -/*! - Returns the type of the dynamic property. Note that when the property is an - alias property, this will return -1. Use QDeclarativeDomProperty::isAlias() to check - if the property is an alias. -*/ -int QDeclarativeDomDynamicProperty::propertyType() const -{ - if (isValid()) { - switch (d->property.type) { - case QDeclarativeParser::Object::DynamicProperty::Bool: - return QMetaType::type("bool"); - - case QDeclarativeParser::Object::DynamicProperty::Color: - return QMetaType::type("QColor"); - - case QDeclarativeParser::Object::DynamicProperty::Time: - return QMetaType::type("QTime"); - - case QDeclarativeParser::Object::DynamicProperty::Date: - return QMetaType::type("QDate"); - - case QDeclarativeParser::Object::DynamicProperty::DateTime: - return QMetaType::type("QDateTime"); - - case QDeclarativeParser::Object::DynamicProperty::Int: - return QMetaType::type("int"); - - case QDeclarativeParser::Object::DynamicProperty::Real: - return sizeof(qreal) == sizeof(double) ? QMetaType::type("double") : QMetaType::type("float"); - - case QDeclarativeParser::Object::DynamicProperty::String: - return QMetaType::type("QString"); - - case QDeclarativeParser::Object::DynamicProperty::Url: - return QMetaType::type("QUrl"); - - case QDeclarativeParser::Object::DynamicProperty::Variant: - return QMetaType::type("QVariant"); - - default: - break; - } - } - - return -1; -} - -QByteArray QDeclarativeDomDynamicProperty::propertyTypeName() const -{ - if (isValid()) - return d->property.customType; - - return QByteArray(); -} - -/*! - Return true if this property is used as a default property in the QML - document. - - \code - -hello - \endcode - - The above two examples return the same DOM tree, except that the second has - the default property flag set on the text property. Observe that whether - or not a property has isDefaultProperty set is determined by how the - property is used, and not only by whether the property is the types default - property. -*/ -bool QDeclarativeDomDynamicProperty::isDefaultProperty() const -{ - if (isValid()) - return d->property.isDefaultProperty; - else - return false; -} - -/*! - Returns the default value as a QDeclarativeDomProperty. -*/ -QDeclarativeDomProperty QDeclarativeDomDynamicProperty::defaultValue() const -{ - QDeclarativeDomProperty rp; - - if (isValid() && d->property.defaultValue) { - rp.d->property = d->property.defaultValue; - rp.d->propertyName = propertyName(); - rp.d->property->addref(); - } - - return rp; -} - -/*! - Returns true if this dynamic property is an alias for another property, - false otherwise. -*/ -bool QDeclarativeDomDynamicProperty::isAlias() const -{ - if (isValid()) - return d->property.type == QDeclarativeParser::Object::DynamicProperty::Alias; - else - return false; -} - -/*! - Returns the position in the input data where the property ID startd, or 0 if - the property is invalid. -*/ -int QDeclarativeDomDynamicProperty::position() const -{ - if (isValid()) { - return d->property.location.range.offset; - } else - return -1; -} - -/*! - Returns the length in the input data from where the property ID started upto - the end of it, or 0 if the property is invalid. -*/ -int QDeclarativeDomDynamicProperty::length() const -{ - if (isValid()) - return d->property.location.range.length; - else - return -1; -} - -QDeclarativeDomObjectPrivate::QDeclarativeDomObjectPrivate() -: object(0) -{ -} - -QDeclarativeDomObjectPrivate::~QDeclarativeDomObjectPrivate() -{ - if (object) object->release(); -} - -QDeclarativeDomObjectPrivate::Properties -QDeclarativeDomObjectPrivate::properties() const -{ - Properties rv; - - for (QHash::ConstIterator iter = - object->properties.begin(); - iter != object->properties.end(); - ++iter) { - - rv << properties(*iter); - - } - return rv; -} - -QDeclarativeDomObjectPrivate::Properties -QDeclarativeDomObjectPrivate::properties(QDeclarativeParser::Property *property) const -{ - Properties rv; - - if (property->value) { - - for (QHash::ConstIterator iter = - property->value->properties.begin(); - iter != property->value->properties.end(); - ++iter) { - - rv << properties(*iter); - - } - - QByteArray name(property->name + '.'); - for (Properties::Iterator iter = rv.begin(); iter != rv.end(); ++iter) - iter->second.prepend(name); - - } else { - rv << qMakePair(property, property->name); - } - - return rv; -} - -/*! - \class QDeclarativeDomObject - \internal - \brief The QDeclarativeDomObject class represents an object instantiation. - - Each object instantiated in a QML file has a corresponding QDeclarativeDomObject - node in the QML DOM. - - In addition to the type information that determines the object to - instantiate, QDeclarativeDomObject's also have a set of associated QDeclarativeDomProperty's. - Each QDeclarativeDomProperty represents a QML property assignment on the instantiated - object. For example, - - \qml -QGraphicsWidget { - opacity: 0.5 - size: "100x100" -} - \endqml - - describes a single QDeclarativeDomObject - "QGraphicsWidget" - with two properties, - "opacity" and "size". Obviously QGraphicsWidget has many more properties than just - these two, but the QML DOM representation only contains those assigned - values (or bindings) in the QML file. -*/ - -/*! - Construct an invalid QDeclarativeDomObject. -*/ -QDeclarativeDomObject::QDeclarativeDomObject() -: d(new QDeclarativeDomObjectPrivate) -{ -} - -/*! - Create a copy of \a other QDeclarativeDomObject. -*/ -QDeclarativeDomObject::QDeclarativeDomObject(const QDeclarativeDomObject &other) -: d(other.d) -{ -} - -/*! - Destroy the QDeclarativeDomObject. -*/ -QDeclarativeDomObject::~QDeclarativeDomObject() -{ -} - -/*! - Assign \a other to this QDeclarativeDomObject. -*/ -QDeclarativeDomObject &QDeclarativeDomObject::operator=(const QDeclarativeDomObject &other) -{ - d = other.d; - return *this; -} - -/*! - Returns true if this is a valid QDeclarativeDomObject, false otherwise. -*/ -bool QDeclarativeDomObject::isValid() const -{ - return d->object != 0; -} - -/*! - Returns the fully-qualified type name of this object. - - For example, the type of this object would be "Qt/4.6/Rectangle". - \qml -Rectangle { } - \endqml -*/ -QByteArray QDeclarativeDomObject::objectType() const -{ - if (d->object) return d->object->typeName; - else return QByteArray(); -} - -/*! - Returns the type name as referenced in the qml file. - - For example, the type of this object would be "Rectangle". - \qml -Rectangle { } - \endqml -*/ -QByteArray QDeclarativeDomObject::objectClassName() const -{ - if (d->object) - return d->object->className; - else - return QByteArray(); -} - -int QDeclarativeDomObject::objectTypeMajorVersion() const -{ - if (d->object) - return d->object->majorVersion; - else - return -1; -} - -int QDeclarativeDomObject::objectTypeMinorVersion() const -{ - if (d->object) - return d->object->minorVersion; - else - return -1; -} - -/*! - Returns the QML id assigned to this object, or an empty QByteArray if no id - has been assigned. - - For example, the object id of this object would be "MyText". - \qml -Text { id: myText } - \endqml -*/ -QString QDeclarativeDomObject::objectId() const -{ - if (d->object) { - return d->object->id; - } else { - return QString(); - } -} - -/*! - Returns the list of assigned properties on this object. - - In the following example, "text" and "x" properties would be returned. - \qml -Text { - text: "Hello world!" - x: 100 -} - \endqml -*/ -QList QDeclarativeDomObject::properties() const -{ - QList rv; - - if (!d->object || isComponent()) - return rv; - - QDeclarativeDomObjectPrivate::Properties properties = d->properties(); - for (int ii = 0; ii < properties.count(); ++ii) { - - QDeclarativeDomProperty domProperty; - domProperty.d->property = properties.at(ii).first; - domProperty.d->property->addref(); - domProperty.d->propertyName = properties.at(ii).second; - rv << domProperty; - - } - - if (d->object->defaultProperty) { - QDeclarativeDomProperty domProperty; - domProperty.d->property = d->object->defaultProperty; - domProperty.d->property->addref(); - domProperty.d->propertyName = d->object->defaultProperty->name; - rv << domProperty; - } - - return rv; -} - -/*! - Returns the object's \a name property if a value has been assigned to - it, or an invalid QDeclarativeDomProperty otherwise. - - In the example below, \c {object.property("source")} would return a valid - QDeclarativeDomProperty, and \c {object.property("tile")} an invalid QDeclarativeDomProperty. - - \qml -Image { source: "sample.jpg" } - \endqml -*/ -QDeclarativeDomProperty QDeclarativeDomObject::property(const QByteArray &name) const -{ - QList props = properties(); - for (int ii = 0; ii < props.count(); ++ii) - if (props.at(ii).propertyName() == name) - return props.at(ii); - return QDeclarativeDomProperty(); -} - -QList QDeclarativeDomObject::dynamicProperties() const -{ - QList properties; - - for (int i = 0; i < d->object->dynamicProperties.size(); ++i) { - QDeclarativeDomDynamicProperty p; - p.d = new QDeclarativeDomDynamicPropertyPrivate; - p.d->property = d->object->dynamicProperties.at(i); - p.d->valid = true; - - if (p.d->property.defaultValue) - p.d->property.defaultValue->addref(); - - properties.append(p); - } - - return properties; -} - -QDeclarativeDomDynamicProperty QDeclarativeDomObject::dynamicProperty(const QByteArray &name) const -{ - QDeclarativeDomDynamicProperty p; - - if (!isValid()) - return p; - - for (int i = 0; i < d->object->dynamicProperties.size(); ++i) { - if (d->object->dynamicProperties.at(i).name == name) { - p.d = new QDeclarativeDomDynamicPropertyPrivate; - p.d->property = d->object->dynamicProperties.at(i); - if (p.d->property.defaultValue) p.d->property.defaultValue->addref(); - p.d->valid = true; - } - } - - return p; -} - -/*! - Returns true if this object is a custom type. Custom types are special - types that allow embeddeding non-QML data, such as SVG or HTML data, - directly into QML files. - - \note Currently this method will always return false, and is a placekeeper - for future functionality. - - \sa QDeclarativeDomObject::customTypeData() -*/ -bool QDeclarativeDomObject::isCustomType() const -{ - return false; -} - -/*! - If this object represents a custom type, returns the data associated with - the custom type, otherwise returns an empty QByteArray(). - QDeclarativeDomObject::isCustomType() can be used to check if this object represents - a custom type. -*/ -QByteArray QDeclarativeDomObject::customTypeData() const -{ - return QByteArray(); -} - -/*! - Returns true if this object is a sub-component object. Sub-component - objects can be converted into QDeclarativeDomComponent instances by calling - QDeclarativeDomObject::toComponent(). - - \sa QDeclarativeDomObject::toComponent() -*/ -bool QDeclarativeDomObject::isComponent() const -{ - return (d->object && (d->object->typeName == "Qt/Component" || d->object->typeName == "QtQuick/Component")); -} - -/*! - Returns a QDeclarativeDomComponent for this object if it is a sub-component, or - an invalid QDeclarativeDomComponent if not. QDeclarativeDomObject::isComponent() can be used - to check if this object represents a sub-component. - - \sa QDeclarativeDomObject::isComponent() -*/ -QDeclarativeDomComponent QDeclarativeDomObject::toComponent() const -{ - QDeclarativeDomComponent rv; - if (isComponent()) - rv.d = d; - return rv; -} - -/*! - Returns the position in the input data where the property assignment started -, or -1 if the property is invalid. -*/ -int QDeclarativeDomObject::position() const -{ - if (d && d->object) - return d->object->location.range.offset; - else - return -1; -} - -/*! - Returns the length in the input data from where the property assignment star -ted upto the end of it, or -1 if the property is invalid. -*/ -int QDeclarativeDomObject::length() const -{ - if (d && d->object) - return d->object->location.range.length; - else - return -1; -} - -// Returns the URL of the type, if it is an external type, or an empty URL if -// not -QUrl QDeclarativeDomObject::url() const -{ - if (d && d->object) - return d->object->url; - else - return QUrl(); -} - -QDeclarativeDomBasicValuePrivate::QDeclarativeDomBasicValuePrivate() -: value(0) -{ -} - -QDeclarativeDomBasicValuePrivate::~QDeclarativeDomBasicValuePrivate() -{ - if (value) value->release(); -} - -/*! - \class QDeclarativeDomValueLiteral - \internal - \brief The QDeclarativeDomValueLiteral class represents a literal value. - - A literal value is a simple value, written inline with the QML. In the - example below, the "x", "y" and "color" properties are being assigned - literal values. - - \qml -Rectangle { - x: 10 - y: 10 - color: "red" -} - \endqml -*/ - -/*! - Construct an empty QDeclarativeDomValueLiteral. -*/ -QDeclarativeDomValueLiteral::QDeclarativeDomValueLiteral(): - d(new QDeclarativeDomBasicValuePrivate) -{ -} - -/*! - Create a copy of \a other QDeclarativeDomValueLiteral. -*/ -QDeclarativeDomValueLiteral::QDeclarativeDomValueLiteral(const QDeclarativeDomValueLiteral &other) -: d(other.d) -{ -} - -/*! - Destroy the QDeclarativeDomValueLiteral. -*/ -QDeclarativeDomValueLiteral::~QDeclarativeDomValueLiteral() -{ -} - -/*! - Assign \a other to this QDeclarativeDomValueLiteral. -*/ -QDeclarativeDomValueLiteral &QDeclarativeDomValueLiteral::operator=(const QDeclarativeDomValueLiteral &other) -{ - d = other.d; - return *this; -} - -/*! - Return the literal value. - - In the example below, the literal value will be the string "10". - \qml -Rectangle { x: 10 } - \endqml -*/ -QString QDeclarativeDomValueLiteral::literal() const -{ - if (d->value) return d->value->primitive(); - else return QString(); -} - -/*! - \class QDeclarativeDomValueBinding - \internal - \brief The QDeclarativeDomValueBinding class represents a property binding. - - A property binding is an ECMAScript expression assigned to a property. In - the example below, the "x" property is being assigned a property binding. - - \qml -Rectangle { x: Other.x } - \endqml -*/ - -/*! - Construct an empty QDeclarativeDomValueBinding. -*/ -QDeclarativeDomValueBinding::QDeclarativeDomValueBinding(): - d(new QDeclarativeDomBasicValuePrivate) -{ -} - -/*! - Create a copy of \a other QDeclarativeDomValueBinding. -*/ -QDeclarativeDomValueBinding::QDeclarativeDomValueBinding(const QDeclarativeDomValueBinding &other) -: d(other.d) -{ -} - -/*! - Destroy the QDeclarativeDomValueBinding. -*/ -QDeclarativeDomValueBinding::~QDeclarativeDomValueBinding() -{ -} - -/*! - Assign \a other to this QDeclarativeDomValueBinding. -*/ -QDeclarativeDomValueBinding &QDeclarativeDomValueBinding::operator=(const QDeclarativeDomValueBinding &other) -{ - d = other.d; - return *this; -} - -/*! - Return the binding expression. - - In the example below, the string "Other.x" will be returned. - \qml -Rectangle { x: Other.x } - \endqml -*/ -QString QDeclarativeDomValueBinding::binding() const -{ - if (d->value) - return d->value->value.asScript(); - else - return QString(); -} - -/*! - \class QDeclarativeDomValueValueSource - \internal - \brief The QDeclarativeDomValueValueSource class represents a value source assignment value. - - In QML, value sources are special value generating types that may be - assigned to properties. Value sources inherit the QDeclarativePropertyValueSource - class. In the example below, the "x" property is being assigned the - NumberAnimation value source. - - \qml -Rectangle { - x: NumberAnimation { - from: 0 - to: 100 - loops: Animation.Infinite - } -} - \endqml -*/ - -/*! - Construct an empty QDeclarativeDomValueValueSource. -*/ -QDeclarativeDomValueValueSource::QDeclarativeDomValueValueSource(): - d(new QDeclarativeDomBasicValuePrivate) -{ -} - -/*! - Create a copy of \a other QDeclarativeDomValueValueSource. -*/ -QDeclarativeDomValueValueSource::QDeclarativeDomValueValueSource(const QDeclarativeDomValueValueSource &other) -: d(other.d) -{ -} - -/*! - Destroy the QDeclarativeDomValueValueSource. -*/ -QDeclarativeDomValueValueSource::~QDeclarativeDomValueValueSource() -{ -} - -/*! - Assign \a other to this QDeclarativeDomValueValueSource. -*/ -QDeclarativeDomValueValueSource &QDeclarativeDomValueValueSource::operator=(const QDeclarativeDomValueValueSource &other) -{ - d = other.d; - return *this; -} - -/*! - Return the value source object. - - In the example below, an object representing the NumberAnimation will be - returned. - \qml -Rectangle { - x: NumberAnimation { - from: 0 - to: 100 - loops: Animation.Infinite - } -} - \endqml -*/ -QDeclarativeDomObject QDeclarativeDomValueValueSource::object() const -{ - QDeclarativeDomObject rv; - if (d->value) { - rv.d->object = d->value->object; - rv.d->object->addref(); - } - return rv; -} - -/*! - \class QDeclarativeDomValueValueInterceptor - \internal - \brief The QDeclarativeDomValueValueInterceptor class represents a value interceptor assignment value. - - In QML, value interceptor are special write-intercepting types that may be - assigned to properties. Value interceptor inherit the QDeclarativePropertyValueInterceptor - class. In the example below, the "x" property is being assigned the - Behavior value interceptor. - - \qml -Rectangle { - Behavior on x { NumberAnimation { duration: 500 } } -} - \endqml -*/ - -/*! - Construct an empty QDeclarativeDomValueValueInterceptor. -*/ -QDeclarativeDomValueValueInterceptor::QDeclarativeDomValueValueInterceptor(): - d(new QDeclarativeDomBasicValuePrivate) -{ -} - -/*! - Create a copy of \a other QDeclarativeDomValueValueInterceptor. -*/ -QDeclarativeDomValueValueInterceptor::QDeclarativeDomValueValueInterceptor(const QDeclarativeDomValueValueInterceptor &other) -: d(other.d) -{ -} - -/*! - Destroy the QDeclarativeDomValueValueInterceptor. -*/ -QDeclarativeDomValueValueInterceptor::~QDeclarativeDomValueValueInterceptor() -{ -} - -/*! - Assign \a other to this QDeclarativeDomValueValueInterceptor. -*/ -QDeclarativeDomValueValueInterceptor &QDeclarativeDomValueValueInterceptor::operator=(const QDeclarativeDomValueValueInterceptor &other) -{ - d = other.d; - return *this; -} - -/*! - Return the value interceptor object. - - In the example below, an object representing the Behavior will be - returned. - \qml -Rectangle { - Behavior on x { NumberAnimation { duration: 500 } } -} - \endqml -*/ -QDeclarativeDomObject QDeclarativeDomValueValueInterceptor::object() const -{ - QDeclarativeDomObject rv; - if (d->value) { - rv.d->object = d->value->object; - rv.d->object->addref(); - } - return rv; -} - -QDeclarativeDomValuePrivate::QDeclarativeDomValuePrivate() -: property(0), value(0) -{ -} - -QDeclarativeDomValuePrivate::~QDeclarativeDomValuePrivate() -{ - if (property) property->release(); - if (value) value->release(); -} - -/*! - \class QDeclarativeDomValue - \internal - \brief The QDeclarativeDomValue class represents a generic Qml value. - - QDeclarativeDomValue's can be assigned to QML \l {QDeclarativeDomProperty}{properties}. In - QML, properties can be assigned various different values, including basic - literals, property bindings, property value sources, objects and lists of - values. The QDeclarativeDomValue class allows a programmer to determine the specific - value type being assigned and access more detailed information through a - corresponding value type class. - - For example, in the following example, - - \qml -Text { - text: "Hello World!" - y: Other.y -} - \endqml - - The text property is being assigned a literal, and the y property a property - binding. To output the values assigned to the text and y properties in the - above example from C++, - - \code - QDeclarativeDomDocument document; - QDeclarativeDomObject root = document.rootObject(); - - QDeclarativeDomProperty text = root.property("text"); - if (text.value().isLiteral()) { - QDeclarativeDomValueLiteral literal = text.value().toLiteral(); - qDebug() << literal.literal(); - } - - QDeclarativeDomProperty y = root.property("y"); - if (y.value().isBinding()) { - QDeclarativeDomValueBinding binding = y.value().toBinding(); - qDebug() << binding.binding(); - } - \endcode -*/ - -/*! - Construct an invalid QDeclarativeDomValue. -*/ -QDeclarativeDomValue::QDeclarativeDomValue() -: d(new QDeclarativeDomValuePrivate) -{ -} - -/*! - Create a copy of \a other QDeclarativeDomValue. -*/ -QDeclarativeDomValue::QDeclarativeDomValue(const QDeclarativeDomValue &other) -: d(other.d) -{ -} - -/*! - Destroy the QDeclarativeDomValue -*/ -QDeclarativeDomValue::~QDeclarativeDomValue() -{ -} - -/*! - Assign \a other to this QDeclarativeDomValue. -*/ -QDeclarativeDomValue &QDeclarativeDomValue::operator=(const QDeclarativeDomValue &other) -{ - d = other.d; - return *this; -} - -/*! - \enum QDeclarativeDomValue::Type - - The type of the QDeclarativeDomValue node. - - \value Invalid The QDeclarativeDomValue is invalid. - \value Literal The QDeclarativeDomValue is a literal value assignment. Use QDeclarativeDomValue::toLiteral() to access the type instance. - \value PropertyBinding The QDeclarativeDomValue is a property binding. Use QDeclarativeDomValue::toBinding() to access the type instance. - \value ValueSource The QDeclarativeDomValue is a property value source. Use QDeclarativeDomValue::toValueSource() to access the type instance. - \value ValueInterceptor The QDeclarativeDomValue is a property value interceptor. Use QDeclarativeDomValue::toValueInterceptor() to access the type instance. - \value Object The QDeclarativeDomValue is an object assignment. Use QDeclarativeDomValue::toObject() to access the type instnace. - \value List The QDeclarativeDomValue is a list of other values. Use QDeclarativeDomValue::toList() to access the type instance. -*/ - -/*! - Returns the type of this QDeclarativeDomValue. -*/ -QDeclarativeDomValue::Type QDeclarativeDomValue::type() const -{ - if (d->property) - if (QDeclarativeMetaType::isList(d->property->type) || - (d->property && (d->property->values.count() + d->property->onValues.count()) > 1)) - return List; - - QDeclarativeParser::Value *value = d->value; - if (!value && !d->property) - return Invalid; - - switch(value->type) { - case QDeclarativeParser::Value::Unknown: - return Invalid; - case QDeclarativeParser::Value::Literal: - return Literal; - case QDeclarativeParser::Value::PropertyBinding: - return PropertyBinding; - case QDeclarativeParser::Value::ValueSource: - return ValueSource; - case QDeclarativeParser::Value::ValueInterceptor: - return ValueInterceptor; - case QDeclarativeParser::Value::CreatedObject: - return Object; - case QDeclarativeParser::Value::SignalObject: - return Invalid; - case QDeclarativeParser::Value::SignalExpression: - return Literal; - case QDeclarativeParser::Value::Id: - return Literal; - } - return Invalid; -} - -/*! - Returns true if this is an invalid value, otherwise false. -*/ -bool QDeclarativeDomValue::isInvalid() const -{ - return type() == Invalid; -} - -/*! - Returns true if this is a literal value, otherwise false. -*/ -bool QDeclarativeDomValue::isLiteral() const -{ - return type() == Literal; -} - -/*! - Returns true if this is a property binding value, otherwise false. -*/ -bool QDeclarativeDomValue::isBinding() const -{ - return type() == PropertyBinding; -} - -/*! - Returns true if this is a value source value, otherwise false. -*/ -bool QDeclarativeDomValue::isValueSource() const -{ - return type() == ValueSource; -} - -/*! - Returns true if this is a value interceptor value, otherwise false. -*/ -bool QDeclarativeDomValue::isValueInterceptor() const -{ - return type() == ValueInterceptor; -} - -/*! - Returns true if this is an object value, otherwise false. -*/ -bool QDeclarativeDomValue::isObject() const -{ - return type() == Object; -} - -/*! - Returns true if this is a list value, otherwise false. -*/ -bool QDeclarativeDomValue::isList() const -{ - return type() == List; -} - -/*! - Returns a QDeclarativeDomValueLiteral if this value is a literal type, otherwise - returns an invalid QDeclarativeDomValueLiteral. - - \sa QDeclarativeDomValue::type() -*/ -QDeclarativeDomValueLiteral QDeclarativeDomValue::toLiteral() const -{ - QDeclarativeDomValueLiteral rv; - if (type() == Literal) { - rv.d->value = d->value; - rv.d->value->addref(); - } - return rv; -} - -/*! - Returns a QDeclarativeDomValueBinding if this value is a property binding type, - otherwise returns an invalid QDeclarativeDomValueBinding. - - \sa QDeclarativeDomValue::type() -*/ -QDeclarativeDomValueBinding QDeclarativeDomValue::toBinding() const -{ - QDeclarativeDomValueBinding rv; - if (type() == PropertyBinding) { - rv.d->value = d->value; - rv.d->value->addref(); - } - return rv; -} - -/*! - Returns a QDeclarativeDomValueValueSource if this value is a property value source - type, otherwise returns an invalid QDeclarativeDomValueValueSource. - - \sa QDeclarativeDomValue::type() -*/ -QDeclarativeDomValueValueSource QDeclarativeDomValue::toValueSource() const -{ - QDeclarativeDomValueValueSource rv; - if (type() == ValueSource) { - rv.d->value = d->value; - rv.d->value->addref(); - } - return rv; -} - -/*! - Returns a QDeclarativeDomValueValueInterceptor if this value is a property value interceptor - type, otherwise returns an invalid QDeclarativeDomValueValueInterceptor. - - \sa QDeclarativeDomValue::type() -*/ -QDeclarativeDomValueValueInterceptor QDeclarativeDomValue::toValueInterceptor() const -{ - QDeclarativeDomValueValueInterceptor rv; - if (type() == ValueInterceptor) { - rv.d->value = d->value; - rv.d->value->addref(); - } - return rv; -} - -/*! - Returns a QDeclarativeDomObject if this value is an object assignment type, otherwise - returns an invalid QDeclarativeDomObject. - - \sa QDeclarativeDomValue::type() -*/ -QDeclarativeDomObject QDeclarativeDomValue::toObject() const -{ - QDeclarativeDomObject rv; - if (type() == Object) { - rv.d->object = d->value->object; - rv.d->object->addref(); - } - return rv; -} - -/*! - Returns a QDeclarativeDomList if this value is a list type, otherwise returns an - invalid QDeclarativeDomList. - - \sa QDeclarativeDomValue::type() -*/ -QDeclarativeDomList QDeclarativeDomValue::toList() const -{ - QDeclarativeDomList rv; - if (type() == List) { - rv.d = d; - } - return rv; -} - -/*! - Returns the position in the input data where the property value startd, or -1 - if the value is invalid. -*/ -int QDeclarativeDomValue::position() const -{ - if (type() == Invalid) - return -1; - else - return d->value->location.range.offset; -} - -/*! - Returns the length in the input data from where the property value started u -pto the end of it, or -1 if the value is invalid. -*/ -int QDeclarativeDomValue::length() const -{ - if (type() == Invalid) - return -1; - else - return d->value->location.range.length; -} - -/*! - \class QDeclarativeDomList - \internal - \brief The QDeclarativeDomList class represents a list of values assigned to a QML property. - - Lists of values can be assigned to properties. For example, the following - example assigns multiple objects to Item's "children" property - \qml -Item { - children: [ - Text { }, - Rectangle { } - ] -} - \endqml - - Lists can also be implicitly created by assigning multiple - \l {QDeclarativeDomValueValueSource}{value sources} or constants to a property. - \qml -Item { - x: 10 - x: NumberAnimation { - running: false - from: 0 - to: 100 - } -} - \endqml -*/ - -/*! - Construct an empty QDeclarativeDomList. -*/ -QDeclarativeDomList::QDeclarativeDomList() -{ -} - -/*! - Create a copy of \a other QDeclarativeDomList. -*/ -QDeclarativeDomList::QDeclarativeDomList(const QDeclarativeDomList &other) -: d(other.d) -{ -} - -/*! - Destroy the QDeclarativeDomList. -*/ -QDeclarativeDomList::~QDeclarativeDomList() -{ -} - -/*! - Assign \a other to this QDeclarativeDomList. -*/ -QDeclarativeDomList &QDeclarativeDomList::operator=(const QDeclarativeDomList &other) -{ - d = other.d; - return *this; -} - -/*! - Returns the list of QDeclarativeDomValue's. -*/ -QList QDeclarativeDomList::values() const -{ - QList rv; - if (!d->property) - return rv; - - for (int ii = 0; ii < d->property->values.count(); ++ii) { - QDeclarativeDomValue v; - v.d->value = d->property->values.at(ii); - v.d->value->addref(); - rv << v; - } - - for (int ii = 0; ii < d->property->onValues.count(); ++ii) { - QDeclarativeDomValue v; - v.d->value = d->property->onValues.at(ii); - v.d->value->addref(); - rv << v; - } - - return rv; -} - -/*! - Returns the position in the input data where the list started, or -1 if - the property is invalid. -*/ -int QDeclarativeDomList::position() const -{ - if (d && d->property) { - return d->property->listValueRange.offset; - } else - return -1; -} - -/*! - Returns the length in the input data from where the list started upto - the end of it, or 0 if the property is invalid. -*/ -int QDeclarativeDomList::length() const -{ - if (d && d->property) - return d->property->listValueRange.length; - else - return -1; -} - -/*! - Returns a list of positions of the commas in the QML file. -*/ -QList QDeclarativeDomList:: commaPositions() const -{ - if (d && d->property) - return d->property->listCommaPositions; - else - return QList(); -} - -/*! - \class QDeclarativeDomComponent - \internal - \brief The QDeclarativeDomComponent class represents sub-component within a QML document. - - Sub-components are QDeclarativeComponents defined within a QML document. The - following example shows the definition of a sub-component with the id - "listDelegate". - - \qml -Item { - Component { - id: listDelegate - Text { - text: modelData.text - } - } -} - \endqml - - Like QDeclarativeDomDocument's, components contain a single root object. -*/ - -/*! - Construct an empty QDeclarativeDomComponent. -*/ -QDeclarativeDomComponent::QDeclarativeDomComponent() -{ -} - -/*! - Create a copy of \a other QDeclarativeDomComponent. -*/ -QDeclarativeDomComponent::QDeclarativeDomComponent(const QDeclarativeDomComponent &other) -: QDeclarativeDomObject(other) -{ -} - -/*! - Destroy the QDeclarativeDomComponent. -*/ -QDeclarativeDomComponent::~QDeclarativeDomComponent() -{ -} - -/*! - Assign \a other to this QDeclarativeDomComponent. -*/ -QDeclarativeDomComponent &QDeclarativeDomComponent::operator=(const QDeclarativeDomComponent &other) -{ - static_cast(*this) = other; - return *this; -} - -/*! - Returns the component's root object. - - In the example below, the root object is the "Text" object. - \qml -Item { - Component { - id: listDelegate - Text { - text: modelData.text - } - } -} - \endqml -*/ -QDeclarativeDomObject QDeclarativeDomComponent::componentRoot() const -{ - QDeclarativeDomObject rv; - if (d->object) { - QDeclarativeParser::Object *obj = 0; - if (d->object->defaultProperty && - d->object->defaultProperty->values.count() == 1 && - d->object->defaultProperty->values.at(0)->object) - obj = d->object->defaultProperty->values.at(0)->object; - - if (obj) { - rv.d->object = obj; - rv.d->object->addref(); - } - } - - return rv; -} - -QDeclarativeDomImportPrivate::QDeclarativeDomImportPrivate() -: type(File) -{ -} - -QDeclarativeDomImportPrivate::~QDeclarativeDomImportPrivate() -{ -} - -/*! - \class QDeclarativeDomImport - \internal - \brief The QDeclarativeDomImport class represents an import statement. -*/ - -/*! - Construct an empty QDeclarativeDomImport. -*/ -QDeclarativeDomImport::QDeclarativeDomImport() -: d(new QDeclarativeDomImportPrivate) -{ -} - -/*! - Create a copy of \a other QDeclarativeDomImport. -*/ -QDeclarativeDomImport::QDeclarativeDomImport(const QDeclarativeDomImport &other) -: d(other.d) -{ -} - -/*! - Destroy the QDeclarativeDomImport. -*/ -QDeclarativeDomImport::~QDeclarativeDomImport() -{ -} - -/*! - Assign \a other to this QDeclarativeDomImport. -*/ -QDeclarativeDomImport &QDeclarativeDomImport::operator=(const QDeclarativeDomImport &other) -{ - d = other.d; - return *this; -} - -/*! - Returns the type of the import. - */ -QDeclarativeDomImport::Type QDeclarativeDomImport::type() const -{ - return static_cast(d->type); -} - -/*! - Returns the URI of the import (e.g. 'subdir' or 'com.nokia.Qt') - */ -QString QDeclarativeDomImport::uri() const -{ - return d->uri; -} - -/*! - Returns the version specified by the import. An empty string if no version was specified. - */ -QString QDeclarativeDomImport::version() const -{ - return d->version; -} - -/*! - Returns the (optional) qualifier string (the token following the 'as' keyword) of the import. - */ -QString QDeclarativeDomImport::qualifier() const -{ - return d->qualifier; -} - -QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativedom_p.h b/src/declarative/qml/qdeclarativedom_p.h deleted file mode 100644 index 64300d47e7..0000000000 --- a/src/declarative/qml/qdeclarativedom_p.h +++ /dev/null @@ -1,362 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QDECLARATIVEDOM_P_H -#define QDECLARATIVEDOM_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 "qdeclarativeerror.h" - -#include -#include - -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Declarative) - -class QString; -class QByteArray; -class QDeclarativeDomObject; -class QDeclarativeDomList; -class QDeclarativeDomValue; -class QDeclarativeEngine; -class QDeclarativeDomComponent; -class QDeclarativeDomImport; -class QIODevice; - -class QDeclarativeDomDocumentPrivate; - -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDomDocument -{ -public: - QDeclarativeDomDocument(); - QDeclarativeDomDocument(const QDeclarativeDomDocument &); - ~QDeclarativeDomDocument(); - QDeclarativeDomDocument &operator=(const QDeclarativeDomDocument &); - - QList imports() const; - - QList errors() const; - bool load(QDeclarativeEngine *, const QByteArray &, const QUrl & = QUrl()); - - QDeclarativeDomObject rootObject() const; - -private: - QSharedDataPointer d; -}; - -class QDeclarativeDomPropertyPrivate; -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDomProperty -{ -public: - QDeclarativeDomProperty(); - QDeclarativeDomProperty(const QDeclarativeDomProperty &); - ~QDeclarativeDomProperty(); - QDeclarativeDomProperty &operator=(const QDeclarativeDomProperty &); - - bool isValid() const; - - QByteArray propertyName() const; - QList propertyNameParts() const; - - bool isDefaultProperty() const; - - QDeclarativeDomValue value() const; - - int position() const; - int length() const; - -private: - friend class QDeclarativeDomObject; - friend class QDeclarativeDomDynamicProperty; - QSharedDataPointer d; -}; - -class QDeclarativeDomDynamicPropertyPrivate; -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDomDynamicProperty -{ -public: - QDeclarativeDomDynamicProperty(); - QDeclarativeDomDynamicProperty(const QDeclarativeDomDynamicProperty &); - ~QDeclarativeDomDynamicProperty(); - QDeclarativeDomDynamicProperty &operator=(const QDeclarativeDomDynamicProperty &); - - bool isValid() const; - - QByteArray propertyName() const; - int propertyType() const; - QByteArray propertyTypeName() const; - - bool isDefaultProperty() const; - QDeclarativeDomProperty defaultValue() const; - - bool isAlias() const; - - int position() const; - int length() const; - -private: - friend class QDeclarativeDomObject; - QSharedDataPointer d; -}; - -class QDeclarativeDomObjectPrivate; -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDomObject -{ -public: - QDeclarativeDomObject(); - QDeclarativeDomObject(const QDeclarativeDomObject &); - ~QDeclarativeDomObject(); - QDeclarativeDomObject &operator=(const QDeclarativeDomObject &); - - bool isValid() const; - - QByteArray objectType() const; - QByteArray objectClassName() const; - - int objectTypeMajorVersion() const; - int objectTypeMinorVersion() const; - - QString objectId() const; - - QList properties() const; - QDeclarativeDomProperty property(const QByteArray &) const; - - QList dynamicProperties() const; - QDeclarativeDomDynamicProperty dynamicProperty(const QByteArray &) const; - - bool isCustomType() const; - QByteArray customTypeData() const; - - bool isComponent() const; - QDeclarativeDomComponent toComponent() const; - - int position() const; - int length() const; - - QUrl url() const; -private: - friend class QDeclarativeDomDocument; - friend class QDeclarativeDomComponent; - friend class QDeclarativeDomValue; - friend class QDeclarativeDomValueValueSource; - friend class QDeclarativeDomValueValueInterceptor; - QSharedDataPointer d; -}; - -class QDeclarativeDomValuePrivate; -class QDeclarativeDomBasicValuePrivate; -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDomValueLiteral -{ -public: - QDeclarativeDomValueLiteral(); - QDeclarativeDomValueLiteral(const QDeclarativeDomValueLiteral &); - ~QDeclarativeDomValueLiteral(); - QDeclarativeDomValueLiteral &operator=(const QDeclarativeDomValueLiteral &); - - QString literal() const; - -private: - friend class QDeclarativeDomValue; - QSharedDataPointer d; -}; - -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDomValueBinding -{ -public: - QDeclarativeDomValueBinding(); - QDeclarativeDomValueBinding(const QDeclarativeDomValueBinding &); - ~QDeclarativeDomValueBinding(); - QDeclarativeDomValueBinding &operator=(const QDeclarativeDomValueBinding &); - - QString binding() const; - -private: - friend class QDeclarativeDomValue; - QSharedDataPointer d; -}; - -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDomValueValueSource -{ -public: - QDeclarativeDomValueValueSource(); - QDeclarativeDomValueValueSource(const QDeclarativeDomValueValueSource &); - ~QDeclarativeDomValueValueSource(); - QDeclarativeDomValueValueSource &operator=(const QDeclarativeDomValueValueSource &); - - QDeclarativeDomObject object() const; - -private: - friend class QDeclarativeDomValue; - QSharedDataPointer d; -}; - -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDomValueValueInterceptor -{ -public: - QDeclarativeDomValueValueInterceptor(); - QDeclarativeDomValueValueInterceptor(const QDeclarativeDomValueValueInterceptor &); - ~QDeclarativeDomValueValueInterceptor(); - QDeclarativeDomValueValueInterceptor &operator=(const QDeclarativeDomValueValueInterceptor &); - - QDeclarativeDomObject object() const; - -private: - friend class QDeclarativeDomValue; - QSharedDataPointer d; -}; - - -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDomComponent : public QDeclarativeDomObject -{ -public: - QDeclarativeDomComponent(); - QDeclarativeDomComponent(const QDeclarativeDomComponent &); - ~QDeclarativeDomComponent(); - QDeclarativeDomComponent &operator=(const QDeclarativeDomComponent &); - - QDeclarativeDomObject componentRoot() const; -}; - -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDomValue -{ -public: - enum Type { - Invalid, - Literal, - PropertyBinding, - ValueSource, - ValueInterceptor, - Object, - List - }; - - QDeclarativeDomValue(); - QDeclarativeDomValue(const QDeclarativeDomValue &); - ~QDeclarativeDomValue(); - QDeclarativeDomValue &operator=(const QDeclarativeDomValue &); - - Type type() const; - - bool isInvalid() const; - bool isLiteral() const; - bool isBinding() const; - bool isValueSource() const; - bool isValueInterceptor() const; - bool isObject() const; - bool isList() const; - - QDeclarativeDomValueLiteral toLiteral() const; - QDeclarativeDomValueBinding toBinding() const; - QDeclarativeDomValueValueSource toValueSource() const; - QDeclarativeDomValueValueInterceptor toValueInterceptor() const; - QDeclarativeDomObject toObject() const; - QDeclarativeDomList toList() const; - - int position() const; - int length() const; - -private: - friend class QDeclarativeDomProperty; - friend class QDeclarativeDomList; - QSharedDataPointer d; -}; - -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDomList -{ -public: - QDeclarativeDomList(); - QDeclarativeDomList(const QDeclarativeDomList &); - ~QDeclarativeDomList(); - QDeclarativeDomList &operator=(const QDeclarativeDomList &); - - QList values() const; - - int position() const; - int length() const; - - QList commaPositions() const; - -private: - friend class QDeclarativeDomValue; - QSharedDataPointer d; -}; - -class QDeclarativeDomImportPrivate; -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDomImport -{ -public: - enum Type { Library, File }; - - QDeclarativeDomImport(); - QDeclarativeDomImport(const QDeclarativeDomImport &); - ~QDeclarativeDomImport(); - QDeclarativeDomImport &operator=(const QDeclarativeDomImport &); - - Type type() const; - QString uri() const; - QString version() const; - QString qualifier() const; - -private: - friend class QDeclarativeDomDocument; - QSharedDataPointer d; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QDECLARATIVEDOM_P_H diff --git a/src/declarative/qml/qdeclarativedom_p_p.h b/src/declarative/qml/qdeclarativedom_p_p.h deleted file mode 100644 index 7ce99ec74d..0000000000 --- a/src/declarative/qml/qdeclarativedom_p_p.h +++ /dev/null @@ -1,157 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QDECLARATIVEDOM_P_P_H -#define QDECLARATIVEDOM_P_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 "private/qdeclarativeparser_p.h" - -#include - -QT_BEGIN_NAMESPACE - -class QDeclarativeDomDocumentPrivate : public QSharedData -{ -public: - QDeclarativeDomDocumentPrivate(); - QDeclarativeDomDocumentPrivate(const QDeclarativeDomDocumentPrivate &o) - : QSharedData(o) { qFatal("Not impl"); } - ~QDeclarativeDomDocumentPrivate(); - - QList errors; - QList imports; - QDeclarativeParser::Object *root; - QList automaticSemicolonOffsets; -}; - -class QDeclarativeDomObjectPrivate : public QSharedData -{ -public: - QDeclarativeDomObjectPrivate(); - QDeclarativeDomObjectPrivate(const QDeclarativeDomObjectPrivate &o) - : QSharedData(o) { qFatal("Not impl"); } - ~QDeclarativeDomObjectPrivate(); - - typedef QList > Properties; - Properties properties() const; - Properties properties(QDeclarativeParser::Property *) const; - - QDeclarativeParser::Object *object; -}; - -class QDeclarativeDomPropertyPrivate : public QSharedData -{ -public: - QDeclarativeDomPropertyPrivate(); - QDeclarativeDomPropertyPrivate(const QDeclarativeDomPropertyPrivate &o) - : QSharedData(o) { qFatal("Not impl"); } - ~QDeclarativeDomPropertyPrivate(); - - QByteArray propertyName; - QDeclarativeParser::Property *property; -}; - -class QDeclarativeDomDynamicPropertyPrivate : public QSharedData -{ -public: - QDeclarativeDomDynamicPropertyPrivate(); - QDeclarativeDomDynamicPropertyPrivate(const QDeclarativeDomDynamicPropertyPrivate &o) - : QSharedData(o) { qFatal("Not impl"); } - ~QDeclarativeDomDynamicPropertyPrivate(); - - bool valid; - QDeclarativeParser::Object::DynamicProperty property; -}; - -class QDeclarativeDomValuePrivate : public QSharedData -{ -public: - QDeclarativeDomValuePrivate(); - QDeclarativeDomValuePrivate(const QDeclarativeDomValuePrivate &o) - : QSharedData(o) { qFatal("Not impl"); } - ~QDeclarativeDomValuePrivate(); - - QDeclarativeParser::Property *property; - QDeclarativeParser::Value *value; -}; - -class QDeclarativeDomBasicValuePrivate : public QSharedData -{ -public: - QDeclarativeDomBasicValuePrivate(); - QDeclarativeDomBasicValuePrivate(const QDeclarativeDomBasicValuePrivate &o) - : QSharedData(o) { qFatal("Not impl"); } - ~QDeclarativeDomBasicValuePrivate(); - - QDeclarativeParser::Value *value; -}; - -class QDeclarativeDomImportPrivate : public QSharedData -{ -public: - QDeclarativeDomImportPrivate(); - QDeclarativeDomImportPrivate(const QDeclarativeDomImportPrivate &o) - : QSharedData(o) { qFatal("Not impl"); } - ~QDeclarativeDomImportPrivate(); - - enum Type { Library, File }; - - Type type; - QString uri; - QString version; - QString qualifier; -}; - -QT_END_NAMESPACE - -#endif // QDECLARATIVEDOM_P_P_H - diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 9fde18c81c..b30b4cfb55 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -55,6 +55,7 @@ #include "private/qdeclarativestringconverters_p.h" #include "private/qdeclarativexmlhttprequest_p.h" #include "private/qdeclarativesqldatabase_p.h" +#include "private/qdeclarativescarceresourcescriptclass_p.h" #include "private/qdeclarativetypenamescriptclass_p.h" #include "private/qdeclarativelistscriptclass_p.h" #include "qdeclarativescriptstring.h" @@ -103,6 +104,8 @@ #include #include +#include +#include #ifdef Q_OS_WIN // for %APPDATA% #include @@ -349,13 +352,15 @@ QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e) objectClass(0), valueTypeClass(0), globalClass(0), cleanup(0), erroredBindings(0), inProgressCreations(0), scriptEngine(this), workerScriptEngine(0), componentAttached(0), inBeginCreate(false), networkAccessManager(0), networkAccessManagerFactory(0), - typeLoader(e), importDatabase(e), uniqueId(1) + scarceResources(0), scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1), + sgContext(0) { if (!qt_QmlQtModule_registered) { qt_QmlQtModule_registered = true; QDeclarativeItemModule::defineModule(); QDeclarativeUtilModule::defineModule(); QDeclarativeEnginePrivate::defineModule(); + QSGItemsModule::defineModule(); QDeclarativeValueTypeFactory::registerValueTypes(); } globalClass = new QDeclarativeGlobalScriptClass(&scriptEngine); @@ -499,6 +504,8 @@ QDeclarativeEnginePrivate::~QDeclarativeEnginePrivate() contextClass = 0; delete objectClass; objectClass = 0; + delete scarceResourceClass; + scarceResourceClass = 0; delete valueTypeClass; valueTypeClass = 0; delete typeNameClass; @@ -514,7 +521,10 @@ QDeclarativeEnginePrivate::~QDeclarativeEnginePrivate() (*iter)->release(); for(QHash, QDeclarativePropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter) (*iter)->release(); - + for(QHash::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) { + delete (*iter)->qobjectApi; + delete *iter; + } } void QDeclarativeEnginePrivate::clear(SimpleList &bvs) @@ -571,6 +581,7 @@ void QDeclarativeEnginePrivate::init() contextClass = new QDeclarativeContextScriptClass(q); objectClass = new QDeclarativeObjectScriptClass(q); + scarceResourceClass = new QDeclarativeScarceResourceScriptClass(q); valueTypeClass = new QDeclarativeValueTypeScriptClass(q); typeNameClass = new QDeclarativeTypeNameScriptClass(q); listClass = new QDeclarativeListScriptClass(q); @@ -647,6 +658,22 @@ QDeclarativeEngine::~QDeclarativeEngine() Q_D(QDeclarativeEngine); if (d->isDebugging) QDeclarativeEngineDebugServer::instance()->remEngine(this); + + // if we are the parent of any of the qobject module api instances, + // we need to remove them from our internal list, in order to prevent + // a segfault in engine private dtor. + QList keys = d->moduleApiInstances.keys(); + QObject *currQObjectApi = 0; + QDeclarativeMetaType::ModuleApiInstance *currInstance = 0; + foreach (const QDeclarativeMetaType::ModuleApi &key, keys) { + currInstance = d->moduleApiInstances.value(key); + currQObjectApi = currInstance->qobjectApi; + if (this->children().contains(currQObjectApi)) { + delete currQObjectApi; + delete currInstance; + d->moduleApiInstances.remove(key); + } + } } /*! \fn void QDeclarativeEngine::quit() @@ -813,6 +840,18 @@ QDeclarativeImageProvider::ImageType QDeclarativeEnginePrivate::getImageProvider return static_cast(-1); } +QSGTexture *QDeclarativeEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size) +{ + QMutexLocker locker(&mutex); + QSharedPointer provider = imageProviders.value(url.host()); + locker.unlock(); + if (provider) { + QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1); + return provider->requestTexture(imageId, size, req_size); + } + return 0; +} + QImage QDeclarativeEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size) { QMutexLocker locker(&mutex); @@ -2056,7 +2095,9 @@ QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &val) { - if (val.userType() == qMetaTypeId()) { + if (variantIsScarceResource(val)) { + return scarceResourceClass->newScarceResource(val); + } else if (val.userType() == qMetaTypeId()) { QDeclarativeListReferencePrivate *p = QDeclarativeListReferencePrivate::get((QDeclarativeListReference*)val.constData()); if (p->object) { @@ -2085,11 +2126,69 @@ QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &v } } +/* + If the variant is a scarce resource (consumes a large amount of memory, or + only a limited number of them can be held in memory at any given time without + exhausting supply for future use) we need to release the scarce resource + after evaluation of the javascript binding is complete. + */ +bool QDeclarativeEnginePrivate::variantIsScarceResource(const QVariant& val) +{ + if (val.type() == QVariant::Pixmap) { + return true; + } else if (val.type() == QVariant::Image) { + return true; + } + + return false; +} + +/* + This function should be called prior to evaluation of any js expression, + so that scarce resources are not freed prematurely (eg, if there is a + nested javascript expression). + */ +void QDeclarativeEnginePrivate::referenceScarceResources() +{ + scarceResourcesRefCount += 1; +} + +/* + This function should be called after evaluation of the js expression is + complete, and so the scarce resources may be freed safely. + */ +void QDeclarativeEnginePrivate::dereferenceScarceResources() +{ + Q_ASSERT(scarceResourcesRefCount > 0); + scarceResourcesRefCount -= 1; + + // if the refcount is zero, then evaluation of the "top level" + // expression must have completed. We can safely release the + // scarce resources. + if (scarceResourcesRefCount == 0) { + // iterate through the list and release them all. + // note that the actual SRD is owned by the JS engine, + // so we cannot delete the SRD; but we can free the + // memory used by the variant in the SRD. + ScarceResourceData *srd = 0; + while (scarceResources) { + srd = scarceResources; // srd points to the "old" (current) head of the list + scarceResources = srd->next; // srd->next is the "new" head of the list + if (srd->next) srd->next->prev = &scarceResources; // newHead->prev = listptr. + srd->next = 0; + srd->prev = 0; + srd->releaseResource(); // release the old head node. + } + } +} + QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val, int hint) { QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val); if (dc == objectClass) return QVariant::fromValue(objectClass->toQObject(val)); + else if (dc == scarceResourceClass) + return scarceResourceClass->toVariant(val); else if (dc == valueTypeClass) return valueTypeClass->toVariant(val); else if (dc == contextClass) @@ -2214,6 +2313,20 @@ void QDeclarativeEngine::setPluginPathList(const QStringList &paths) } +/*! + Imports the plugin named \a filePath with the \a uri provided. + Returns true if the plugin was successfully imported; otherwise returns false. + + On failure and if non-null, the \a errors list will have any errors which occurred prepended to it. + + The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface. +*/ +bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QList *errors) +{ + Q_D(QDeclarativeEngine); + return d->importDatabase.importPlugin(filePath, uri, errors); +} + /*! Imports the plugin named \a filePath with the \a uri provided. Returns true if the plugin was successfully imported; otherwise returns false. @@ -2225,7 +2338,18 @@ void QDeclarativeEngine::setPluginPathList(const QStringList &paths) bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString) { Q_D(QDeclarativeEngine); - return d->importDatabase.importPlugin(filePath, uri, errorString); + QList errors; + bool retn = d->importDatabase.importPlugin(filePath, uri, &errors); + if (!errors.isEmpty()) { + QString builtError; + for (int i = 0; i < errors.size(); ++i) { + builtError = QString(QLatin1String("%1\n %2")) + .arg(builtError) + .arg(errors.at(i).toString()); + } + *errorString = builtError; + } + return retn; } /*! diff --git a/src/declarative/qml/qdeclarativeengine.h b/src/declarative/qml/qdeclarativeengine.h index 631fc5ec57..8db3db8096 100644 --- a/src/declarative/qml/qdeclarativeengine.h +++ b/src/declarative/qml/qdeclarativeengine.h @@ -86,7 +86,8 @@ public: void setPluginPathList(const QStringList &paths); void addPluginPath(const QString& dir); - bool importPlugin(const QString &filePath, const QString &uri, QString *errorString); + bool importPlugin(const QString &filePath, const QString &uri, QString *errorString); // XXX: Qt 5: Remove this function + bool importPlugin(const QString &filePath, const QString &uri, QList *errors); void setNetworkAccessManagerFactory(QDeclarativeNetworkAccessManagerFactory *); QDeclarativeNetworkAccessManagerFactory *networkAccessManagerFactory() const; diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h index 88b4e800f8..fadedf41dd 100644 --- a/src/declarative/qml/qdeclarativeengine_p.h +++ b/src/declarative/qml/qdeclarativeengine_p.h @@ -67,6 +67,7 @@ #include "private/qdeclarativeproperty_p.h" #include "private/qdeclarativepropertycache_p.h" #include "private/qdeclarativeobjectscriptclass_p.h" +#include "private/qdeclarativescarceresourcescriptclass_p.h" #include "private/qdeclarativecontextscriptclass_p.h" #include "private/qdeclarativevaluetypescriptclass_p.h" #include "private/qdeclarativemetatype_p.h" @@ -93,6 +94,8 @@ class QDeclarativeExpression; class QDeclarativeContextScriptClass; class QDeclarativeImportDatabase; class QDeclarativeObjectScriptClass; +class QDeclarativeScarceResourceScriptClass; +class ScarceResourceData; class QDeclarativeTypeNameScriptClass; class QDeclarativeValueTypeScriptClass; class QScriptEngineDebugger; @@ -110,6 +113,8 @@ class QDeclarativeDelayedError; class QDeclarativeWorkerScriptEngine; class QDeclarativeGlobalScriptClass; class QDir; +class QSGTexture; +class QSGContext; class QDeclarativeScriptEngine : public QScriptEngine { @@ -169,6 +174,7 @@ public: QDeclarativeContextData *sharedContext; QObject *sharedScope; QDeclarativeObjectScriptClass *objectClass; + QDeclarativeScarceResourceScriptClass *scarceResourceClass; QDeclarativeValueTypeScriptClass *valueTypeClass; QDeclarativeTypeNameScriptClass *typeNameClass; QDeclarativeListScriptClass *listClass; @@ -233,9 +239,22 @@ public: QHash > imageProviders; QDeclarativeImageProvider::ImageType getImageProviderType(const QUrl &url); + QSGTexture *getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size); QImage getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size); QPixmap getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size); + /* + A scarce resource (like a large pixmap or texture) will be cached in a + JavaScript wrapper object when accessed in a binding or other js expression. + We need some way to automatically release that scarce resource prior to normal + garbage collection (unless the user explicitly preserves the resource). + */ + ScarceResourceData* scarceResources; + int scarceResourcesRefCount; + static bool variantIsScarceResource(const QVariant& val); + void referenceScarceResources(); + void dereferenceScarceResources(); + mutable QMutex mutex; QDeclarativeTypeLoader typeLoader; @@ -250,6 +269,8 @@ public: QDeclarativeValueTypeFactory valueTypes; + QHash moduleApiInstances; + QHash propertyCache; QHash, QDeclarativePropertyCache *> typePropertyCache; inline QDeclarativePropertyCache *cache(QObject *obj); @@ -270,8 +291,6 @@ public: QHash m_qmlLists; QHash m_compositeTypes; - QHash m_sharedScriptImports; - QScriptValue scriptValueFromVariant(const QVariant &); QVariant scriptValueToVariant(const QScriptValue &, int hint = QVariant::Invalid); @@ -327,6 +346,8 @@ public: static void defineModule(); static bool qml_debugging_enabled; + + QSGContext *sgContext; }; /*! diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp index 7a85adaa6e..afd1be1025 100644 --- a/src/declarative/qml/qdeclarativeexpression.cpp +++ b/src/declarative/qml/qdeclarativeexpression.cpp @@ -630,7 +630,6 @@ QScriptValue QDeclarativeExpressionPrivate::scriptValue(QObject *secondaryScope, if (!expressionFunctionValid) { QDeclarativeEngine *engine = context()->engine; QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); - QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); @@ -663,8 +662,10 @@ QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isU } QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(q->engine()); - - return ep->scriptValueToVariant(scriptValue(secondaryScope, isUndefined), qMetaTypeId >()); + ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation. + QVariant retn(ep->scriptValueToVariant(scriptValue(secondaryScope, isUndefined), qMetaTypeId >())); + ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete. + return retn; } /*! diff --git a/src/declarative/qml/qdeclarativeimageprovider.cpp b/src/declarative/qml/qdeclarativeimageprovider.cpp index f111c201fa..c9b399cc32 100644 --- a/src/declarative/qml/qdeclarativeimageprovider.cpp +++ b/src/declarative/qml/qdeclarativeimageprovider.cpp @@ -159,6 +159,8 @@ public: requestImage() method will be called for all image requests. \value Pixmap The Image Provider provides QPixmap images. The requestPixmap() method will be called for all image requests. + \value Texture The Image Provider provides QSGTextureProvider based images. + The requestTexture() method will be called for all image requests. \omitvalue */ /*! @@ -243,5 +245,36 @@ QPixmap QDeclarativeImageProvider::requestPixmap(const QString &id, QSize *size, return QPixmap(); } + +/*! + Implement this method to return the texture with \a id. The default + implementation returns 0. + + The \a id is the requested image source, with the "image:" scheme and + provider identifier removed. For example, if the image \l{Image::}{source} + was "image://myprovider/icons/home", the given \a id would be "icons/home". + + The \a requestedSize corresponds to the \l {Image::sourceSize} requested by + an Image element. If \a requestedSize is a valid size, the image + returned should be of that size. + + In all cases, \a size must be set to the original size of the image. This + is used to set the \l {Item::}{width} and \l {Item::}{height} of the + relevant \l Image if these values have not been set explicitly. + + \note this method may be called by multiple threads, so ensure the + implementation of this method is reentrant. +*/ + +QSGTexture *QDeclarativeImageProvider::requestTexture(const QString &id, QSize *size, const QSize &requestedSize) +{ + Q_UNUSED(id); + Q_UNUSED(size); + Q_UNUSED(requestedSize); + if (d->type == Texture) + qWarning("ImageProvider supports Texture type but has not implemented requestTexture()"); + return 0; +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeimageprovider.h b/src/declarative/qml/qdeclarativeimageprovider.h index 7f13fda85b..e5e80f227c 100644 --- a/src/declarative/qml/qdeclarativeimageprovider.h +++ b/src/declarative/qml/qdeclarativeimageprovider.h @@ -52,13 +52,15 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeImageProviderPrivate; +class QSGTexture; class Q_DECLARATIVE_EXPORT QDeclarativeImageProvider { public: enum ImageType { Image, - Pixmap + Pixmap, + Texture }; QDeclarativeImageProvider(ImageType type); @@ -68,6 +70,7 @@ public: virtual QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize); virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize); + virtual QSGTexture *requestTexture(const QString &id, QSize *size, const QSize &requestedSize); private: QDeclarativeImageProviderPrivate *d; diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp index e8d593fd1a..c5abe2c75d 100644 --- a/src/declarative/qml/qdeclarativeimport.cpp +++ b/src/declarative/qml/qdeclarativeimport.cpp @@ -83,7 +83,7 @@ public: QDeclarativeType** type_return, QUrl* url_return, QUrl *base = 0, bool *typeRecursionDetected = 0); bool find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, - QUrl* url_return, QUrl *base = 0, QString *errorString = 0); + QUrl* url_return, QUrl *base = 0, QList *errors = 0); }; class QDeclarativeImportsPrivate { @@ -93,15 +93,15 @@ public: bool importExtension(const QString &absoluteFilePath, const QString &uri, QDeclarativeImportDatabase *database, QDeclarativeDirComponents* components, - QString *errorString); + QList *errors); QString resolvedUri(const QString &dir_arg, QDeclarativeImportDatabase *database); bool add(const QDeclarativeDirComponents &qmldircomponentsnetwork, const QString& uri_arg, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType, - QDeclarativeImportDatabase *database, QString *errorString); + QDeclarativeImportDatabase *database, QList *errors); bool find(const QByteArray& type, int *vmajor, int *vminor, - QDeclarativeType** type_return, QUrl* url_return, QString *errorString); + QDeclarativeType** type_return, QUrl* url_return, QList *errors); QDeclarativeImportedNamespace *findNamespace(const QString& type); @@ -163,7 +163,7 @@ QUrl QDeclarativeImports::baseUrl() const static QDeclarativeTypeNameCache * cacheForNamespace(QDeclarativeEngine *engine, const QDeclarativeImportedNamespace &set, - QDeclarativeTypeNameCache *cache) + QDeclarativeTypeNameCache *cache, bool importWasQualified) { if (!cache) cache = new QDeclarativeTypeNameCache(engine); @@ -171,10 +171,27 @@ cacheForNamespace(QDeclarativeEngine *engine, const QDeclarativeImportedNamespac QList types = QDeclarativeMetaType::qmlTypes(); for (int ii = 0; ii < set.uris.count(); ++ii) { - QByteArray base = set.uris.at(ii).toUtf8() + '/'; + QByteArray uri = set.uris.at(ii).toUtf8(); int major = set.majversions.at(ii); int minor = set.minversions.at(ii); + if (importWasQualified) { + QDeclarativeMetaType::ModuleApi moduleApi = QDeclarativeMetaType::moduleApi(uri, major, minor); + if (moduleApi.script || moduleApi.qobject) { + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); + QDeclarativeMetaType::ModuleApiInstance *a = ep->moduleApiInstances.value(moduleApi); + if (!a) { + a = new QDeclarativeMetaType::ModuleApiInstance; + a->scriptCallback = moduleApi.script; + a->qobjectCallback = moduleApi.qobject; + ep->moduleApiInstances.insert(moduleApi, a); + } + cache->setModuleApi(a); + } + } + + QByteArray base = uri + '/'; + foreach (QDeclarativeType *type, types) { if (type->qmlTypeName().startsWith(base) && type->qmlTypeName().lastIndexOf('/') == (base.length() - 1) && @@ -200,15 +217,15 @@ void QDeclarativeImports::populateCache(QDeclarativeTypeNameCache *cache, QDecla QDeclarativeTypeNameCache::Data *d = cache->data(iter.key()); if (d) { if (!d->typeNamespace) - cacheForNamespace(engine, *(*iter), d->typeNamespace); + cacheForNamespace(engine, *(*iter), d->typeNamespace, true); } else { - QDeclarativeTypeNameCache *nc = cacheForNamespace(engine, *(*iter), 0); + QDeclarativeTypeNameCache *nc = cacheForNamespace(engine, *(*iter), 0, true); cache->add(iter.key(), nc); nc->release(); } } - cacheForNamespace(engine, set, cache); + cacheForNamespace(engine, set, cache, false); } /*! @@ -227,7 +244,7 @@ void QDeclarativeImports::populateCache(QDeclarativeTypeNameCache *cache, QDecla */ bool QDeclarativeImports::resolveType(const QByteArray& type, QDeclarativeType** type_return, QUrl* url_return, int *vmaj, int *vmin, - QDeclarativeImportedNamespace** ns_return, QString *errorString) const + QDeclarativeImportedNamespace** ns_return, QList *errors) const { QDeclarativeImportedNamespace* ns = d->findNamespace(QString::fromUtf8(type)); if (ns) { @@ -236,7 +253,7 @@ bool QDeclarativeImports::resolveType(const QByteArray& type, return true; } if (type_return || url_return) { - if (d->find(type,vmaj,vmin,type_return,url_return, errorString)) { + if (d->find(type,vmaj,vmin,type_return,url_return, errors)) { if (qmlImportTrace()) { if (type_return && *type_return && url_return && !url_return->isEmpty()) qDebug().nospace() << "QDeclarativeImports(" << qPrintable(baseUrl().toString()) << ")" << "::resolveType: " @@ -351,13 +368,16 @@ QDeclarativeImportsPrivate::~QDeclarativeImportsPrivate() bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath, const QString &uri, QDeclarativeImportDatabase *database, - QDeclarativeDirComponents* components, QString *errorString) + QDeclarativeDirComponents* components, QList *errors) { QFile file(absoluteFilePath); QString filecontent; if (!QDeclarative_isFileCaseCorrect(absoluteFilePath)) { - if (errorString) - *errorString = QDeclarativeImportDatabase::tr("cannot load module \"%1\": File name case mismatch for \"%2\"").arg(uri).arg(absoluteFilePath); + if (errors) { + QDeclarativeError error; + error.setDescription(QDeclarativeImportDatabase::tr("cannot load module \"%1\": File name case mismatch for \"%2\"").arg(uri).arg(absoluteFilePath)); + errors->prepend(error); + } return false; } else if (file.open(QFile::ReadOnly)) { filecontent = QString::fromUtf8(file.readAll()); @@ -365,15 +385,29 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath qDebug().nospace() << "QDeclarativeImports(" << qPrintable(base.toString()) << "::importExtension: " << "loaded " << absoluteFilePath; } else { - if (errorString) - *errorString = QDeclarativeImportDatabase::tr("module \"%1\" definition \"%2\" not readable").arg(uri).arg(absoluteFilePath); + if (errors) { + QDeclarativeError error; + error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" definition \"%2\" not readable").arg(uri).arg(absoluteFilePath)); + errors->prepend(error); + } return false; } QDir dir = QFileInfo(file).dir(); + QUrl url = QUrl::fromLocalFile(absoluteFilePath); QDeclarativeDirParser qmldirParser; qmldirParser.setSource(filecontent); - qmldirParser.parse(); + qmldirParser.setUrl(url); + + // propagate any errors reported by the parser back up to the typeloader. + if (qmldirParser.parse()) { + if (errors) { + for (int i = 0; i < qmldirParser.errors().size(); ++i) { + errors->prepend(qmldirParser.errors().at(i)); + } + } + return false; + } if (! qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(absoluteFilePath)) { qmlDirFilesForWhichPluginsHaveBeenLoaded.insert(absoluteFilePath); @@ -390,14 +424,26 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath } #endif if (!resolvedFilePath.isEmpty()) { - if (!database->importPlugin(resolvedFilePath, uri, errorString)) { - if (errorString) - *errorString = QDeclarativeImportDatabase::tr("plugin cannot be loaded for module \"%1\": %2").arg(uri).arg(*errorString); + if (!database->importPlugin(resolvedFilePath, uri, errors)) { + if (errors) { + // XXX TODO: should we leave the import plugin error alone? + // Here, we pop it off the top and coalesce it into this error's message. + // The reason is that the lower level may add url and line/column numbering information. + QDeclarativeError poppedError = errors->takeFirst(); + QDeclarativeError error; + error.setDescription(QDeclarativeImportDatabase::tr("plugin cannot be loaded for module \"%1\": %2").arg(uri).arg(poppedError.description())); + error.setUrl(url); + errors->prepend(error); + } return false; } } else { - if (errorString) - *errorString = QDeclarativeImportDatabase::tr("module \"%1\" plugin \"%2\" not found").arg(uri).arg(plugin.name); + if (errors) { + QDeclarativeError error; + error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" plugin \"%2\" not found").arg(uri).arg(plugin.name)); + error.setUrl(url); + errors->prepend(error); + } return false; } } @@ -443,7 +489,7 @@ QString QDeclarativeImportsPrivate::resolvedUri(const QString &dir_arg, QDeclara bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomponentsnetwork, const QString& uri_arg, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType, - QDeclarativeImportDatabase *database, QString *errorString) + QDeclarativeImportDatabase *database, QList *errors) { QDeclarativeDirComponents qmldircomponents = qmldircomponentsnetwork; QString uri = uri_arg; @@ -477,7 +523,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp url = QUrl::fromLocalFile(fi.absolutePath()).toString(); uri = resolvedUri(dir, database); - if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString)) + if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errors)) return false; break; } @@ -496,7 +542,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp url = QUrl::fromLocalFile(fi.absolutePath()).toString(); uri = resolvedUri(dir, database); - if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString)) + if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errors)) return false; break; } @@ -516,7 +562,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp url = QUrl::fromLocalFile(fi.absolutePath()).toString(); uri = resolvedUri(dir, database); - if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString)) + if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errors)) return false; break; } @@ -527,12 +573,14 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp versionFound = true; if (!versionFound && qmldircomponents.isEmpty()) { - if (errorString) { + if (errors) { bool anyversion = QDeclarativeMetaType::isModule(uri.toUtf8(), -1, -1); + QDeclarativeError error; // we don't set the url or line or column as these will be set by the loader. if (anyversion) - *errorString = QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin); + error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin)); else - *errorString = QDeclarativeImportDatabase::tr("module \"%1\" is not installed").arg(uri_arg); + error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" is not installed").arg(uri_arg)); + errors->prepend(error); } return false; } @@ -545,15 +593,19 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp QString dir = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri))); QFileInfo dirinfo(dir); if (dir.isEmpty() || !dirinfo.exists() || !dirinfo.isDir()) { - if (errorString) - *errorString = QDeclarativeImportDatabase::tr("\"%1\": no such directory").arg(uri_arg); + if (errors) { + QDeclarativeError error; // we don't set the line or column as these will be set by the loader. + error.setDescription(QDeclarativeImportDatabase::tr("\"%1\": no such directory").arg(uri_arg)); + error.setUrl(importUrl); + errors->prepend(error); + } return false; // local import dirs must exist } uri = resolvedUri(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri))), database); if (uri.endsWith(QLatin1Char('/'))) uri.chop(1); if (QFile::exists(localFileOrQrc)) { - if (!importExtension(localFileOrQrc,uri,database,&qmldircomponents,errorString)) + if (!importExtension(localFileOrQrc,uri,database,&qmldircomponents,errors)) return false; } } else { @@ -562,11 +614,14 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp QString localFileOrQrc = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri))); QFileInfo dirinfo(localFileOrQrc); if (localFileOrQrc.isEmpty() || !dirinfo.exists() || !dirinfo.isDir()) { - if (errorString) { + if (errors) { + QDeclarativeError error; // we don't set the line or column as these will be set by the loader. if (localFileOrQrc.isEmpty()) - *errorString = QDeclarativeImportDatabase::tr("import \"%1\" has no qmldir and no namespace").arg(uri); + error.setDescription(QDeclarativeImportDatabase::tr("import \"%1\" has no qmldir and no namespace").arg(uri)); else - *errorString = QDeclarativeImportDatabase::tr("\"%1\": no such directory").arg(uri); + error.setDescription(QDeclarativeImportDatabase::tr("\"%1\": no such directory").arg(uri)); + error.setUrl(importUrl); + errors->prepend(error); } return false; } @@ -598,7 +653,11 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp if (lowest_maj > vmaj || (lowest_maj == vmaj && lowest_min > vmin) || highest_maj < vmaj || (highest_maj == vmaj && highest_min < vmin)) { - *errorString = QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin); + if (errors) { + QDeclarativeError error; // we don't set the url or line or column information, as these will be set by the loader. + error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin)); + errors->prepend(error); + } return false; } } @@ -613,7 +672,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp } bool QDeclarativeImportsPrivate::find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, - QUrl* url_return, QString *errorString) + QUrl* url_return, QList *errors) { QDeclarativeImportedNamespace *s = 0; int slash = type.indexOf('/'); @@ -621,14 +680,20 @@ bool QDeclarativeImportsPrivate::find(const QByteArray& type, int *vmajor, int * QString namespaceName = QString::fromUtf8(type.left(slash)); s = set.value(namespaceName); if (!s) { - if (errorString) - *errorString = QDeclarativeImportDatabase::tr("- %1 is not a namespace").arg(namespaceName); + if (errors) { + QDeclarativeError error; + error.setDescription(QDeclarativeImportDatabase::tr("- %1 is not a namespace").arg(namespaceName)); + errors->prepend(error); + } return false; } int nslash = type.indexOf('/',slash+1); if (nslash > 0) { - if (errorString) - *errorString = QDeclarativeImportDatabase::tr("- nested namespaces not allowed"); + if (errors) { + QDeclarativeError error; + error.setDescription(QDeclarativeImportDatabase::tr("- nested namespaces not allowed")); + errors->prepend(error); + } return false; } } else { @@ -636,7 +701,7 @@ bool QDeclarativeImportsPrivate::find(const QByteArray& type, int *vmajor, int * } QByteArray unqualifiedtype = slash < 0 ? type : type.mid(slash+1); // common-case opt (QString::mid works fine, but slower) if (s) { - if (s->find(unqualifiedtype,vmajor,vminor,type_return,url_return, &base, errorString)) + if (s->find(unqualifiedtype,vmajor,vminor,type_return,url_return, &base, errors)) return true; if (s->urls.count() == 1 && !s->isLibrary[0] && url_return && s != &unqualifiedset) { // qualified, and only 1 url @@ -654,7 +719,7 @@ QDeclarativeImportedNamespace *QDeclarativeImportsPrivate::findNamespace(const Q } bool QDeclarativeImportedNamespace::find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, - QUrl* url_return, QUrl *base, QString *errorString) + QUrl* url_return, QUrl *base, QList *errors) { bool typeRecursionDetected = false; for (int i=0; iprepend(error); } return false; } @@ -701,11 +766,13 @@ bool QDeclarativeImportedNamespace::find(const QByteArray& type, int *vmajor, in return true; } } - if (errorString) { + if (errors) { + QDeclarativeError error; if (typeRecursionDetected) - *errorString = QDeclarativeImportDatabase::tr("is instantiated recursively"); + error.setDescription(QDeclarativeImportDatabase::tr("is instantiated recursively")); else - *errorString = QDeclarativeImportDatabase::tr("is not a type"); + error.setDescription(QDeclarativeImportDatabase::tr("is not a type")); + errors->prepend(error); } return false; } @@ -790,7 +857,7 @@ bool QDeclarativeImports::addImport(QDeclarativeImportDatabase *importDb, const QString& uri, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType, const QDeclarativeDirComponents &qmldircomponentsnetwork, - QString *errorString) + QList *errors) { if (qmlImportTrace()) qDebug().nospace() << "QDeclarativeImports(" << qPrintable(baseUrl().toString()) << ")" << "::addImport: " @@ -798,7 +865,7 @@ bool QDeclarativeImports::addImport(QDeclarativeImportDatabase *importDb, << (importType==QDeclarativeScriptParser::Import::Library? "Library" : "File") << " as " << prefix; - return d->add(qmldircomponentsnetwork, uri, prefix, vmaj, vmin, importType, importDb, errorString); + return d->add(qmldircomponentsnetwork, uri, prefix, vmaj, vmin, importType, importDb, errors); } /*! @@ -1013,7 +1080,7 @@ void QDeclarativeImportDatabase::setImportPathList(const QStringList &paths) /*! \internal */ -bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QString &uri, QString *errorString) +bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QString &uri, QList *errors) { if (qmlImportTrace()) qDebug().nospace() << "QDeclarativeImportDatabase::importPlugin: " << uri << " from " << filePath; @@ -1033,15 +1100,21 @@ bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QSt if (!engineInitialized || !typesRegistered) { if (!QDeclarative_isFileCaseCorrect(absoluteFilePath)) { - if (errorString) - *errorString = tr("File name case mismatch for \"%2\"").arg(absoluteFilePath); + if (errors) { + QDeclarativeError error; + error.setDescription(tr("File name case mismatch for \"%2\"").arg(absoluteFilePath)); + errors->prepend(error); + } return false; } QPluginLoader loader(absoluteFilePath); if (!loader.load()) { - if (errorString) - *errorString = loader.errorString(); + if (errors) { + QDeclarativeError error; + error.setDescription(loader.errorString()); + errors->prepend(error); + } return false; } @@ -1063,8 +1136,11 @@ bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QSt iface->initializeEngine(engine, moduleId); } } else { - if (errorString) - *errorString = loader.errorString(); + if (errors) { + QDeclarativeError error; + error.setDescription(loader.errorString()); + errors->prepend(error); + } return false; } } diff --git a/src/declarative/qml/qdeclarativeimport_p.h b/src/declarative/qml/qdeclarativeimport_p.h index 1c910fd5bf..9d140bf106 100644 --- a/src/declarative/qml/qdeclarativeimport_p.h +++ b/src/declarative/qml/qdeclarativeimport_p.h @@ -84,7 +84,7 @@ public: QDeclarativeType** type_return, QUrl* url_return, int *version_major, int *version_minor, QDeclarativeImportedNamespace** ns_return, - QString *errorString = 0) const; + QList *errors = 0) const; bool resolveType(QDeclarativeImportedNamespace*, const QByteArray& type, QDeclarativeType** type_return, QUrl* url_return, @@ -94,7 +94,7 @@ public: const QString& uri, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType, const QDeclarativeDirComponents &qmldircomponentsnetwork, - QString *errorString); + QList *errors); void populateCache(QDeclarativeTypeNameCache *cache, QDeclarativeEngine *) const; @@ -110,7 +110,7 @@ public: QDeclarativeImportDatabase(QDeclarativeEngine *); ~QDeclarativeImportDatabase(); - bool importPlugin(const QString &filePath, const QString &uri, QString *errorString); + bool importPlugin(const QString &filePath, const QString &uri, QList *errors); QStringList importPathList() const; void setImportPathList(const QStringList &paths); diff --git a/src/declarative/qml/qdeclarativeinfo.cpp b/src/declarative/qml/qdeclarativeinfo.cpp index 7c8f73bc61..8449578c65 100644 --- a/src/declarative/qml/qdeclarativeinfo.cpp +++ b/src/declarative/qml/qdeclarativeinfo.cpp @@ -129,6 +129,18 @@ QDeclarativeInfo::~QDeclarativeInfo() int marker = typeName.indexOf(QLatin1String("_QMLTYPE_")); if (marker != -1) typeName = typeName.left(marker); + + marker = typeName.indexOf(QLatin1String("_QML_")); + if (marker != -1) { + typeName = typeName.left(marker) + "*"; + type = QDeclarativeMetaType::qmlType(QMetaType::type(typeName.toLatin1())); + if (type) { + typeName = QLatin1String(type->qmlTypeName()); + int lastSlash = typeName.lastIndexOf(QLatin1Char('/')); + if (lastSlash != -1) + typeName = typeName.mid(lastSlash+1); + } + } } d->buffer.prepend(QLatin1String("QML ") + typeName + QLatin1String(": ")); diff --git a/src/declarative/qml/qdeclarativeinstruction.cpp b/src/declarative/qml/qdeclarativeinstruction.cpp index 0c99cefb04..556b7bc343 100644 --- a/src/declarative/qml/qdeclarativeinstruction.cpp +++ b/src/declarative/qml/qdeclarativeinstruction.cpp @@ -96,6 +96,9 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx) case QDeclarativeInstruction::StoreString: qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_STRING\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value); break; + case QDeclarativeInstruction::StoreByteArray: + qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_BYTEARRAY" << instr->storeByteArray.propertyIndex << "\t" << instr->storeByteArray.value << "\t\t" << datas.at(instr->storeByteArray.value); + break; case QDeclarativeInstruction::StoreUrl: qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_URL\t\t" << instr->storeUrl.propertyIndex << "\t" << instr->storeUrl.value << "\t\t" << urls.at(instr->storeUrl.value); break; diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h index 20be889252..a5521b6425 100644 --- a/src/declarative/qml/qdeclarativeinstruction_p.h +++ b/src/declarative/qml/qdeclarativeinstruction_p.h @@ -88,6 +88,7 @@ public: // StoreInteger - Store a int or uint in a core property // StoreBool - Store a bool in a core property // StoreString - Store a QString in a core property + // StoreByteArray - Store a QByteArray in a core property // StoreUrl - Store a QUrl in a core property // StoreColor - Store a QColor in a core property // StoreDate - Store a QDate in a core property @@ -101,6 +102,7 @@ public: StoreInteger, /* storeInteger */ StoreBool, /* storeBool */ StoreString, /* storeString */ + StoreByteArray, /* storeByteArray */ StoreUrl, /* storeUrl */ StoreColor, /* storeColor */ StoreDate, /* storeDate */ @@ -245,6 +247,10 @@ public: int propertyIndex; int value; }; + struct StoreByteArrayInstruction { + int propertyIndex; + int value; + }; struct StoreScriptStringInstruction { int propertyIndex; int value; @@ -332,6 +338,7 @@ public: StoreIntegerInstruction storeInteger; StoreBoolInstruction storeBool; StoreStringInstruction storeString; + StoreByteArrayInstruction storeByteArray; StoreScriptStringInstruction storeScriptString; StoreScriptInstruction storeScript; StoreUrlInstruction storeUrl; diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp index bf1f699c72..ede02e9f30 100644 --- a/src/declarative/qml/qdeclarativemetatype.cpp +++ b/src/declarative/qml/qdeclarativemetatype.cpp @@ -88,6 +88,7 @@ QT_BEGIN_NAMESPACE struct QDeclarativeMetaTypeData { + QDeclarativeMetaTypeData(); ~QDeclarativeMetaTypeData(); QList types; typedef QHash Ids; @@ -98,6 +99,14 @@ struct QDeclarativeMetaTypeData MetaObjects metaObjectToType; typedef QHash StringConverters; StringConverters stringConverters; + struct ModuleApiList { + ModuleApiList() : sorted(true) {} + QList moduleApis; + bool sorted; + }; + typedef QHash ModuleApis; + ModuleApis moduleApis; + int moduleApiCount; struct ModuleInfo { ModuleInfo(int major, int minor) @@ -119,6 +128,11 @@ struct QDeclarativeMetaTypeData Q_GLOBAL_STATIC(QDeclarativeMetaTypeData, metaTypeData) Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock) +QDeclarativeMetaTypeData::QDeclarativeMetaTypeData() +: moduleApiCount(0) +{ +} + QDeclarativeMetaTypeData::~QDeclarativeMetaTypeData() { for (int i = 0; i < types.count(); ++i) @@ -664,6 +678,34 @@ int registerType(const QDeclarativePrivate::RegisterType &type) return index; } +int registerModuleApi(const QDeclarativePrivate::RegisterModuleApi &api) +{ + QWriteLocker lock(metaTypeDataLock()); + + QDeclarativeMetaTypeData *data = metaTypeData(); + QByteArray uri(api.uri); + QDeclarativeMetaType::ModuleApi import; + import.major = api.versionMajor; + import.minor = api.versionMinor; + import.script = api.scriptApi; + import.qobject = api.qobjectApi; + + int index = data->moduleApiCount++; + + QDeclarativeMetaTypeData::ModuleApis::Iterator iter = data->moduleApis.find(uri); + if (iter == data->moduleApis.end()) { + QDeclarativeMetaTypeData::ModuleApiList apis; + apis.moduleApis << import; + data->moduleApis.insert(uri, apis); + } else { + iter->moduleApis << import; + iter->sorted = false; + } + + return index; +} + + /* This method is "over generalized" to allow us to (potentially) register more types of things in the future without adding exported symbols. @@ -676,13 +718,16 @@ int QDeclarativePrivate::qmlregister(RegistrationType type, void *data) return registerInterface(*reinterpret_cast(data)); } else if (type == AutoParentRegistration) { return registerAutoParentFunction(*reinterpret_cast(data)); + } else if (type == ModuleApiRegistration) { + return registerModuleApi(*reinterpret_cast(data)); } return -1; } /* - Have any types been registered for \a module with at least versionMajor.versionMinor, and types - for \a module with at most versionMajor.versionMinor. + Returns true if any type or API has been registered for the given \a module with at least + versionMajor.versionMinor, or if types have been registered for \a module with at most + versionMajor.versionMinor. So if only 4.7 and 4.9 have been registered, 4.7,4.8, and 4.9 are valid, but not 4.6 nor 4.10. @@ -691,13 +736,27 @@ int QDeclarativePrivate::qmlregister(RegistrationType type, void *data) bool QDeclarativeMetaType::isModule(const QByteArray &module, int versionMajor, int versionMinor) { QDeclarativeMetaTypeData *data = metaTypeData(); + + // first, check Types QDeclarativeMetaTypeData::ModuleInfoHash::Iterator it = data->modules.find(module); - return it != data->modules.end() + if (it != data->modules.end() && ((versionMajor<0 && versionMinor<0) || (((*it).vmajor_max > versionMajor || ((*it).vmajor_max == versionMajor && (*it).vminor_max >= versionMinor)) && ((*it).vmajor_min < versionMajor || - ((*it).vmajor_min == versionMajor && (*it).vminor_min <= versionMinor)))); + ((*it).vmajor_min == versionMajor && (*it).vminor_min <= versionMinor))))) { + return true; + } + + // then, check ModuleApis + foreach (const QDeclarativeMetaType::ModuleApi &mApi, data->moduleApis.value(module).moduleApis) { + if ((versionMajor<0 && versionMinor<0) + || (mApi.major == versionMajor && mApi.minor == versionMinor)) { + return true; + } + } + + return false; } QList QDeclarativeMetaType::parentFunctions() @@ -707,6 +766,35 @@ QList QDeclarativeMetaType::parentFunct return data->parentFunctions; } +static bool operator<(const QDeclarativeMetaType::ModuleApi &lhs, const QDeclarativeMetaType::ModuleApi &rhs) +{ + return lhs.major < rhs.major || (lhs.major == rhs.major && lhs.minor < rhs.minor); +} + +QDeclarativeMetaType::ModuleApi +QDeclarativeMetaType::moduleApi(const QByteArray &uri, int versionMajor, int versionMinor) +{ + QReadLocker lock(metaTypeDataLock()); + QDeclarativeMetaTypeData *data = metaTypeData(); + + QDeclarativeMetaTypeData::ModuleApis::Iterator iter = data->moduleApis.find(uri); + if (iter == data->moduleApis.end()) + return ModuleApi(); + + if (iter->sorted == false) { + qSort(iter->moduleApis.begin(), iter->moduleApis.end()); + iter->sorted = true; + } + + for (int ii = iter->moduleApis.count() - 1; ii >= 0; --ii) { + const ModuleApi &import = iter->moduleApis.at(ii); + if (import.major == versionMajor && import.minor <= versionMinor) + return import; + } + + return ModuleApi(); +} + QObject *QDeclarativeMetaType::toQObject(const QVariant &v, bool *ok) { if (!isQObject(v.userType())) { diff --git a/src/declarative/qml/qdeclarativemetatype_p.h b/src/declarative/qml/qdeclarativemetatype_p.h index aab1c31ef5..291bc38222 100644 --- a/src/declarative/qml/qdeclarativemetatype_p.h +++ b/src/declarative/qml/qdeclarativemetatype_p.h @@ -59,6 +59,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -106,6 +107,25 @@ public: static bool isModule(const QByteArray &module, int versionMajor, int versionMinor); static QList parentFunctions(); + + struct ModuleApiInstance { + ModuleApiInstance() + : scriptCallback(0), qobjectCallback(0), qobjectApi(0) {} + + QScriptValue (*scriptCallback)(QDeclarativeEngine *, QScriptEngine *); + QObject *(*qobjectCallback)(QDeclarativeEngine *, QScriptEngine *); + QScriptValue scriptApi; + QObject *qobjectApi; + }; + struct ModuleApi { + inline ModuleApi(); + inline bool operator==(const ModuleApi &) const; + int major; + int minor; + QScriptValue (*script)(QDeclarativeEngine *, QScriptEngine *); + QObject *(*qobject)(QDeclarativeEngine *, QScriptEngine *); + }; + static ModuleApi moduleApi(const QByteArray &, int, int); }; class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeType @@ -168,6 +188,25 @@ private: QDeclarativeTypePrivate *d; }; +QDeclarativeMetaType::ModuleApi::ModuleApi() +// : major(0), minor(0), script(0), qobject(0) +{ + major = 0; + minor = 0; + script = 0; + qobject = 0; +} + +bool QDeclarativeMetaType::ModuleApi::operator==(const ModuleApi &other) const +{ + return major == other.major && minor == other.minor && script == other.script && qobject == other.qobject; +} + +inline uint qHash(const QDeclarativeMetaType::ModuleApi &import) +{ + return import.major ^ import.minor ^ quintptr(import.script) ^ quintptr(import.qobject); +} + QT_END_NAMESPACE #endif // QDECLARATIVEMETATYPE_P_H diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index 9eecc65e3c..edc1755a72 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -403,6 +403,33 @@ void QDeclarativeObjectScriptClass::setProperty(QObject *obj, } else if (value.isFunction() && !value.isRegExp()) { // this is handled by the binding creation above } else { + //### expand optimization for other known types + if (lastData->propType == QMetaType::Int && value.isNumber()) { + int rawValue = qRound(value.toNumber()); + int status = -1; + int flags = 0; + void *a[] = { (void *)&rawValue, 0, &status, &flags }; + QMetaObject::metacall(obj, QMetaObject::WriteProperty, + lastData->coreIndex, a); + return; + } else if (lastData->propType == QMetaType::QReal && value.isNumber()) { + qreal rawValue = qreal(value.toNumber()); + int status = -1; + int flags = 0; + void *a[] = { (void *)&rawValue, 0, &status, &flags }; + QMetaObject::metacall(obj, QMetaObject::WriteProperty, + lastData->coreIndex, a); + return; + } else if (lastData->propType == QMetaType::QString && value.isString()) { + const QString &rawValue = value.toString(); + int status = -1; + int flags = 0; + void *a[] = { (void *)&rawValue, 0, &status, &flags }; + QMetaObject::metacall(obj, QMetaObject::WriteProperty, + lastData->coreIndex, a); + return; + } + QVariant v; if (lastData->flags & QDeclarativePropertyCache::Data::IsQList) v = enginePriv->scriptValueToVariant(value, qMetaTypeId >()); diff --git a/src/declarative/qml/qdeclarativeprivate.h b/src/declarative/qml/qdeclarativeprivate.h index 7ac3369fc7..fea9eae109 100644 --- a/src/declarative/qml/qdeclarativeprivate.h +++ b/src/declarative/qml/qdeclarativeprivate.h @@ -74,6 +74,9 @@ public: }; +class QScriptValue; +class QScriptEngine; +class QDeclarativeEngine; class QDeclarativeCustomParser; namespace QDeclarativePrivate { @@ -233,10 +236,22 @@ namespace QDeclarativePrivate AutoParentFunction function; }; + struct RegisterModuleApi { + int version; + + const char *uri; + int versionMajor; + int versionMinor; + + QScriptValue (*scriptApi)(QDeclarativeEngine *, QScriptEngine *); + QObject *(*qobjectApi)(QDeclarativeEngine *, QScriptEngine *); + }; + enum RegistrationType { TypeRegistration = 0, InterfaceRegistration = 1, - AutoParentRegistration = 2 + AutoParentRegistration = 2, + ModuleApiRegistration = 3, }; int Q_DECLARATIVE_EXPORT qmlregister(RegistrationType, void *); diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp index 6a39a65532..9cbb4fa8cc 100644 --- a/src/declarative/qml/qdeclarativepropertycache.cpp +++ b/src/declarative/qml/qdeclarativepropertycache.cpp @@ -61,6 +61,8 @@ QDeclarativePropertyCache::Data::Flags QDeclarativePropertyCache::Data::flagsFor flags |= Data::IsWritable; if (p.isResettable()) flags |= Data::IsResettable; + if (p.isFinal()) + flags |= Data::IsFinal; if (propType == qMetaTypeId()) { flags |= Data::IsQmlBinding; diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h index eeeff1aea1..65a8725b8f 100644 --- a/src/declarative/qml/qdeclarativepropertycache_p.h +++ b/src/declarative/qml/qdeclarativepropertycache_p.h @@ -84,20 +84,21 @@ public: IsWritable = 0x00000002, IsResettable = 0x00000004, IsAlias = 0x00000008, + IsFinal = 0x00000010, // These are mutualy exclusive - IsFunction = 0x00000010, - IsQObjectDerived = 0x00000020, - IsEnumType = 0x00000040, - IsQList = 0x00000080, - IsQmlBinding = 0x00000100, - IsQScriptValue = 0x00000200, + IsFunction = 0x00000020, + IsQObjectDerived = 0x00000040, + IsEnumType = 0x00000080, + IsQList = 0x00000100, + IsQmlBinding = 0x00000200, + IsQScriptValue = 0x00000400, // Apply only to IsFunctions - IsVMEFunction = 0x00000400, - HasArguments = 0x00000800, - IsSignal = 0x00001000, - IsVMESignal = 0x00002000 + IsVMEFunction = 0x00000800, + HasArguments = 0x00001000, + IsSignal = 0x00002000, + IsVMESignal = 0x00004000 }; Q_DECLARE_FLAGS(Flags, Flag) diff --git a/src/declarative/qml/qdeclarativescarceresourcescriptclass.cpp b/src/declarative/qml/qdeclarativescarceresourcescriptclass.cpp new file mode 100644 index 0000000000..121d0a1a35 --- /dev/null +++ b/src/declarative/qml/qdeclarativescarceresourcescriptclass.cpp @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qdeclarativescarceresourcescriptclass_p.h" + +#include "private/qdeclarativeengine_p.h" +#include "private/qdeclarativecontext_p.h" +#include "private/qdeclarativedata_p.h" +#include "private/qdeclarativetypenamescriptclass_p.h" +#include "private/qdeclarativelistscriptclass_p.h" +#include "private/qdeclarativebinding_p.h" +#include "private/qdeclarativeguard_p.h" +#include "private/qdeclarativevmemetaobject_p.h" + +#include +#include +#include + +Q_DECLARE_METATYPE(QScriptValue); + +QT_BEGIN_NAMESPACE + +QDeclarativeScarceResourceScriptClass::QDeclarativeScarceResourceScriptClass(QDeclarativeEngine *bindEngine) + : QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine) +{ + QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); + + // Properties of this type can be explicitly preserved by clients, + // which prevents the scarce resource from being automatically + // released after the binding has been evaluated. + m_preserve = scriptEngine->newFunction(preserve); + m_preserveId = createPersistentIdentifier(QLatin1String("preserve")); + + // Similarly, they can be explicitly destroyed by clients, + // which releases the scarce resource. + m_destroy = scriptEngine->newFunction(destroy); + m_destroyId = createPersistentIdentifier(QLatin1String("destroy")); +} + +QDeclarativeScarceResourceScriptClass::~QDeclarativeScarceResourceScriptClass() +{ +} + +/* + Returns a JavaScript object whose instance data is a new scarce resource data. + The scarce resource is added to the doubly-linked-list of scarce resources in the engine + so that the scarce resource can be released after evaluation completes. + */ +QScriptValue QDeclarativeScarceResourceScriptClass::newScarceResource(const QVariant &v) +{ + // create the scarce resource + ScarceResourceData *srd = new ScarceResourceData(v); + + // insert into the linked list + QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine); + srd->insertInto(&enginePrivate->scarceResources); + Q_ASSERT(enginePrivate->scarceResourcesRefCount > 0); + + // return the javascript object with the scarce resource instance data + QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); + return QScriptDeclarativeClass::newObject(scriptEngine, this, srd); // JSC takes ownership of srd. +} + +QVariant QDeclarativeScarceResourceScriptClass::toVariant(Object *object, bool *ok) +{ + ScarceResourceData *obj = static_cast(object); + if (ok) *ok = true; + return obj->resource; +} + +QVariant QDeclarativeScarceResourceScriptClass::toVariant(const QScriptValue &value) +{ + Q_ASSERT(scriptClass(value) == this); + + return toVariant(object(value), 0); +} + +// The destroy() and preserve() function properties are readable. +QScriptClass::QueryFlags +QDeclarativeScarceResourceScriptClass::queryProperty(Object *object, const Identifier &name, + QScriptClass::QueryFlags flags) +{ + Q_UNUSED(object) + Q_UNUSED(flags) + + if (name == m_destroyId.identifier || name == m_preserveId.identifier) + return (QScriptClass::HandlesReadAccess); + return 0; +} + +// Return the (function) values which may be evaluated by clients. +QDeclarativeScarceResourceScriptClass::Value +QDeclarativeScarceResourceScriptClass::property(Object *object, const Identifier &name) +{ + Q_UNUSED(object) + + QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); + + // functions + if (name == m_preserveId.identifier) + return Value(scriptEngine, m_preserve); + else if (name == m_destroyId.identifier) + return Value(scriptEngine, m_destroy); + + return Value(); +} + +/* + The user explicitly wants to preserve the resource. + We remove the scarce resource from the engine's linked list + of resources to release after evaluation completes. + */ +QScriptValue QDeclarativeScarceResourceScriptClass::preserve(QScriptContext *context, QScriptEngine *engine) +{ + QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine); + QScriptValue that = context->thisObject(); + + if (scriptClass(that) != p->scarceResourceClass) + return engine->undefinedValue(); + + // The client wishes to preserve the resource in this SRD. + ScarceResourceData *data = static_cast(p->scarceResourceClass->object(that)); + if (!data) + return engine->undefinedValue(); + + // remove node from list, without releasing the resource. + data->removeNode(); + + return engine->undefinedValue(); +} + +/* + The user explicitly wants to release the resource. + We set the internal scarce resource variant to the invalid variant. + */ +QScriptValue QDeclarativeScarceResourceScriptClass::destroy(QScriptContext *context, QScriptEngine *engine) +{ + QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine); + QScriptValue that = context->thisObject(); + + if (scriptClass(that) != p->scarceResourceClass) + return engine->undefinedValue(); + + // the client wishes to release the resource in this SRD. + ScarceResourceData *data = static_cast(p->scarceResourceClass->object(that)); + if (!data) + return engine->undefinedValue(); + + // release the resource and remove the node from the list. + data->releaseResource(); + + return engine->undefinedValue(); +} + +QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativescarceresourcescriptclass_p.h b/src/declarative/qml/qdeclarativescarceresourcescriptclass_p.h new file mode 100644 index 0000000000..2a1390a230 --- /dev/null +++ b/src/declarative/qml/qdeclarativescarceresourcescriptclass_p.h @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVESCARCERESOURCESCRIPTCLASS_P_H +#define QDECLARATIVESCARCERESOURCESCRIPTCLASS_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 "private/qdeclarativepropertycache_p.h" +#include "private/qdeclarativetypenamecache_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativeEngine; + +/* + Scarce resources (like pixmaps and textures) are managed manually + in that the variant will be set to the invalid variant once the + JavaScript engine has finished using the JavaScript object whose + instance data is the ScarceResourceData (but before the garbage + collector frees the JavaScript object itself). + + The engine stores a doubly-linked-list of scarce resources which + will to be cleaned up after a binding is successfully evaluated + (unless the user explicitly preserves the scarce resource). + + A ScarceResourceData pointer should not be deleted manually, as + all instances of a ScarceResourceData should be owned by the + JavaScript engine. + */ +struct ScarceResourceData : public QScriptDeclarativeClass::Object { + ScarceResourceData(const QVariant &v) : resource(v), prev(0), next(0) + { + } + + virtual ~ScarceResourceData() + { + releaseResource(); + } + + // Insert this resource into the given list of resources. + void insertInto(ScarceResourceData **list) + { + // This node becomes the head of the list. + next = *list; // so our next = old list head + *list = this; // list now points to us (we're the head) + prev = list; // as we're the head, our prev ptr becomes the list ptr. + + // and the next node's prev pointer must contain a ptr to our next ptr, + // since per definition, prev always contains a pointer to the previous node's "next" ptr, + // and the "this" node is the "this->next" node's "prev" node. + if (next) next->prev = &next; + } + + // Remove this resource from the list of resources, without releasing the resource. + void removeNode() + { + // whatever previously pointed to this node (ie, as that node's "next" node) + // should now point to our next node (since we no longer exist in the list). + // and the next node's prev ptr should point to our prev node. + if (prev) *prev = next; + if (next) next->prev = prev; + prev = 0; + next = 0; + } + + // Release this resource, and remove from the list. + void releaseResource() + { + resource = QVariant(); + removeNode(); + } + + QVariant resource; + + // prev always contains a pointer to the previous node's "next" ptr. + // :. for the head node, [*prev] will be engine->scarceResources + // :. for every other node, [*prev] will be the previous node's "next" ptr. + ScarceResourceData **prev; + ScarceResourceData *next; +}; + +class Q_AUTOTEST_EXPORT QDeclarativeScarceResourceScriptClass : public QScriptDeclarativeClass +{ +public: + QDeclarativeScarceResourceScriptClass(QDeclarativeEngine *); + ~QDeclarativeScarceResourceScriptClass(); + + // Creates a new JavaScript object whose instance data is the scarce resource v + QScriptValue newScarceResource(const QVariant &v); + + // inherited from QScriptDeclarativeClass + virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, + QScriptClass::QueryFlags flags); + virtual Value property(Object *, const Identifier &); + virtual QVariant toVariant(Object *, bool *ok = 0); + QVariant toVariant(const QScriptValue &value); + +private: + PersistentIdentifier m_preserveId; + PersistentIdentifier m_destroyId; + QScriptValue m_preserve; + QScriptValue m_destroy; + + static QScriptValue preserve(QScriptContext *context, QScriptEngine *engine); + static QScriptValue destroy(QScriptContext *context, QScriptEngine *engine); + + QDeclarativeEngine *engine; +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVESCARCERESOURCESCRIPTCLASS_P_H diff --git a/src/declarative/qml/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescriptparser.cpp index e04cfc52af..352e341437 100644 --- a/src/declarative/qml/qdeclarativescriptparser.cpp +++ b/src/declarative/qml/qdeclarativescriptparser.cpp @@ -59,6 +59,22 @@ QT_BEGIN_NAMESPACE using namespace QDeclarativeJS; using namespace QDeclarativeParser; +void QDeclarativeScriptParser::Import::extractVersion(int *maj, int *min) const +{ + *maj = -1; *min = -1; + + if (!version.isEmpty()) { + int dot = version.indexOf(QLatin1Char('.')); + if (dot < 0) { + *maj = version.toInt(); + *min = 0; + } else { + *maj = version.left(dot).toInt(); + *min = version.mid(dot+1).toInt(); + } + } +} + namespace { class ProcessAST: protected AST::Visitor @@ -896,6 +912,19 @@ static void replaceWithSpace(QString &str, int idx, int n) *data++ = space; } +static QDeclarativeParser::LocationSpan +locationFromLexer(const QDeclarativeJS::Lexer &lex, int startLine, int startColumn, int startOffset) +{ + QDeclarativeParser::LocationSpan l; + + l.start.line = startLine; l.start.column = startColumn; + l.end.line = lex.endLineNo(); l.end.column = lex.endColumnNo(); + l.range.offset = startOffset; + l.range.length = lex.tokenOffset() + lex.tokenLength() - startOffset; + + return l; +} + /* Searches for ".pragma " declarations within \a script. Currently supported pragmas are: @@ -1024,7 +1053,8 @@ QDeclarativeScriptParser::JavaScriptMetaData QDeclarativeScriptParser::extractMe return rv; int startOffset = l.tokenOffset(); - int startLine = l.currentLineNo(); + int startLine = l.startLineNo(); + int startColumn = l.startColumnNo(); token = l.lex(); @@ -1062,8 +1092,11 @@ QDeclarativeScriptParser::JavaScriptMetaData QDeclarativeScriptParser::extractMe if (!importId.at(0).isUpper()) return rv; + QDeclarativeParser::LocationSpan location = + locationFromLexer(l, startLine, startColumn, startOffset); + token = l.lex(); - if (l.currentLineNo() == startLine) + if (l.startLineNo() == startLine) return rv; replaceWithSpace(script, startOffset, endOffset - startOffset); @@ -1072,9 +1105,9 @@ QDeclarativeScriptParser::JavaScriptMetaData QDeclarativeScriptParser::extractMe import.type = Import::Script; import.uri = file; import.qualifier = importId; + import.location = location; rv.imports << import; - } else { // URI QString uri; @@ -1117,8 +1150,11 @@ QDeclarativeScriptParser::JavaScriptMetaData QDeclarativeScriptParser::extractMe if (!importId.at(0).isUpper()) return rv; + QDeclarativeParser::LocationSpan location = + locationFromLexer(l, startLine, startColumn, startOffset); + token = l.lex(); - if (l.currentLineNo() == startLine) + if (l.startLineNo() == startLine) return rv; replaceWithSpace(script, startOffset, endOffset - startOffset); @@ -1128,6 +1164,7 @@ QDeclarativeScriptParser::JavaScriptMetaData QDeclarativeScriptParser::extractMe import.uri = uri; import.version = version; import.qualifier = importId; + import.location = location; rv.imports << import; } @@ -1143,7 +1180,7 @@ QDeclarativeScriptParser::JavaScriptMetaData QDeclarativeScriptParser::extractMe QString pragmaValue = script.mid(l.tokenOffset(), l.tokenLength()); int endOffset = l.tokenLength() + l.tokenOffset(); - if (pragmaValue == QLatin1String("library")) { + if (pragmaValue == library) { pragmas |= QDeclarativeParser::Object::ScriptBlock::Shared; replaceWithSpace(script, startOffset, endOffset - startOffset); } else { diff --git a/src/declarative/qml/qdeclarativescriptparser_p.h b/src/declarative/qml/qdeclarativescriptparser_p.h index e5e0d7075d..fd89f757cc 100644 --- a/src/declarative/qml/qdeclarativescriptparser_p.h +++ b/src/declarative/qml/qdeclarativescriptparser_p.h @@ -82,6 +82,8 @@ public: QString qualifier; QString version; + void extractVersion(int *maj, int *min) const; + QDeclarativeParser::LocationSpan location; }; diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp index 26f3996871..1c1eeee2cf 100644 --- a/src/declarative/qml/qdeclarativetypeloader.cpp +++ b/src/declarative/qml/qdeclarativetypeloader.cpp @@ -607,7 +607,7 @@ void QDeclarativeDataLoader::setData(QDeclarativeDataBlob *blob, const QByteArra if (!blob->isError() && !blob->isWaiting()) blob->allDependenciesDone(); - if (blob->status() != QDeclarativeDataBlob::Error) + if (blob->status() != QDeclarativeDataBlob::Error) blob->m_status = QDeclarativeDataBlob::WaitingForDependencies; blob->m_inCallback = false; @@ -674,24 +674,23 @@ QDeclarativeTypeData *QDeclarativeTypeLoader::get(const QByteArray &data, const } /*! -Return a QDeclarativeScriptData for \a url. The QDeclarativeScriptData may be cached. +Return a QDeclarativeScriptBlob for \a url. The QDeclarativeScriptData may be cached. */ -QDeclarativeScriptData *QDeclarativeTypeLoader::getScript(const QUrl &url) +QDeclarativeScriptBlob *QDeclarativeTypeLoader::getScript(const QUrl &url) { Q_ASSERT(!url.isRelative() && (QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url).isEmpty() || !QDir::isRelativePath(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url)))); - QDeclarativeScriptData *scriptData = m_scriptCache.value(url); + QDeclarativeScriptBlob *scriptBlob = m_scriptCache.value(url); - if (!scriptData) { - scriptData = new QDeclarativeScriptData(url); - m_scriptCache.insert(url, scriptData); - QDeclarativeDataLoader::load(scriptData); + if (!scriptBlob) { + scriptBlob = new QDeclarativeScriptBlob(url, this); + m_scriptCache.insert(url, scriptBlob); + QDeclarativeDataLoader::load(scriptBlob); } - scriptData->addref(); - return scriptData; + return scriptBlob; } /*! @@ -868,13 +867,14 @@ void QDeclarativeTypeData::dataReceived(const QByteArray &data) } } else if (import.type == QDeclarativeScriptParser::Import::Script) { QUrl scriptUrl = finalUrl().resolved(QUrl(import.uri)); - QDeclarativeScriptData *data = typeLoader()->getScript(scriptUrl); - addDependency(data); + QDeclarativeScriptBlob *blob = typeLoader()->getScript(scriptUrl); + addDependency(blob); ScriptReference ref; ref.location = import.location.start; ref.qualifier = import.qualifier; - ref.script = data; + ref.script = blob; + blob->addref(); m_scripts << ref; } @@ -933,14 +933,31 @@ void QDeclarativeTypeData::resolveTypes() // For local urls, add an implicit import "." as first (most overridden) lookup. // This will also trigger the loading of the qmldir and the import of any native // types from available plugins. + QList errors; if (QDeclarativeQmldirData *qmldir = qmldirForUrl(finalUrl().resolved(QUrl(QLatin1String("./qmldir"))))) { m_imports.addImport(importDatabase, QLatin1String("."), QString(), -1, -1, QDeclarativeScriptParser::Import::File, - qmldir->dirComponents(), 0); + qmldir->dirComponents(), &errors); } else { m_imports.addImport(importDatabase, QLatin1String("."), QString(), -1, -1, QDeclarativeScriptParser::Import::File, - QDeclarativeDirComponents(), 0); + QDeclarativeDirComponents(), &errors); + } + + // remove any errors which are due to the implicit import which aren't real errors. + // for example, if the implicitly included qmldir file doesn't exist, that is not an error. + QList realErrors; + for (int i = 0; i < errors.size(); ++i) { + if (errors.at(i).description() != QDeclarativeImportDatabase::tr("import \".\" has no qmldir and no namespace") + && errors.at(i).description() != QDeclarativeImportDatabase::tr("\".\": no such directory")) { + realErrors.prepend(errors.at(i)); // this is a real error. + } + } + + // report any real errors which occurred during plugin loading or qmldir parsing. + if (!realErrors.isEmpty()) { + setError(realErrors); + return; } foreach (const QDeclarativeScriptParser::Import &import, scriptParser.imports()) { @@ -950,34 +967,31 @@ void QDeclarativeTypeData::resolveTypes() if (import.type == QDeclarativeScriptParser::Import::File && import.qualifier.isEmpty()) { QUrl qmldirUrl = finalUrl().resolved(QUrl(import.uri + QLatin1String("/qmldir"))); - if (QDeclarativeQmldirData *qmldir = qmldirForUrl(qmldirUrl)) + if (QDeclarativeQmldirData *qmldir = qmldirForUrl(qmldirUrl)) qmldircomponentsnetwork = qmldir->dirComponents(); } int vmaj = -1; int vmin = -1; + import.extractVersion(&vmaj, &vmin); - if (!import.version.isEmpty()) { - int dot = import.version.indexOf(QLatin1Char('.')); - if (dot < 0) { - vmaj = import.version.toInt(); - vmin = 0; - } else { - vmaj = import.version.left(dot).toInt(); - vmin = import.version.mid(dot+1).toInt(); - } - } - - QString errorString; + QList errors; if (!m_imports.addImport(importDatabase, import.uri, import.qualifier, - vmaj, vmin, import.type, qmldircomponentsnetwork, &errorString)) { + vmaj, vmin, import.type, qmldircomponentsnetwork, &errors)) { QDeclarativeError error; + if (errors.size()) { + error = errors.takeFirst(); + } else { + // this should not be possible! + // Description should come from error provided by addImport() function. + error.setDescription(QDeclarativeTypeLoader::tr("Unreported error adding script import to import database")); + } error.setUrl(m_imports.baseUrl()); - error.setDescription(errorString); error.setLine(import.location.start.line); error.setColumn(import.location.start.column); + errors.prepend(error); // put it back on the list after filling out information. - setError(error); + setError(errors); return; } } @@ -991,29 +1005,38 @@ void QDeclarativeTypeData::resolveTypes() int majorVersion; int minorVersion; QDeclarativeImportedNamespace *typeNamespace = 0; - QString errorString; + QList errors; if (!m_imports.resolveType(typeName, &ref.type, &url, &majorVersion, &minorVersion, - &typeNamespace, &errorString) || typeNamespace) { + &typeNamespace, &errors) || typeNamespace) { // Known to not be a type: // - known to be a namespace (Namespace {}) // - type with unknown namespace (UnknownNamespace.SomeType {}) QDeclarativeError error; - error.setUrl(m_imports.baseUrl()); QString userTypeName = parserRef->name; userTypeName.replace(QLatin1Char('/'),QLatin1Char('.')); - if (typeNamespace) + if (typeNamespace) { error.setDescription(QDeclarativeTypeLoader::tr("Namespace %1 cannot be used as a type").arg(userTypeName)); - else - error.setDescription(QDeclarativeTypeLoader::tr("%1 %2").arg(userTypeName).arg(errorString)); + } else { + if (errors.size()) { + error = errors.takeFirst(); + } else { + // this should not be possible! + // Description should come from error provided by addImport() function. + error.setDescription(QDeclarativeTypeLoader::tr("Unreported error adding script import to import database")); + } + error.setUrl(m_imports.baseUrl()); + error.setDescription(QDeclarativeTypeLoader::tr("%1 %2").arg(userTypeName).arg(error.description())); + } if (!parserRef->refObjects.isEmpty()) { QDeclarativeParser::Object *obj = parserRef->refObjects.first(); error.setLine(obj->location.start.line); error.setColumn(obj->location.start.column); } - - setError(error); + + errors.prepend(error); + setError(errors); return; } @@ -1046,25 +1069,156 @@ QDeclarativeQmldirData *QDeclarativeTypeData::qmldirForUrl(const QUrl &url) return 0; } -QDeclarativeScriptData::QDeclarativeScriptData(const QUrl &url) -: QDeclarativeDataBlob(url, JavaScriptFile), m_pragmas(QDeclarativeParser::Object::ScriptBlock::None) +QDeclarativeScriptData::QDeclarativeScriptData(QDeclarativeEngine *engine) +: QDeclarativeCleanup(engine), importCache(0), pragmas(QDeclarativeParser::Object::ScriptBlock::None), + m_loaded(false) +{ +} + +QDeclarativeScriptData::~QDeclarativeScriptData() { + clear(); } -QDeclarativeParser::Object::ScriptBlock::Pragmas QDeclarativeScriptData::pragmas() const +void QDeclarativeScriptData::clear() +{ + if (importCache) { + importCache->release(); + importCache = 0; + } + + for (int ii = 0; ii < scripts.count(); ++ii) + scripts.at(ii)->release(); + scripts.clear(); +} + +QDeclarativeScriptBlob::QDeclarativeScriptBlob(const QUrl &url, QDeclarativeTypeLoader *loader) +: QDeclarativeDataBlob(url, JavaScriptFile), m_pragmas(QDeclarativeParser::Object::ScriptBlock::None), + m_scriptData(0), m_typeLoader(loader) +{ +} + +QDeclarativeScriptBlob::~QDeclarativeScriptBlob() +{ + if (m_scriptData) { + m_scriptData->release(); + m_scriptData = 0; + } +} + +QDeclarativeParser::Object::ScriptBlock::Pragmas QDeclarativeScriptBlob::pragmas() const { return m_pragmas; } -QString QDeclarativeScriptData::scriptSource() const +QString QDeclarativeScriptBlob::scriptSource() const { return m_source; } -void QDeclarativeScriptData::dataReceived(const QByteArray &data) +QDeclarativeTypeLoader *QDeclarativeScriptBlob::typeLoader() const +{ + return m_typeLoader; +} + +const QDeclarativeImports &QDeclarativeScriptBlob::imports() const +{ + return m_imports; +} + +QDeclarativeScriptData *QDeclarativeScriptBlob::scriptData() const +{ + return m_scriptData; +} + +void QDeclarativeScriptBlob::dataReceived(const QByteArray &data) { + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(m_typeLoader->engine()); + QDeclarativeImportDatabase *importDatabase = &ep->importDatabase; + m_source = QString::fromUtf8(data); - m_pragmas = QDeclarativeScriptParser::extractPragmas(m_source); + + QDeclarativeScriptParser::JavaScriptMetaData metadata = + QDeclarativeScriptParser::extractMetaData(m_source); + + m_imports.setBaseUrl(finalUrl()); + + m_pragmas = metadata.pragmas; + + foreach (const QDeclarativeScriptParser::Import &import, metadata.imports) { + Q_ASSERT(import.type != QDeclarativeScriptParser::Import::File); + + if (import.type == QDeclarativeScriptParser::Import::Script) { + QUrl scriptUrl = finalUrl().resolved(QUrl(import.uri)); + QDeclarativeScriptBlob *blob = typeLoader()->getScript(scriptUrl); + addDependency(blob); + + ScriptReference ref; + ref.location = import.location.start; + ref.qualifier = import.qualifier; + ref.script = blob; + blob->addref(); + m_scripts << ref; + } else { + Q_ASSERT(import.type == QDeclarativeScriptParser::Import::Library); + int vmaj = -1; + int vmin = -1; + import.extractVersion(&vmaj, &vmin); + + QList errors; + if (!m_imports.addImport(importDatabase, import.uri, import.qualifier, vmaj, vmin, + import.type, QDeclarativeDirComponents(), &errors)) { + QDeclarativeError error = errors.takeFirst(); + // description should be set by addImport(). + error.setUrl(m_imports.baseUrl()); + error.setLine(import.location.start.line); + error.setColumn(import.location.start.column); + errors.prepend(error); + + setError(errors); + return; + } + } + } +} + +void QDeclarativeScriptBlob::done() +{ + // Check all script dependencies for errors + for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) { + const ScriptReference &script = m_scripts.at(ii); + Q_ASSERT(script.script->isCompleteOrError()); + if (script.script->isError()) { + QList errors = script.script->errors(); + QDeclarativeError error; + error.setUrl(finalUrl()); + error.setLine(script.location.line); + error.setColumn(script.location.column); + error.setDescription(typeLoader()->tr("Script %1 unavailable").arg(script.script->url().toString())); + errors.prepend(error); + setError(errors); + } + } + + if (isError()) + return; + + QDeclarativeEngine *engine = typeLoader()->engine(); + m_scriptData = new QDeclarativeScriptData(engine); + m_scriptData->url = finalUrl(); + m_scriptData->importCache = new QDeclarativeTypeNameCache(engine); + + for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) { + const ScriptReference &script = m_scripts.at(ii); + + m_scriptData->scripts.append(script.script); + m_scriptData->importCache->add(script.qualifier, ii); + } + + m_imports.populateCache(m_scriptData->importCache, engine); + + m_scriptData->pragmas = m_pragmas; + m_scriptData->m_program = QScriptProgram(m_source, finalUrl().toString()); } QDeclarativeQmldirData::QDeclarativeQmldirData(const QUrl &url) diff --git a/src/declarative/qml/qdeclarativetypeloader_p.h b/src/declarative/qml/qdeclarativetypeloader_p.h index 7f487a0e24..1c0798d67b 100644 --- a/src/declarative/qml/qdeclarativetypeloader_p.h +++ b/src/declarative/qml/qdeclarativetypeloader_p.h @@ -55,8 +55,11 @@ #include #include +#include +#include #include #include +#include #include #include #include @@ -64,6 +67,7 @@ QT_BEGIN_NAMESPACE class QDeclarativeScriptData; +class QDeclarativeScriptBlob; class QDeclarativeQmldirData; class QDeclarativeTypeLoader; class QDeclarativeCompiledData; @@ -140,7 +144,7 @@ private: QUrl m_finalUrl; // List of QDeclarativeDataBlob's that are waiting for me to complete. - QList m_waitingOnMe; + QList m_waitingOnMe; // List of QDeclarativeDataBlob's that I am waiting for to complete. QList m_waitingFor; @@ -178,7 +182,6 @@ private: NetworkReplies m_networkReplies; }; - class Q_AUTOTEST_EXPORT QDeclarativeTypeLoader : public QDeclarativeDataLoader { Q_OBJECT @@ -196,11 +199,11 @@ public: QDeclarativeTypeData *get(const QByteArray &, const QUrl &url, Options = None); void clearCache(); - QDeclarativeScriptData *getScript(const QUrl &); + QDeclarativeScriptBlob *getScript(const QUrl &); QDeclarativeQmldirData *getQmldir(const QUrl &); private: typedef QHash TypeCache; - typedef QHash ScriptCache; + typedef QHash ScriptCache; typedef QHash QmldirCache; TypeCache m_typeCache; @@ -230,7 +233,7 @@ public: QDeclarativeParser::Location location; QString qualifier; - QDeclarativeScriptData *script; + QDeclarativeScriptBlob *script; }; QDeclarativeTypeData(const QUrl &, QDeclarativeTypeLoader::Options, QDeclarativeTypeLoader *); @@ -285,20 +288,65 @@ private: QDeclarativeTypeLoader *m_typeLoader; }; -class Q_AUTOTEST_EXPORT QDeclarativeScriptData : public QDeclarativeDataBlob +class Q_AUTOTEST_EXPORT QDeclarativeScriptData : public QDeclarativeRefCount, public QDeclarativeCleanup { public: - QDeclarativeScriptData(const QUrl &); + QDeclarativeScriptData(QDeclarativeEngine *); + ~QDeclarativeScriptData(); + + QUrl url; + QDeclarativeTypeNameCache *importCache; + QList scripts; + QDeclarativeParser::Object::ScriptBlock::Pragmas pragmas; + +protected: + virtual void clear(); // From QDeclarativeCleanup + +private: + friend class QDeclarativeVME; + friend class QDeclarativeScriptBlob; + + bool m_loaded; + QScriptProgram m_program; + QScriptValue m_value; +}; + +class Q_AUTOTEST_EXPORT QDeclarativeScriptBlob : public QDeclarativeDataBlob +{ +public: + QDeclarativeScriptBlob(const QUrl &, QDeclarativeTypeLoader *); + ~QDeclarativeScriptBlob(); + + struct ScriptReference + { + ScriptReference() : script(0) {} + + QDeclarativeParser::Location location; + QString qualifier; + QDeclarativeScriptBlob *script; + }; QDeclarativeParser::Object::ScriptBlock::Pragmas pragmas() const; QString scriptSource() const; + QDeclarativeTypeLoader *typeLoader() const; + const QDeclarativeImports &imports() const; + + QDeclarativeScriptData *scriptData() const; + protected: virtual void dataReceived(const QByteArray &); + virtual void done(); private: QDeclarativeParser::Object::ScriptBlock::Pragmas m_pragmas; QString m_source; + + QDeclarativeImports m_imports; + QList m_scripts; + QDeclarativeScriptData *m_scriptData; + + QDeclarativeTypeLoader *m_typeLoader; }; class Q_AUTOTEST_EXPORT QDeclarativeQmldirData : public QDeclarativeDataBlob diff --git a/src/declarative/qml/qdeclarativetypenamecache.cpp b/src/declarative/qml/qdeclarativetypenamecache.cpp index 48c72a7fef..b9577c17fa 100644 --- a/src/declarative/qml/qdeclarativetypenamecache.cpp +++ b/src/declarative/qml/qdeclarativetypenamecache.cpp @@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE QDeclarativeTypeNameCache::QDeclarativeTypeNameCache(QDeclarativeEngine *e) -: QDeclarativeCleanup(e), engine(e) +: QDeclarativeCleanup(e), engine(e), m_moduleApi(0) { } @@ -60,6 +60,7 @@ void QDeclarativeTypeNameCache::clear() qDeleteAll(stringCache); stringCache.clear(); identifierCache.clear(); + m_moduleApi = 0; engine = 0; } @@ -114,5 +115,10 @@ QDeclarativeTypeNameCache::Data *QDeclarativeTypeNameCache::data(const QString & return stringCache.value(id); } +void QDeclarativeTypeNameCache::setModuleApi(QDeclarativeMetaType::ModuleApiInstance *api) +{ + m_moduleApi = api; +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativetypenamecache_p.h b/src/declarative/qml/qdeclarativetypenamecache_p.h index f2562da777..bcca41f4d5 100644 --- a/src/declarative/qml/qdeclarativetypenamecache_p.h +++ b/src/declarative/qml/qdeclarativetypenamecache_p.h @@ -55,6 +55,7 @@ #include "private/qdeclarativerefcount_p.h" #include "private/qdeclarativecleanup_p.h" +#include "private/qdeclarativemetatype_p.h" #include @@ -82,6 +83,10 @@ public: Data *data(const QString &) const; inline Data *data(const QScriptDeclarativeClass::Identifier &id) const; + inline bool isEmpty() const; + + inline QDeclarativeMetaType::ModuleApiInstance *moduleApi() const; + void setModuleApi(QDeclarativeMetaType::ModuleApiInstance *); protected: virtual void clear(); @@ -96,6 +101,7 @@ private: StringCache stringCache; IdentifierCache identifierCache; QDeclarativeEngine *engine; + QDeclarativeMetaType::ModuleApiInstance *m_moduleApi; }; QDeclarativeTypeNameCache::Data::Data() @@ -113,6 +119,16 @@ QDeclarativeTypeNameCache::Data *QDeclarativeTypeNameCache::data(const QScriptDe return identifierCache.value(id); } +bool QDeclarativeTypeNameCache::isEmpty() const +{ + return identifierCache.isEmpty(); +} + +QDeclarativeMetaType::ModuleApiInstance *QDeclarativeTypeNameCache::moduleApi() const +{ + return m_moduleApi; +} + QT_END_NAMESPACE #endif // QDECLARATIVETYPENAMECACHE_P_H diff --git a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp b/src/declarative/qml/qdeclarativetypenamescriptclass.cpp index a7c0b2cfbe..d628b7065a 100644 --- a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp +++ b/src/declarative/qml/qdeclarativetypenamescriptclass.cpp @@ -63,7 +63,7 @@ struct TypeNameData : public QScriptDeclarativeClass::Object { QDeclarativeTypeNameScriptClass::QDeclarativeTypeNameScriptClass(QDeclarativeEngine *bindEngine) : QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), - engine(bindEngine), object(0), type(0) + engine(bindEngine), object(0), type(0), api(0) { } @@ -95,14 +95,35 @@ QDeclarativeTypeNameScriptClass::queryProperty(Object *obj, const Identifier &na object = 0; type = 0; + api = 0; QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); if (data->typeNamespace) { - QDeclarativeTypeNameCache::Data *d = data->typeNamespace->data(name); if (d && d->type) { type = d->type; return QScriptClass::HandlesReadAccess; + } else if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = data->typeNamespace->moduleApi()) { + if (moduleApi->scriptCallback) { + moduleApi->scriptApi = moduleApi->scriptCallback(engine, &ep->scriptEngine); + moduleApi->scriptCallback = 0; + moduleApi->qobjectCallback = 0; + } else if (moduleApi->qobjectCallback) { + moduleApi->qobjectApi = moduleApi->qobjectCallback(engine, &ep->scriptEngine); + moduleApi->scriptCallback = 0; + moduleApi->qobjectCallback = 0; + } + + api = moduleApi; + if (api->qobjectApi) { + return ep->objectClass->queryProperty(api->qobjectApi, name, flags, 0, + QDeclarativeObjectScriptClass::SkipAttachedProperties); + } else { + return QScriptClass::HandlesReadAccess; + } + + return 0; + } else { return 0; } @@ -147,6 +168,10 @@ QDeclarativeTypeNameScriptClass::property(Object *obj, const Identifier &name) return Value(scriptEngine, newObject(((TypeNameData *)obj)->object, type, ((TypeNameData *)obj)->mode)); } else if (object) { return ep->objectClass->property(object, name); + } else if (api && api->qobjectApi) { + return ep->objectClass->property(api->qobjectApi, name); + } else if (api) { + return propertyValue(api->scriptApi, name); } else { return Value(scriptEngine, enumValue); } @@ -154,11 +179,16 @@ QDeclarativeTypeNameScriptClass::property(Object *obj, const Identifier &name) void QDeclarativeTypeNameScriptClass::setProperty(Object *, const Identifier &n, const QScriptValue &v) { - Q_ASSERT(object); Q_ASSERT(!type); QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); - ep->objectClass->setProperty(object, n, v, context()); + if (api) { + Q_ASSERT(api->qobjectApi); + ep->objectClass->setProperty(api->qobjectApi, n, v, context()); + } else { + Q_ASSERT(object); + ep->objectClass->setProperty(object, n, v, context()); + } } QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativetypenamescriptclass_p.h b/src/declarative/qml/qdeclarativetypenamescriptclass_p.h index cf7dbc8480..49e1ae809e 100644 --- a/src/declarative/qml/qdeclarativetypenamescriptclass_p.h +++ b/src/declarative/qml/qdeclarativetypenamescriptclass_p.h @@ -83,6 +83,7 @@ private: QDeclarativeEngine *engine; QObject *object; QDeclarativeType *type; + QDeclarativeMetaType::ModuleApiInstance *api; quint32 enumValue; }; diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index 781e1b8ea3..6bbc47bcaf 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -57,8 +57,9 @@ #include "private/qdeclarativevmemetaobject_p.h" #include "private/qdeclarativebinding_p_p.h" #include "private/qdeclarativecontext_p.h" -#include "private/qdeclarativecompiledbindings_p.h" +#include "private/qdeclarativev4bindings_p.h" #include "private/qdeclarativeglobal_p.h" +#include "private/qdeclarativeglobalscriptclass_p.h" #include "qdeclarativescriptstring.h" #include @@ -71,6 +72,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -158,7 +160,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, const QList &intData = comp->intData; const QList &floatData = comp->floatData; const QList &propertyCaches = comp->propertyCaches; - const QList &scripts = comp->scripts; + const QList &scripts = comp->scripts; const QList &urls = comp->urls; QDeclarativeEnginePrivate::SimpleList bindValues; @@ -186,7 +188,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, if (instr.init.contextCache != -1) ctxt->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache)); if (instr.init.compiledBinding != -1) - ctxt->optimizedBindings = new QDeclarativeCompiledBindings(datas.at(instr.init.compiledBinding).constData(), ctxt); + ctxt->optimizedBindings = new QDeclarativeV4Bindings(datas.at(instr.init.compiledBinding).constData(), ctxt); } break; @@ -409,6 +411,15 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, } break; + case QDeclarativeInstruction::StoreByteArray: + { + QObject *target = stack.top(); + void *a[] = { (void *)&datas.at(instr.storeByteArray.value), 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.storeByteArray.propertyIndex, a); + } + break; + case QDeclarativeInstruction::StoreUrl: { QObject *target = stack.top(); @@ -701,7 +712,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, case QDeclarativeInstruction::StoreImportedScript: { - ctxt->addImportedScript(scripts.at(instr.storeScript.value)); + ctxt->importedScripts << run(ctxt, scripts.at(instr.storeScript.value)); } break; @@ -1054,5 +1065,68 @@ QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData } } +QScriptValue QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script) +{ + if (script->m_loaded) + return script->m_value; + + QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(parentCtxt->engine); + QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(parentCtxt->engine); + + bool shared = script->pragmas & QDeclarativeParser::Object::ScriptBlock::Shared; + + // Create the script context if required + QDeclarativeContextData *ctxt = 0; + if (!shared) { + ctxt = new QDeclarativeContextData; + ctxt->isInternal = true; + ctxt->url = script->url; + + // For backward compatibility, if there are no imports, we need to use the + // imports from the parent context. See QTBUG-17518. + if (!script->importCache->isEmpty()) { + ctxt->imports = script->importCache; + } else { + ctxt->imports = parentCtxt->imports; + } + + if (ctxt->imports) { + ctxt->imports->addref(); + } + + ctxt->setParent(parentCtxt, true); + + for (int ii = 0; ii < script->scripts.count(); ++ii) + ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData()); + } + + QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); + if (shared) { + scriptContext->pushScope(enginePriv->contextClass->newUrlContext(script->url.toString())); // XXX toString()? + } else { + scriptContext->pushScope(enginePriv->contextClass->newUrlContext(ctxt, 0, script->url.toString())); + } + + scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject()); + QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine); + scriptContext->pushScope(scope); + + scriptEngine->evaluate(script->m_program); + + if (scriptEngine->hasUncaughtException()) { + QDeclarativeError error; + QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error); + enginePriv->warning(error); + } + + scriptEngine->popContext(); + + if (shared) { + script->m_loaded = true; + script->m_value = scope; + } + + return scope; +} QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativevme_p.h b/src/declarative/qml/qdeclarativevme_p.h index 77c016c1a8..4c010f19d8 100644 --- a/src/declarative/qml/qdeclarativevme_p.h +++ b/src/declarative/qml/qdeclarativevme_p.h @@ -62,6 +62,8 @@ QT_BEGIN_NAMESPACE class QObject; +class QScriptValue; +class QDeclarativeScriptData; class QDeclarativeInstruction; class QDeclarativeCompiledData; class QDeclarativeCompiledData; @@ -103,6 +105,8 @@ public: QObject *run(QDeclarativeContextData *, QDeclarativeCompiledData *, int start = -1, int count = -1, const QBitField & = QBitField()); + QScriptValue run(QDeclarativeContextData *, QDeclarativeScriptData *); + void runDeferred(QObject *); bool isError() const; diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp index ad1bf0dd3a..6eb74b3bad 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject.cpp +++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp @@ -647,6 +647,7 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) return -1; // We can't run the method QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine); + ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation. QScriptValue function = method(id); @@ -657,10 +658,19 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) args << ep->scriptValueFromVariant(*(QVariant *)a[ii + 1]); } } + QScriptValue rv = function.call(ep->objectClass->newQObject(object), args); + if (ep->scriptEngine.hasUncaughtException()) { + QDeclarativeError error; + QDeclarativeExpressionPrivate::exceptionToError(&ep->scriptEngine, error); + if (error.isValid()) { + ep->warning(error); + } + } if (a[0]) *reinterpret_cast(a[0]) = ep->scriptValueToVariant(rv); + ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete. return -1; } return -1; diff --git a/src/declarative/qml/qdeclarativexmlhttprequest.cpp b/src/declarative/qml/qdeclarativexmlhttprequest.cpp index aefc896f5b..930d345285 100644 --- a/src/declarative/qml/qdeclarativexmlhttprequest.cpp +++ b/src/declarative/qml/qdeclarativexmlhttprequest.cpp @@ -101,6 +101,8 @@ QT_BEGIN_NAMESPACE DEFINE_BOOL_CONFIG_OPTION(xhrDump, QML_XHR_DUMP); +namespace { + class DocumentImpl; class NodeImpl { @@ -323,6 +325,8 @@ public: static QScriptValue load(QScriptEngine *engine, const QByteArray &data); }; +} + QT_END_NAMESPACE Q_DECLARE_METATYPE(Node) @@ -1231,6 +1235,18 @@ void QDeclarativeXMLHttpRequest::downloadProgress(qint64 bytes) } } +static const char *errorToString(QNetworkReply::NetworkError error) +{ + int idx = QNetworkReply::staticMetaObject.indexOfEnumerator("NetworkError"); + if (idx == -1) return "EnumLookupFailed"; + + QMetaEnum e = QNetworkReply::staticMetaObject.enumerator(idx); + + const char *name = e.valueToKey(error); + if (!name) return "EnumLookupFailed"; + else return name; +} + void QDeclarativeXMLHttpRequest::error(QNetworkReply::NetworkError error) { Q_UNUSED(error) @@ -1245,6 +1261,11 @@ void QDeclarativeXMLHttpRequest::error(QNetworkReply::NetworkError error) m_data.clear(); destroyNetwork(); + if (xhrDump()) { + qWarning().nospace() << "XMLHttpRequest: ERROR " << qPrintable(m_url.toString()); + qWarning().nospace() << " " << error << " " << errorToString(error) << " " << m_statusText; + } + if (error == QNetworkReply::ContentAccessDenied || error == QNetworkReply::ContentOperationNotPermittedError || error == QNetworkReply::ContentNotFoundError || diff --git a/src/declarative/qml/qintrusivelist.cpp b/src/declarative/qml/qintrusivelist.cpp new file mode 100644 index 0000000000..6c27af0777 --- /dev/null +++ b/src/declarative/qml/qintrusivelist.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qintrusivelist_p.h" + +/*! +\class QIntrusiveList +\brief The QIntrusiveList class is a template class that provides a list of objects using static storage. +\internal + +QIntrusiveList creates a linked list of objects. Adding and removing objects from the +QIntrusiveList is a constant time operation and is very quick. The list performs no memory +allocations, but does require the objects being added to the list to contain a QIntrusiveListNode +instance for the list's use. Even so, for small lists QIntrusiveList uses less memory than Qt's +other list classes. + +As QIntrusiveList uses storage inside the objects in the list, each object can only be in one +list at a time. Objects are inserted by the insert() method. If the object is already +in a list (including the one it is being inserted into) it is first removed, and then inserted +at the head of the list. QIntrusiveList is a last-in-first-out list. That is, following an +insert() the inserted object becomes the list's first() object. + +\code +struct MyObject { + MyObject(int value) : value(value) {} + + int value; + QIntrusiveListNode node; +}; +typedef QIntrusiveList MyObjectList; + +void foo() { + MyObjectList list; + + MyObject m0(0); + MyObject m1(1); + MyObject m2(2); + + list.insert(&m0); + list.insert(&m1); + list.insert(&m2); + + // QIntrusiveList is LIFO, so will print: 2... 1... 0... + for (MyObjectList::iterator iter = list.begin(); iter != list.end(); ++iter) { + qWarning() << iter->value; + } +} +\endcode +*/ + + +/*! +\fn QIntrusiveList::QIntrusiveList(); + +Construct an empty list. +*/ + +/*! +\fn QIntrusiveList::~QIntrusiveList(); + +Destroy the list. All entries are removed. +*/ + +/*! +\fn void QIntrusiveList::insert(N *object); + +Insert \a object into the list. If \a object is a member of this, or another list, it will be +removed and inserted at the head of this list. +*/ + +/*! +\fn void QIntrusiveList::remove(N *object); + +Remove \a object from the list. \a object must not be null. +*/ + +/*! +\fn N *QIntrusiveList::first() const + +Returns the first entry in this list, or null if the list is empty. +*/ + +/*! +\fn N *QIntrusiveList::next(N *current) + +Returns the next object after \a current, or null if \a current is the last object. \a current cannot be null. +*/ + +/*! +\fn iterator QIntrusiveList::begin() + +Returns an STL-style interator pointing to the first item in the list. + +\sa end() +*/ + +/*! +\fn iterator QIntrusiveList::end() + +Returns an STL-style iterator pointing to the imaginary item after the last item in the list. + +\sa begin() +*/ + +/*! +iterator &QInplacelist::iterator::erase() + +Remove the current object from the list, and return an iterator to the next element. +*/ + + +/*! +\fn QIntrusiveListNode::QIntrusiveListNode() + +Create a QIntrusiveListNode. +*/ + +/*! +\fn QIntrusiveListNode::~QIntrusiveListNode() + +Destroy the QIntrusiveListNode. If the node is in a list, it is removed. +*/ + +/*! +\fn void QIntrusiveListNode::remove() + +If in a list, remove this node otherwise do nothing. +*/ + +/*! +\fn bool QIntrusiveListNode::isInList() const + +Returns true if this node is in a list, false otherwise. +*/ + diff --git a/src/declarative/qml/qintrusivelist_p.h b/src/declarative/qml/qintrusivelist_p.h new file mode 100644 index 0000000000..459d051d07 --- /dev/null +++ b/src/declarative/qml/qintrusivelist_p.h @@ -0,0 +1,254 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QINTRUSIVELIST_P_H +#define QINTRUSIVELIST_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 + +QT_BEGIN_NAMESPACE + +class QIntrusiveListNode; +template +class QIntrusiveList +{ +public: + inline QIntrusiveList(); + inline ~QIntrusiveList(); + + inline void insert(N *n); + inline void remove(N *n); + + class iterator { + public: + inline iterator(); + inline iterator(N *value); + + inline N *operator*() const; + inline N *operator->() const; + inline bool operator==(const iterator &other) const; + inline bool operator!=(const iterator &other) const; + inline iterator &operator++(); + + inline iterator &erase(); + + private: + N *_value; + }; + typedef iterator Iterator; + + inline N *first() const; + static inline N *next(N *current); + + inline iterator begin(); + inline iterator end(); + +private: + static inline N *nodeToN(QIntrusiveListNode *node); + + QIntrusiveListNode *__first; +}; + +class QIntrusiveListNode +{ +public: + inline QIntrusiveListNode(); + inline ~QIntrusiveListNode(); + + inline void remove(); + inline bool isInList() const; + + QIntrusiveListNode *_next; + QIntrusiveListNode**_prev; +}; + +template +QIntrusiveList::iterator::iterator() +: _value(0) +{ +} + +template +QIntrusiveList::iterator::iterator(N *value) +: _value(value) +{ +} + +template +N *QIntrusiveList::iterator::operator*() const +{ + return _value; +} + +template +N *QIntrusiveList::iterator::operator->() const +{ + return _value; +} + +template +bool QIntrusiveList::iterator::operator==(const iterator &other) const +{ + return other._value == _value; +} + +template +bool QIntrusiveList::iterator::operator!=(const iterator &other) const +{ + return other._value != _value; +} + +template +typename QIntrusiveList::iterator &QIntrusiveList::iterator::operator++() +{ + _value = QIntrusiveList::next(_value); + return *this; +} + +template +typename QIntrusiveList::iterator &QIntrusiveList::iterator::erase() +{ + N *old = _value; + _value = QIntrusiveList::next(_value); + (old->*member).remove(); + return *this; +} + +template +QIntrusiveList::QIntrusiveList() +: __first(0) +{ +} + +template +QIntrusiveList::~QIntrusiveList() +{ + while (__first) __first->remove(); +} + +template +void QIntrusiveList::insert(N *n) +{ + QIntrusiveListNode *nnode = &(n->*member); + nnode->remove(); + + nnode->_next = __first; + if (nnode->_next) nnode->_next->_prev = &nnode->_next; + __first = nnode; + nnode->_prev = &__first; +} + +template +void QIntrusiveList::remove(N *n) +{ + QIntrusiveListNode *nnode = &(n->*member); + nnode->remove(); +} + +template +N *QIntrusiveList::first() const +{ + return __first?nodeToN(__first):0; +} + +template +N *QIntrusiveList::next(N *current) +{ + QIntrusiveListNode *nextnode = (current->*member)._next; + N *nextstruct = nextnode?nodeToN(nextnode):0; + return nextstruct; +} + +template +typename QIntrusiveList::iterator QIntrusiveList::begin() +{ + return __first?iterator(nodeToN(__first)):iterator(); +} + +template +typename QIntrusiveList::iterator QIntrusiveList::end() +{ + return iterator(); +} + +template +N *QIntrusiveList::nodeToN(QIntrusiveListNode *node) +{ + return (N *)((char *)node - ((char *)&(((N *)0)->*member) - (char *)0)); +} + +QIntrusiveListNode::QIntrusiveListNode() +: _next(0), _prev(0) +{ +} + +QIntrusiveListNode::~QIntrusiveListNode() +{ + remove(); +} + +void QIntrusiveListNode::remove() +{ + if (_prev) *_prev = _next; + if (_next) _next->_prev = _prev; + _prev = 0; + _next = 0; +} + +bool QIntrusiveListNode::isInList() const +{ + return _prev != 0; +} + +QT_END_NAMESPACE + +#endif // QINTRUSIVELIST_P_H diff --git a/src/declarative/qml/qmetaobjectbuilder.cpp b/src/declarative/qml/qmetaobjectbuilder.cpp index dc941e2601..a63656bc28 100644 --- a/src/declarative/qml/qmetaobjectbuilder.cpp +++ b/src/declarative/qml/qmetaobjectbuilder.cpp @@ -101,7 +101,7 @@ bool isVariantType(const char* type) return qvariant_nameToType(type) != 0; } -// copied from qmetaobject.cpp +// copied from qmetaobject_p.h // do not touch without touching the moc as well enum PropertyFlags { Invalid = 0x00000000, @@ -111,6 +111,8 @@ enum PropertyFlags { EnumOrFlag = 0x00000008, StdCppSet = 0x00000100, // Override = 0x00000200, + Constant = 0x00000400, + Final = 0x00000800, Designable = 0x00001000, ResolveDesignable = 0x00002000, Scriptable = 0x00004000, @@ -618,6 +620,8 @@ QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty& protot property.setUser(prototype.isUser()); property.setStdCppSet(prototype.hasStdCppSet()); property.setEnumOrFlag(prototype.isEnumType()); + property.setConstant(prototype.isConstant()); + property.setFinal(prototype.isFinal()); if (prototype.hasNotifySignal()) { // Find an existing method for the notify signal, or add a new one. QMetaMethod method = prototype.notifySignal(); @@ -2277,6 +2281,32 @@ bool QMetaPropertyBuilder::isEnumOrFlag() const return false; } +/*! + Returns true if the property is constant; otherwise returns false. + The default value is false. +*/ +bool QMetaPropertyBuilder::isConstant() const +{ + QMetaPropertyBuilderPrivate *d = d_func(); + if (d) + return d->flag(Constant); + else + return false; +} + +/*! + Returns true if the property is final; otherwise returns false. + The default value is false. +*/ +bool QMetaPropertyBuilder::isFinal() const +{ + QMetaPropertyBuilderPrivate *d = d_func(); + if (d) + return d->flag(Final); + else + return false; +} + /*! Sets this property to readable if \a value is true. @@ -2400,6 +2430,31 @@ void QMetaPropertyBuilder::setEnumOrFlag(bool value) d->setFlag(EnumOrFlag, value); } +/*! + Sets the \c CONSTANT flag on this property to \a value. + + \sa isConstant() +*/ +void QMetaPropertyBuilder::setConstant(bool value) +{ + QMetaPropertyBuilderPrivate *d = d_func(); + if (d) + d->setFlag(Constant, value); +} + +/*! + Sets the \c FINAL flag on this property to \a value. + + \sa isFinal() +*/ +void QMetaPropertyBuilder::setFinal(bool value) +{ + QMetaPropertyBuilderPrivate *d = d_func(); + if (d) + d->setFlag(Final, value); +} + + /*! \class QMetaEnumBuilder \internal diff --git a/src/declarative/qml/qmetaobjectbuilder_p.h b/src/declarative/qml/qmetaobjectbuilder_p.h index d7085f8784..335a825be3 100644 --- a/src/declarative/qml/qmetaobjectbuilder_p.h +++ b/src/declarative/qml/qmetaobjectbuilder_p.h @@ -258,6 +258,8 @@ public: bool isUser() const; bool hasStdCppSet() const; bool isEnumOrFlag() const; + bool isConstant() const; + bool isFinal() const; void setReadable(bool value); void setWritable(bool value); @@ -269,6 +271,8 @@ public: void setUser(bool value); void setStdCppSet(bool value); void setEnumOrFlag(bool value); + void setConstant(bool value); + void setFinal(bool value); private: const QMetaObjectBuilder *_mobj; diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index bf9e54a986..62c1f97d60 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -18,7 +18,6 @@ SOURCES += \ $$PWD/qdeclarativecompiler.cpp \ $$PWD/qdeclarativecompileddata.cpp \ $$PWD/qdeclarativeboundsignal.cpp \ - $$PWD/qdeclarativedom.cpp \ $$PWD/qdeclarativerefcount.cpp \ $$PWD/qdeclarativemetatype.cpp \ $$PWD/qdeclarativestringconverters.cpp \ @@ -30,7 +29,6 @@ SOURCES += \ $$PWD/qdeclarativeenginedebug.cpp \ $$PWD/qdeclarativerewrite.cpp \ $$PWD/qdeclarativevaluetype.cpp \ - $$PWD/qdeclarativecompiledbindings.cpp \ $$PWD/qdeclarativefastproperties.cpp \ $$PWD/qdeclarativexmlhttprequest.cpp \ $$PWD/qdeclarativesqldatabase.cpp \ @@ -44,6 +42,7 @@ SOURCES += \ $$PWD/qdeclarativetypenamecache.cpp \ $$PWD/qdeclarativescriptstring.cpp \ $$PWD/qdeclarativeobjectscriptclass.cpp \ + $$PWD/qdeclarativescarceresourcescriptclass.cpp \ $$PWD/qdeclarativecontextscriptclass.cpp \ $$PWD/qdeclarativeglobalscriptclass.cpp \ $$PWD/qdeclarativevaluetypescriptclass.cpp \ @@ -56,7 +55,8 @@ SOURCES += \ $$PWD/qdeclarativeextensionplugin.cpp \ $$PWD/qdeclarativeimport.cpp \ $$PWD/qdeclarativelist.cpp \ - $$PWD/qperformancetimer.cpp + $$PWD/qperformancetimer.cpp \ + $$PWD/qintrusivelist.cpp \ HEADERS += \ $$PWD/qdeclarativeparser_p.h \ @@ -81,8 +81,6 @@ HEADERS += \ $$PWD/qdeclarativeengine_p.h \ $$PWD/qdeclarativeexpression_p.h \ $$PWD/qdeclarativeprivate.h \ - $$PWD/qdeclarativedom_p.h \ - $$PWD/qdeclarativedom_p_p.h \ $$PWD/qdeclarativerefcount_p.h \ $$PWD/qdeclarativemetatype_p.h \ $$PWD/qdeclarativeengine.h \ @@ -104,7 +102,6 @@ HEADERS += \ $$PWD/qpodvector_p.h \ $$PWD/qbitfield_p.h \ $$PWD/qdeclarativevaluetype_p.h \ - $$PWD/qdeclarativecompiledbindings_p.h \ $$PWD/qdeclarativefastproperties_p.h \ $$PWD/qdeclarativexmlhttprequest_p.h \ $$PWD/qdeclarativesqldatabase_p.h \ @@ -118,6 +115,7 @@ HEADERS += \ $$PWD/qdeclarativetypenamecache_p.h \ $$PWD/qdeclarativescriptstring.h \ $$PWD/qdeclarativeobjectscriptclass_p.h \ + $$PWD/qdeclarativescarceresourcescriptclass_p.h \ $$PWD/qdeclarativecontextscriptclass_p.h \ $$PWD/qdeclarativeglobalscriptclass_p.h \ $$PWD/qdeclarativevaluetypescriptclass_p.h \ @@ -131,11 +129,13 @@ HEADERS += \ $$PWD/qdeclarativeextensioninterface.h \ $$PWD/qdeclarativeimport_p.h \ $$PWD/qdeclarativeextensionplugin.h \ - $$PWD/qperformancetimer_p.h + $$PWD/qperformancetimer_p.h \ + $$PWD/qintrusivelist_p.h \ QT += sql include(parser/parser.pri) include(rewriter/rewriter.pri) +include(v4/v4.pri) # mirrors logic in corelib/kernel/kernel.pri unix:!symbian: contains(QT_CONFIG, clock-gettime):include($$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri) diff --git a/src/declarative/qml/v4/qdeclarativev4bindings.cpp b/src/declarative/qml/v4/qdeclarativev4bindings.cpp new file mode 100644 index 0000000000..80c7a68697 --- /dev/null +++ b/src/declarative/qml/v4/qdeclarativev4bindings.cpp @@ -0,0 +1,1530 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// #define REGISTER_CLEANUP_DEBUG + +#include "private/qdeclarativev4bindings_p.h" +#include "private/qdeclarativev4program_p.h" +#include "private/qdeclarativev4compiler_p.h" + +#include +#include +#include // For AnchorLine +#include // For AnchorLine + +#include +#include +#include +#include // ::fmod + +QT_BEGIN_NAMESPACE + +using namespace QDeclarativeJS; + +namespace { +struct Register { + typedef QDeclarativeRegisterType Type; + + void setUndefined() { dataType = UndefinedType; } + void setNaN() { setqreal(qSNaN()); } + bool isUndefined() const { return dataType == UndefinedType; } + + void setQObject(QObject *o) { *((QObject **)data) = o; dataType = QObjectStarType; } + QObject *getQObject() const { return *((QObject **)data); } + + void setqreal(qreal v) { *((qreal *)data) = v; dataType = QRealType; } + qreal getqreal() const { return *((qreal *)data); } + qreal &getqrealref() const { return *((qreal *)data); } + + void setint(int v) { *((int *)data) = v; dataType = IntType; } + int getint() const { return *((int *)data); } + int &getintref() const { return *((int *)data); } + + void setbool(bool v) { *((bool *)data) = v; dataType = BoolType; } + bool getbool() const { return *((bool *)data); } + bool &getboolref() const { return *((bool *)data); } + + QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); } + QString *getstringptr() { return (QString *)typeDataPtr(); } + QUrl *geturlptr() { return (QUrl *)typeDataPtr(); } + const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); } + const QString *getstringptr() const { return (QString *)typeDataPtr(); } + const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); } + + void *typeDataPtr() { return (void *)&data; } + void *typeMemory() { return (void *)data; } + const void *typeDataPtr() const { return (void *)&data; } + const void *typeMemory() const { return (void *)data; } + + Type gettype() const { return dataType; } + void settype(Type t) { dataType = t; } + + // int type; // Optional type + + Type dataType; // Type of data + void *data[2]; // Object stored here + + inline void cleanup(); + inline void cleanupString(); + inline void cleanupUrl(); + inline void cleanupVariant(); + + inline void copy(const Register &other); + inline void init(Type type); +#ifdef REGISTER_CLEANUP_DEBUG + Register() { + type = 0; + } + + ~Register() { + if (dataType >= FirstCleanupType) + qWarning("Register leaked of type %d", dataType); + } +#endif +}; + +void Register::cleanup() +{ + if (dataType >= FirstCleanupType) { + if (dataType == QStringType) { + getstringptr()->~QString(); + } else if (dataType == QUrlType) { + geturlptr()->~QUrl(); + } else if (dataType == QVariantType) { + getvariantptr()->~QVariant(); + } + } + setUndefined(); +} + +void Register::cleanupString() +{ + getstringptr()->~QString(); + setUndefined(); +} + +void Register::cleanupUrl() +{ + geturlptr()->~QUrl(); + setUndefined(); +} + +void Register::cleanupVariant() +{ + getvariantptr()->~QVariant(); + setUndefined(); +} + +void Register::copy(const Register &other) +{ + *this = other; + if (other.dataType >= FirstCleanupType) { + if (other.dataType == QStringType) + new (getstringptr()) QString(*other.getstringptr()); + else if (other.dataType == QUrlType) + new (geturlptr()) QUrl(*other.geturlptr()); + else if (other.dataType == QVariantType) + new (getvariantptr()) QVariant(*other.getvariantptr()); + } +} + +void Register::init(Type type) +{ + dataType = type; + if (dataType >= FirstCleanupType) { + if (dataType == QStringType) + new (getstringptr()) QString(); + else if (dataType == QUrlType) + new (geturlptr()) QUrl(); + else if (dataType == QVariantType) + new (getvariantptr()) QVariant(); + } +} + +} // end of anonymous namespace + +class QDeclarativeV4BindingsPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeV4Bindings) + +public: + QDeclarativeV4BindingsPrivate(); + virtual ~QDeclarativeV4BindingsPrivate(); + + struct Binding : public QDeclarativeAbstractBinding, public QDeclarativeDelayedError { + Binding() : enabled(false), updating(0), property(0), + scope(0), target(0), executedBlocks(0), parent(0) {} + + // Inherited from QDeclarativeAbstractBinding + virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags flags); + virtual void update(QDeclarativePropertyPrivate::WriteFlags flags); + virtual void destroy(); + + int index:30; + bool enabled:1; + bool updating:1; + int property; + QObject *scope; + QObject *target; + quint32 executedBlocks; + + QDeclarativeV4BindingsPrivate *parent; + }; + + typedef QDeclarativeNotifierEndpoint Subscription; + Subscription *subscriptions; + QScriptDeclarativeClass::PersistentIdentifier *identifiers; + + void run(Binding *, QDeclarativePropertyPrivate::WriteFlags flags); + + QDeclarativeV4Program *program; + Binding *bindings; + + static int methodCount; + + void init(); + void run(int instr, quint32 &executedBlocks, QDeclarativeContextData *context, + QDeclarativeDelayedError *error, QObject *scope, QObject *output, + QDeclarativePropertyPrivate::WriteFlags storeFlags +#ifdef QML_THREADED_INTERPRETER + , void ***decode_instr = 0 +#endif + ); + + + inline void unsubscribe(int subIndex); + inline void subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex); + inline void subscribe(QObject *o, int notifyIndex, int subIndex); + + inline static qint32 toInt32(qsreal n); + static const qsreal D32; + static quint32 toUint32(qsreal n); +}; + +QDeclarativeV4BindingsPrivate::QDeclarativeV4BindingsPrivate() +: subscriptions(0), identifiers(0), program(0), bindings(0) +{ +} + +QDeclarativeV4BindingsPrivate::~QDeclarativeV4BindingsPrivate() +{ + delete [] subscriptions; subscriptions = 0; + delete [] identifiers; identifiers = 0; +} + +int QDeclarativeV4BindingsPrivate::methodCount = -1; + +QDeclarativeV4Bindings::QDeclarativeV4Bindings(const char *program, QDeclarativeContextData *context) +: QObject(*(new QDeclarativeV4BindingsPrivate)) +{ + Q_D(QDeclarativeV4Bindings); + + if (d->methodCount == -1) + d->methodCount = QDeclarativeV4Bindings::staticMetaObject.methodCount(); + + d->program = (QDeclarativeV4Program *)program; + + if (program) { + d->init(); + + QDeclarativeAbstractExpression::setContext(context); + } +} + +QDeclarativeV4Bindings::~QDeclarativeV4Bindings() +{ + Q_D(QDeclarativeV4Bindings); + + delete [] d->bindings; +} + +QDeclarativeAbstractBinding *QDeclarativeV4Bindings::configBinding(int index, QObject *target, + QObject *scope, int property) +{ + Q_D(QDeclarativeV4Bindings); + + QDeclarativeV4BindingsPrivate::Binding *rv = d->bindings + index; + + rv->index = index; + rv->property = property; + rv->target = target; + rv->scope = scope; + rv->parent = d; + + addref(); // This is decremented in Binding::destroy() + + return rv; +} + +void QDeclarativeV4BindingsPrivate::Binding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags) +{ + if (enabled != e) { + enabled = e; + + if (e) update(flags); + } +} + +void QDeclarativeV4BindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags) +{ + QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Binding); + parent->run(this, flags); + QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Binding); +} + +void QDeclarativeV4BindingsPrivate::Binding::destroy() +{ + enabled = false; + removeFromObject(); + clear(); + parent->q_func()->release(); +} + +int QDeclarativeV4Bindings::qt_metacall(QMetaObject::Call c, int id, void **) +{ + Q_D(QDeclarativeV4Bindings); + + if (c == QMetaObject::InvokeMetaMethod && id >= d->methodCount) { + id -= d->methodCount; + + QDeclarativeV4Program::BindingReferenceList *list = d->program->signalTable(id); + + for (quint32 ii = 0; ii < list->count; ++ii) { + QDeclarativeV4Program::BindingReference *bindingRef = list->bindings + ii; + + QDeclarativeV4BindingsPrivate::Binding *binding = d->bindings + bindingRef->binding; + if (binding->executedBlocks & bindingRef->blockMask) + d->run(binding, QDeclarativePropertyPrivate::DontRemoveBinding); + } + } + return -1; +} + +void QDeclarativeV4BindingsPrivate::run(Binding *binding, QDeclarativePropertyPrivate::WriteFlags flags) +{ + Q_Q(QDeclarativeV4Bindings); + + if (!binding->enabled) + return; + + QDeclarativeContextData *context = q->QDeclarativeAbstractExpression::context(); + if (!context || !context->isValid()) + return; + + if (binding->updating) { + QString name; + if (binding->property & 0xFFFF0000) { + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine); + + QDeclarativeValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF]; + Q_ASSERT(vt); + + name = QLatin1String(binding->target->metaObject()->property(binding->property & 0xFFFF).name()); + name.append(QLatin1String(".")); + name.append(QLatin1String(vt->metaObject()->property(binding->property >> 24).name())); + } else { + name = QLatin1String(binding->target->metaObject()->property(binding->property).name()); + } + qmlInfo(binding->target) << QCoreApplication::translate("QDeclarativeV4Bindings", "Binding loop detected for property \"%1\"").arg(name); + return; + } + + binding->updating = true; + if (binding->property & 0xFFFF0000) { + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine); + + QDeclarativeValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF]; + Q_ASSERT(vt); + vt->read(binding->target, binding->property & 0xFFFF); + + QObject *target = vt; + run(binding->index, binding->executedBlocks, context, binding, binding->scope, target, flags); + + vt->write(binding->target, binding->property & 0xFFFF, flags); + } else { + run(binding->index, binding->executedBlocks, context, binding, binding->scope, binding->target, flags); + } + binding->updating = false; +} + + +void QDeclarativeV4BindingsPrivate::unsubscribe(int subIndex) +{ + QDeclarativeV4BindingsPrivate::Subscription *sub = (subscriptions + subIndex); + sub->disconnect(); +} + +void QDeclarativeV4BindingsPrivate::subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex) +{ + Q_Q(QDeclarativeV4Bindings); + + unsubscribe(subIndex); + + if (p->idValues[idIndex]) { + QDeclarativeV4BindingsPrivate::Subscription *sub = (subscriptions + subIndex); + sub->target = q; + sub->targetMethod = methodCount + subIndex; + sub->connect(&p->idValues[idIndex].bindings); + } +} + +void QDeclarativeV4BindingsPrivate::subscribe(QObject *o, int notifyIndex, int subIndex) +{ + Q_Q(QDeclarativeV4Bindings); + + QDeclarativeV4BindingsPrivate::Subscription *sub = (subscriptions + subIndex); + sub->target = q; + sub->targetMethod = methodCount + subIndex; + if (o) + sub->connect(o, notifyIndex); + else + sub->disconnect(); +} + +// Conversion functions - these MUST match the QtScript expression path +inline static qreal toReal(Register *reg, int type, bool *ok = 0) +{ + if (ok) *ok = true; + + if (type == QMetaType::QReal) { + return reg->getqreal(); + } else if (type == qMetaTypeId()) { + return reg->getvariantptr()->toReal(); + } else { + if (ok) *ok = false; + return 0; + } +} + +inline static QString toString(Register *reg, int type, bool *ok = 0) +{ + if (ok) *ok = true; + + if (type == QMetaType::QReal) { + return QString::number(reg->getqreal()); + } else if (type == QMetaType::Int) { + return QString::number(reg->getint()); + } else if (type == qMetaTypeId()) { + return reg->getvariantptr()->toString(); + } else if (type == QMetaType::QString) { + return *reg->getstringptr(); + } else { + if (ok) *ok = false; + return QString(); + } +} + +inline static bool toBool(Register *reg, int type, bool *ok = 0) +{ + if (ok) *ok = true; + + if (type == QMetaType::Bool) { + return reg->getbool(); + } else if (type == qMetaTypeId()) { + return reg->getvariantptr()->toBool(); + } else { + if (ok) *ok = false; + return false; + } +} + +inline static QUrl toUrl(Register *reg, int type, QDeclarativeContextData *context, bool *ok = 0) +{ + if (ok) *ok = true; + + QUrl base; + if (type == qMetaTypeId()) { + QVariant *var = reg->getvariantptr(); + int vt = var->type(); + if (vt == QVariant::Url) { + base = var->toUrl(); + } else if (vt == QVariant::ByteArray) { + base = QUrl(QString::fromUtf8(var->toByteArray())); + } else if (vt == QVariant::String) { + base = QUrl(var->toString()); + } else { + if (ok) *ok = false; + return QUrl(); + } + } else if (type == QMetaType::QString) { + base = QUrl(*reg->getstringptr()); + } else { + if (ok) *ok = false; + return QUrl(); + } + + if (!base.isEmpty() && base.isRelative()) + return context->url.resolved(base); + else + return base; +} + +static QObject *variantToQObject(const QVariant &value, bool *ok) +{ + if (ok) *ok = true; + + if (value.userType() == QMetaType::QObjectStar) { + return qvariant_cast(value); + } else { + if (ok) *ok = false; + return 0; + } +} + +void QDeclarativeV4BindingsPrivate::init() +{ + if (program->subscriptions) + subscriptions = new QDeclarativeV4BindingsPrivate::Subscription[program->subscriptions]; + if (program->identifiers) + identifiers = new QScriptDeclarativeClass::PersistentIdentifier[program->identifiers]; + + bindings = new QDeclarativeV4BindingsPrivate::Binding[program->bindings]; +} + +static bool testCompareVariants(const QVariant &qtscriptRaw, const QVariant &v4) +{ + QVariant qtscript = qtscriptRaw; + + if (qtscript.userType() == v4.userType()) { + } else if (qtscript.canConvert((QVariant::Type)v4.userType())) { + qtscript.convert((QVariant::Type)v4.userType()); + } else if (qtscript.userType() == QVariant::Invalid && v4.userType() == QMetaType::QObjectStar) { + qtscript = qVariantFromValue(0); + } else { + return false; + } + + int type = qtscript.userType(); + + if (type == qMetaTypeId()) { + QDeclarativeAnchorLine la = qvariant_cast(qtscript); + QDeclarativeAnchorLine ra = qvariant_cast(v4); + + return la == ra; + } else if (type == qMetaTypeId()) { + QSGAnchorLine la = qvariant_cast(qtscript); + QSGAnchorLine ra = qvariant_cast(v4); + + return la == ra; + } else if (type == QMetaType::Double) { + + double la = qvariant_cast(qtscript); + double lr = qvariant_cast(v4); + + return la == lr || (qIsNaN(la) && qIsNaN(lr)); + + } else if (type == QMetaType::Float) { + + float la = qvariant_cast(qtscript); + float lr = qvariant_cast(v4); + + return la == lr || (qIsNaN(la) && qIsNaN(lr)); + + } else { + return qtscript == v4; + } +} + +QByteArray testResultToString(const QVariant &result, bool undefined) +{ + if (undefined) { + return "undefined"; + } else { + QString rv; + QDebug d(&rv); + d << result; + return rv.toUtf8(); + } +} + +static void testBindingResult(const QString &binding, int line, int column, + QDeclarativeContextData *context, QObject *scope, + const Register &result, int resultType) +{ + QDeclarativeExpression expression(context->asQDeclarativeContext(), scope, binding); + bool isUndefined = false; + QVariant value = expression.evaluate(&isUndefined); + + bool iserror = false; + QByteArray qtscriptResult; + QByteArray v4Result; + + if (expression.hasError()) { + iserror = true; + qtscriptResult = "exception"; + } else { + qtscriptResult = testResultToString(value, isUndefined); + } + + if (isUndefined && result.isUndefined()) { + return; + } else if(isUndefined != result.isUndefined()) { + iserror = true; + } + + QVariant v4value; + if (!result.isUndefined()) { + switch (resultType) { + case QMetaType::QString: + v4value = *result.getstringptr(); + break; + case QMetaType::QUrl: + v4value = *result.geturlptr(); + break; + case QMetaType::QObjectStar: + v4value = qVariantFromValue(result.getQObject()); + break; + case QMetaType::Bool: + v4value = result.getbool(); + break; + case QMetaType::Int: + v4value = result.getint(); + break; + case QMetaType::QReal: + v4value = result.getqreal(); + break; + default: + if (resultType == qMetaTypeId()) { + v4value = qVariantFromValue(*(QDeclarativeAnchorLine *)result.typeDataPtr()); + } else if (resultType == qMetaTypeId()) { + v4value = qVariantFromValue(*(QSGAnchorLine *)result.typeDataPtr()); + } else { + iserror = true; + v4Result = "Unknown V4 type"; + } + } + } + if (v4Result.isEmpty()) + v4Result = testResultToString(v4value, result.isUndefined()); + + if (!testCompareVariants(value, v4value)) + iserror = true; + + if (iserror) { + qWarning().nospace() << "QDeclarativeV4: Optimization error @" << context->url.toString().toUtf8().constData() << ":" << line << ":" << column; + + qWarning().nospace() << " Binding: " << binding; + qWarning().nospace() << " QtScript: " << qtscriptResult.constData(); + qWarning().nospace() << " V4: " << v4Result.constData(); + } +} + +static void testBindingException(const QString &binding, int line, int column, + QDeclarativeContextData *context, QObject *scope) +{ + QDeclarativeExpression expression(context->asQDeclarativeContext(), scope, binding); + bool isUndefined = false; + QVariant value = expression.evaluate(&isUndefined); + + if (!expression.hasError()) { + QByteArray qtscriptResult = testResultToString(value, isUndefined); + qWarning().nospace() << "QDeclarativeV4: Optimization error @" << context->url.toString().toUtf8().constData() << ":" << line << ":" << column; + qWarning().nospace() << " Binding: " << binding; + qWarning().nospace() << " QtScript: " << qtscriptResult.constData(); + qWarning().nospace() << " V4: exception"; + } +} + +static void throwException(int id, QDeclarativeDelayedError *error, + QDeclarativeV4Program *program, QDeclarativeContextData *context, + const QString &description = QString()) +{ + error->error.setUrl(context->url); + if (description.isEmpty()) + error->error.setDescription(QLatin1String("TypeError: Result of expression is not an object")); + else + error->error.setDescription(description); + if (id != 0xFF) { + quint64 e = *((quint64 *)(program->data() + program->exceptionDataOffset) + id); + error->error.setLine((e >> 32) & 0xFFFFFFFF); + error->error.setColumn(e & 0xFFFFFFFF); + } else { + error->error.setLine(-1); + error->error.setColumn(-1); + } + if (!context->engine || !error->addError(QDeclarativeEnginePrivate::get(context->engine))) + QDeclarativeEnginePrivate::warning(context->engine, error->error); +} + +const qsreal QDeclarativeV4BindingsPrivate::D32 = 4294967296.0; + +qint32 QDeclarativeV4BindingsPrivate::toInt32(qsreal n) +{ + if (qIsNaN(n) || qIsInf(n) || (n == 0)) + return 0; + + double sign = (n < 0) ? -1.0 : 1.0; + qsreal abs_n = fabs(n); + + n = ::fmod(sign * ::floor(abs_n), D32); + const double D31 = D32 / 2.0; + + if (sign == -1 && n < -D31) + n += D32; + + else if (sign != -1 && n >= D31) + n -= D32; + + return qint32 (n); +} + +inline quint32 QDeclarativeV4BindingsPrivate::toUint32(qsreal n) +{ + if (qIsNaN(n) || qIsInf(n) || (n == 0)) + return 0; + + double sign = (n < 0) ? -1.0 : 1.0; + qsreal abs_n = fabs(n); + + n = ::fmod(sign * ::floor(abs_n), D32); + + if (n < 0) + n += D32; + + return quint32 (n); +} + +#define THROW_EXCEPTION_STR(id, str) { \ + if (testBinding) testBindingException(*testBindingSource, bindingLine, bindingColumn, context, scope); \ + throwException((id), error, program, context, (str)); \ + goto exceptionExit; \ +} + +#define THROW_EXCEPTION(id) THROW_EXCEPTION_STR(id, QString()) + +#define MARK_REGISTER(reg) cleanupRegisterMask |= (1 << (reg)) +#define MARK_CLEAN_REGISTER(reg) cleanupRegisterMask &= ~(1 << (reg)) + +#define STRING_REGISTER(reg) { \ + registers[(reg)].settype(QStringType); \ + MARK_REGISTER(reg); \ +} + +#define URL_REGISTER(reg) { \ + registers[(reg)].settype(QUrlType); \ + MARK_REGISTER(reg); \ +} + +#define VARIANT_REGISTER(reg) { \ + registers[(reg)].settype(QVariantType); \ + MARK_REGISTER(reg); \ +} + +#ifdef QML_THREADED_INTERPRETER +void **QDeclarativeV4Bindings::getDecodeInstrTable() +{ + static void **decode_instr; + if (!decode_instr) { + QDeclarativeV4Bindings dummy(0, 0); + quint32 executedBlocks = 0; + dummy.d_func()->run(0, executedBlocks, 0, 0, 0, 0, QDeclarativePropertyPrivate::BypassInterceptor, &decode_instr); + } + return decode_instr; +} +#endif + +void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, + QDeclarativeContextData *context, QDeclarativeDelayedError *error, + QObject *scope, QObject *output, QDeclarativePropertyPrivate::WriteFlags storeFlags +#ifdef QML_THREADED_INTERPRETER + ,void ***table +#endif + ) +{ + Q_Q(QDeclarativeV4Bindings); + +#ifdef QML_THREADED_INTERPRETER + if (table) { + static void *decode_instr[] = { + FOR_EACH_QML_INSTR(QML_INSTR_ADDR) + }; + + *table = decode_instr; + return; + } +#endif + + + error->removeError(); + + Register registers[32]; + quint32 cleanupRegisterMask = 0; + + executedBlocks = 0; + + QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(context->engine); + const char *code = program->instructions(); + code += instrIndex * QML_INSTR_SIZE(Jump, jump); + const Instr *instr = (const Instr *) code; + + const char *data = program->data(); + + QString *testBindingSource = 0; + bool testBinding = false; + int bindingLine = 0; + int bindingColumn = 0; + +#ifdef QML_THREADED_INTERPRETER + goto *instr->common.code; +#else + for (;;) { + switch (instr->common.type) { +#endif + + QML_BEGIN_INSTR(Noop, common) + QML_END_INSTR(Noop, common) + + QML_BEGIN_INSTR(BindingId, id) + bindingLine = instr->id.line; + bindingColumn = instr->id.column; + QML_END_INSTR(BindingId, id) + + QML_BEGIN_INSTR(SubscribeId, subscribeop) + subscribeId(context, instr->subscribeop.index, instr->subscribeop.offset); + QML_END_INSTR(SubscribeId, subscribeop) + + QML_BEGIN_INSTR(Subscribe, subscribeop) + { + QObject *o = 0; + const Register &object = registers[instr->subscribeop.reg]; + if (!object.isUndefined()) o = object.getQObject(); + subscribe(o, instr->subscribeop.index, instr->subscribeop.offset); + } + QML_END_INSTR(Subscribe, subscribeop) + + QML_BEGIN_INSTR(FetchAndSubscribe, fetchAndSubscribe) + { + Register ® = registers[instr->fetchAndSubscribe.reg]; + + if (reg.isUndefined()) + THROW_EXCEPTION(instr->fetchAndSubscribe.exceptionId); + + QObject *object = reg.getQObject(); + if (!object) { + reg.setUndefined(); + } else { + int subIdx = instr->fetchAndSubscribe.subscription; + QDeclarativeV4BindingsPrivate::Subscription *sub = 0; + if (subIdx != -1) { + sub = (subscriptions + subIdx); + sub->target = q; + sub->targetMethod = methodCount + subIdx; + } + reg.init((Register::Type)instr->fetchAndSubscribe.valueType); + if (instr->fetchAndSubscribe.valueType >= FirstCleanupType) + MARK_REGISTER(instr->fetchAndSubscribe.reg); + QDeclarativeV4Compiler::fastPropertyAccessor()->accessor(instr->fetchAndSubscribe.function)(object, reg.typeDataPtr(), sub); + } + } + QML_END_INSTR(FetchAndSubscribe, fetchAndSubscribe) + + QML_BEGIN_INSTR(LoadId, load) + registers[instr->load.reg].setQObject(context->idValues[instr->load.index].data()); + QML_END_INSTR(LoadId, load) + + QML_BEGIN_INSTR(LoadScope, load) + registers[instr->load.reg].setQObject(scope); + QML_END_INSTR(LoadScope, load) + + QML_BEGIN_INSTR(LoadRoot, load) + registers[instr->load.reg].setQObject(context->contextObject); + QML_END_INSTR(LoadRoot, load) + + QML_BEGIN_INSTR(LoadAttached, attached) + { + const Register &input = registers[instr->attached.reg]; + Register &output = registers[instr->attached.output]; + if (input.isUndefined()) + THROW_EXCEPTION(instr->attached.exceptionId); + + QObject *object = registers[instr->attached.reg].getQObject(); + if (!object) { + output.setUndefined(); + } else { + QObject *attached = qmlAttachedPropertiesObjectById(instr->attached.id, input.getQObject(), true); + Q_ASSERT(attached); + output.setQObject(attached); + } + } + QML_END_INSTR(LoadAttached, attached) + + QML_BEGIN_INSTR(UnaryNot, unaryop) + { + registers[instr->unaryop.output].setbool(!registers[instr->unaryop.src].getbool()); + } + QML_END_INSTR(UnaryNot, unaryop) + + QML_BEGIN_INSTR(UnaryMinusReal, unaryop) + { + registers[instr->unaryop.output].setqreal(-registers[instr->unaryop.src].getqreal()); + } + QML_END_INSTR(UnaryMinusReal, unaryop) + + QML_BEGIN_INSTR(UnaryMinusInt, unaryop) + { + registers[instr->unaryop.output].setint(-registers[instr->unaryop.src].getint()); + } + QML_END_INSTR(UnaryMinusInt, unaryop) + + QML_BEGIN_INSTR(UnaryPlusReal, unaryop) + { + registers[instr->unaryop.output].setqreal(+registers[instr->unaryop.src].getqreal()); + } + QML_END_INSTR(UnaryPlusReal, unaryop) + + QML_BEGIN_INSTR(UnaryPlusInt, unaryop) + { + registers[instr->unaryop.output].setint(+registers[instr->unaryop.src].getint()); + } + QML_END_INSTR(UnaryPlusInt, unaryop) + + QML_BEGIN_INSTR(ConvertBoolToInt, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setint(src.getbool()); + } + QML_END_INSTR(ConvertBoolToInt, unaryop) + + QML_BEGIN_INSTR(ConvertBoolToReal, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setqreal(src.getbool()); + } + QML_END_INSTR(ConvertBoolToReal, unaryop) + + QML_BEGIN_INSTR(ConvertBoolToString, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) { + output.setUndefined(); + } else { + new (output.getstringptr()) QString(QLatin1String(src.getbool() ? "true" : "false")); + STRING_REGISTER(instr->unaryop.output); + } + } + QML_END_INSTR(ConvertBoolToString, unaryop) + + QML_BEGIN_INSTR(ConvertIntToBool, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setbool(src.getint()); + } + QML_END_INSTR(ConvertIntToBool, unaryop) + + QML_BEGIN_INSTR(ConvertIntToReal, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setqreal(qreal(src.getint())); + } + QML_END_INSTR(ConvertIntToReal, unaryop) + + QML_BEGIN_INSTR(ConvertIntToString, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) { + output.setUndefined(); + } else { + new (output.getstringptr()) QString(QString::number(src.getint())); + STRING_REGISTER(instr->unaryop.output); + } + } + QML_END_INSTR(ConvertIntToString, unaryop) + + QML_BEGIN_INSTR(ConvertRealToBool, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setbool(src.getqreal() != 0); + } + QML_END_INSTR(ConvertRealToBool, unaryop) + + QML_BEGIN_INSTR(ConvertRealToInt, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setint(toInt32(src.getqreal())); + } + QML_END_INSTR(ConvertRealToInt, unaryop) + + QML_BEGIN_INSTR(ConvertRealToString, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + // ### NaN + if (src.isUndefined()) { + output.setUndefined(); + } else { + new (output.getstringptr()) QString(QString::number(src.getqreal())); + STRING_REGISTER(instr->unaryop.output); + } + } + QML_END_INSTR(ConvertRealToString, unaryop) + + QML_BEGIN_INSTR(ConvertStringToBool, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + // ### NaN + if (src.isUndefined()) { + output.setUndefined(); + } else { + // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine. + // Ideally we should just call the methods in the QScript namespace directly. + QScriptValue tmp(*src.getstringptr()); + if (instr->unaryop.src == instr->unaryop.output) { + output.cleanupString(); + MARK_CLEAN_REGISTER(instr->unaryop.output); + } + output.setbool(tmp.toBool()); + } + } + QML_END_INSTR(ConvertStringToBool, unaryop) + + QML_BEGIN_INSTR(ConvertStringToInt, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + // ### NaN + if (src.isUndefined()) { + output.setUndefined(); + } else { + // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine. + // Ideally we should just call the methods in the QScript namespace directly. + QScriptValue tmp(*src.getstringptr()); + if (instr->unaryop.src == instr->unaryop.output) { + output.cleanupString(); + MARK_CLEAN_REGISTER(instr->unaryop.output); + } + output.setint(tmp.toInt32()); + } + } + QML_END_INSTR(ConvertStringToInt, unaryop) + + QML_BEGIN_INSTR(ConvertStringToReal, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + // ### NaN + if (src.isUndefined()) { + output.setUndefined(); + } else { + // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine. + // Ideally we should just call the methods in the QScript namespace directly. + QScriptValue tmp(*src.getstringptr()); + if (instr->unaryop.src == instr->unaryop.output) { + output.cleanupString(); + MARK_CLEAN_REGISTER(instr->unaryop.output); + } + output.setqreal(tmp.toNumber()); + } + } + QML_END_INSTR(ConvertStringToReal, unaryop) + + QML_BEGIN_INSTR(MathSinReal, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setqreal(qSin(src.getqreal())); + } + QML_END_INSTR(MathSinReal, unaryop) + + QML_BEGIN_INSTR(MathCosReal, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setqreal(qCos(src.getqreal())); + } + QML_END_INSTR(MathCosReal, unaryop) + + QML_BEGIN_INSTR(MathRoundReal, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setint(qRound(src.getqreal())); + } + QML_END_INSTR(MathRoundReal, unaryop) + + QML_BEGIN_INSTR(MathFloorReal, unaryop) + { + const Register &src = registers[instr->unaryop.src]; + Register &output = registers[instr->unaryop.output]; + if (src.isUndefined()) output.setUndefined(); + else output.setint(qFloor(src.getqreal())); + } + QML_END_INSTR(MathFloorReal, unaryop) + + QML_BEGIN_INSTR(MathPIReal, unaryop) + { + static const qsreal qmlPI = 2.0 * qAsin(1.0); + Register &output = registers[instr->unaryop.output]; + output.setqreal(qmlPI); + } + QML_END_INSTR(MathPIReal, unaryop) + + QML_BEGIN_INSTR(Real, real_value) + registers[instr->real_value.reg].setqreal(instr->real_value.value); + QML_END_INSTR(Real, real_value) + + QML_BEGIN_INSTR(Int, int_value) + registers[instr->int_value.reg].setint(instr->int_value.value); + QML_END_INSTR(Int, int_value) + + QML_BEGIN_INSTR(Bool, bool_value) + registers[instr->bool_value.reg].setbool(instr->bool_value.value); + QML_END_INSTR(Bool, bool_value) + + QML_BEGIN_INSTR(String, string_value) + { + Register &output = registers[instr->string_value.reg]; + QChar *string = (QChar *)(data + instr->string_value.offset); + new (output.getstringptr()) QString(string, instr->string_value.length); + STRING_REGISTER(instr->string_value.reg); + } + QML_END_INSTR(String, string_value) + + QML_BEGIN_INSTR(EnableV4Test, string_value) + { + testBindingSource = new QString((QChar *)(data + instr->string_value.offset), instr->string_value.length); + testBinding = true; + } + QML_END_INSTR(String, string_value) + + QML_BEGIN_INSTR(BitAndInt, binaryop) + { + registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() & + registers[instr->binaryop.right].getint()); + } + QML_END_INSTR(BitAndInt, binaryop) + + QML_BEGIN_INSTR(BitOrInt, binaryop) + { + registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() | + registers[instr->binaryop.right].getint()); + } + QML_END_INSTR(BitAndInt, binaryop) + + QML_BEGIN_INSTR(BitXorInt, binaryop) + { + registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() ^ + registers[instr->binaryop.right].getint()); + } + QML_END_INSTR(BitXorInt, binaryop) + + QML_BEGIN_INSTR(AddReal, binaryop) + { + registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() + + registers[instr->binaryop.right].getqreal()); + } + QML_END_INSTR(AddReal, binaryop) + + QML_BEGIN_INSTR(AddString, binaryop) + { + QString &string = *registers[instr->binaryop.output].getstringptr(); + if (instr->binaryop.output == instr->binaryop.left) { + string += registers[instr->binaryop.right].getstringptr(); + } else { + string = *registers[instr->binaryop.left].getstringptr() + + *registers[instr->binaryop.right].getstringptr(); + } + } + QML_END_INSTR(AddString, binaryop) + + QML_BEGIN_INSTR(SubReal, binaryop) + { + registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() - + registers[instr->binaryop.right].getqreal()); + } + QML_END_INSTR(SubReal, binaryop) + + QML_BEGIN_INSTR(MulReal, binaryop) + { + registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() * + registers[instr->binaryop.right].getqreal()); + } + QML_END_INSTR(MulReal, binaryop) + + QML_BEGIN_INSTR(DivReal, binaryop) + { + registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() / + registers[instr->binaryop.right].getqreal()); + } + QML_END_INSTR(DivReal, binaryop) + + QML_BEGIN_INSTR(ModReal, binaryop) + { + Register &target = registers[instr->binaryop.output]; + const Register &left = registers[instr->binaryop.left]; + const Register &right = registers[instr->binaryop.right]; + if (QMetaType::QReal == QMetaType::Float) + target.setqreal(::fmodf(left.getqreal(), right.getqreal())); + else + target.setqreal(::fmod(left.getqreal(), right.getqreal())); + } + QML_END_INSTR(ModInt, binaryop) + + QML_BEGIN_INSTR(LShiftInt, binaryop) + { + registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() << + registers[instr->binaryop.right].getint()); + } + QML_END_INSTR(LShiftInt, binaryop) + + QML_BEGIN_INSTR(RShiftInt, binaryop) + { + registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() >> + registers[instr->binaryop.right].getint()); + } + QML_END_INSTR(RShiftInt, binaryop) + + QML_BEGIN_INSTR(URShiftInt, binaryop) + { + registers[instr->binaryop.output].setint((unsigned)registers[instr->binaryop.left].getint() >> + registers[instr->binaryop.right].getint()); + } + QML_END_INSTR(URShiftInt, binaryop) + + QML_BEGIN_INSTR(GtReal, binaryop) + { + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() > + registers[instr->binaryop.right].getqreal()); + } + QML_END_INSTR(GtReal, binaryop) + + QML_BEGIN_INSTR(LtReal, binaryop) + { + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() < + registers[instr->binaryop.right].getqreal()); + } + QML_END_INSTR(LtReal, binaryop) + + QML_BEGIN_INSTR(GeReal, binaryop) + { + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() >= + registers[instr->binaryop.right].getqreal()); + } + QML_END_INSTR(GeReal, binaryop) + + QML_BEGIN_INSTR(LeReal, binaryop) + { + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() <= + registers[instr->binaryop.right].getqreal()); + } + QML_END_INSTR(LeReal, binaryop) + + QML_BEGIN_INSTR(EqualReal, binaryop) + { + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() == + registers[instr->binaryop.right].getqreal()); + } + QML_END_INSTR(EqualReal, binaryop) + + QML_BEGIN_INSTR(NotEqualReal, binaryop) + { + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() != + registers[instr->binaryop.right].getqreal()); + } + QML_END_INSTR(NotEqualReal, binaryop) + + QML_BEGIN_INSTR(StrictEqualReal, binaryop) + { + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() == + registers[instr->binaryop.right].getqreal()); + } + QML_END_INSTR(StrictEqualReal, binaryop) + + QML_BEGIN_INSTR(StrictNotEqualReal, binaryop) + { + registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() != + registers[instr->binaryop.right].getqreal()); + } + QML_END_INSTR(StrictNotEqualReal, binaryop) + + QML_BEGIN_INSTR(GtString, binaryop) + { + const QString &a = *registers[instr->binaryop.left].getstringptr(); + const QString &b = *registers[instr->binaryop.right].getstringptr(); + bool result = a > b; + if (instr->binaryop.left == instr->binaryop.output) { + registers[instr->binaryop.output].cleanupString(); + MARK_CLEAN_REGISTER(instr->binaryop.output); + } + registers[instr->binaryop.output].setbool(result); + } + QML_END_INSTR(GtString, binaryop) + + QML_BEGIN_INSTR(LtString, binaryop) + { + const QString &a = *registers[instr->binaryop.left].getstringptr(); + const QString &b = *registers[instr->binaryop.right].getstringptr(); + bool result = a < b; + if (instr->binaryop.left == instr->binaryop.output) { + registers[instr->binaryop.output].cleanupString(); + MARK_CLEAN_REGISTER(instr->binaryop.output); + } + registers[instr->binaryop.output].setbool(result); + } + QML_END_INSTR(LtString, binaryop) + + QML_BEGIN_INSTR(GeString, binaryop) + { + const QString &a = *registers[instr->binaryop.left].getstringptr(); + const QString &b = *registers[instr->binaryop.right].getstringptr(); + bool result = a >= b; + if (instr->binaryop.left == instr->binaryop.output) { + registers[instr->binaryop.output].cleanupString(); + MARK_CLEAN_REGISTER(instr->binaryop.output); + } + registers[instr->binaryop.output].setbool(result); + } + QML_END_INSTR(GeString, binaryop) + + QML_BEGIN_INSTR(LeString, binaryop) + { + const QString &a = *registers[instr->binaryop.left].getstringptr(); + const QString &b = *registers[instr->binaryop.right].getstringptr(); + bool result = a <= b; + if (instr->binaryop.left == instr->binaryop.output) { + registers[instr->binaryop.output].cleanupString(); + MARK_CLEAN_REGISTER(instr->binaryop.output); + } + registers[instr->binaryop.output].setbool(result); + } + QML_END_INSTR(LeString, binaryop) + + QML_BEGIN_INSTR(EqualString, binaryop) + { + const QString &a = *registers[instr->binaryop.left].getstringptr(); + const QString &b = *registers[instr->binaryop.right].getstringptr(); + bool result = a == b; + if (instr->binaryop.left == instr->binaryop.output) { + registers[instr->binaryop.output].cleanupString(); + MARK_CLEAN_REGISTER(instr->binaryop.output); + } + registers[instr->binaryop.output].setbool(result); + } + QML_END_INSTR(EqualString, binaryop) + + QML_BEGIN_INSTR(NotEqualString, binaryop) + { + const QString &a = *registers[instr->binaryop.left].getstringptr(); + const QString &b = *registers[instr->binaryop.right].getstringptr(); + bool result = a != b; + if (instr->binaryop.left == instr->binaryop.output) { + registers[instr->binaryop.output].cleanupString(); + MARK_CLEAN_REGISTER(instr->binaryop.output); + } + registers[instr->binaryop.output].setbool(result); + } + QML_END_INSTR(NotEqualString, binaryop) + + QML_BEGIN_INSTR(StrictEqualString, binaryop) + { + const QString &a = *registers[instr->binaryop.left].getstringptr(); + const QString &b = *registers[instr->binaryop.right].getstringptr(); + bool result = a == b; + if (instr->binaryop.left == instr->binaryop.output) { + registers[instr->binaryop.output].cleanupString(); + MARK_CLEAN_REGISTER(instr->binaryop.output); + } + registers[instr->binaryop.output].setbool(result); + } + QML_END_INSTR(StrictEqualString, binaryop) + + QML_BEGIN_INSTR(StrictNotEqualString, binaryop) + { + const QString &a = *registers[instr->binaryop.left].getstringptr(); + const QString &b = *registers[instr->binaryop.right].getstringptr(); + bool result = a != b; + if (instr->binaryop.left == instr->binaryop.output) { + registers[instr->binaryop.output].cleanupString(); + MARK_CLEAN_REGISTER(instr->binaryop.output); + } + registers[instr->binaryop.output].setbool(result); + } + QML_END_INSTR(StrictNotEqualString, binaryop) + + QML_BEGIN_INSTR(NewString, construct) + { + Register &output = registers[instr->construct.reg]; + new (output.getstringptr()) QString; + STRING_REGISTER(instr->construct.reg); + } + QML_END_INSTR(NewString, construct) + + QML_BEGIN_INSTR(NewUrl, construct) + { + Register &output = registers[instr->construct.reg]; + new (output.geturlptr()) QUrl; + URL_REGISTER(instr->construct.reg); + } + QML_END_INSTR(NewUrl, construct) + + QML_BEGIN_INSTR(Fetch, fetch) + { + Register ® = registers[instr->fetch.reg]; + + if (reg.isUndefined()) + THROW_EXCEPTION(instr->fetch.exceptionId); + + QObject *object = reg.getQObject(); + if (!object) { + THROW_EXCEPTION(instr->fetch.exceptionId); + } else { + reg.init((Register::Type)instr->fetch.valueType); + if (instr->fetch.valueType >= FirstCleanupType) + MARK_REGISTER(instr->fetch.reg); + void *argv[] = { reg.typeDataPtr(), 0 }; + QMetaObject::metacall(object, QMetaObject::ReadProperty, instr->fetch.index, argv); + } + } + QML_END_INSTR(Fetch, fetch) + + QML_BEGIN_INSTR(TestV4Store, storetest) + { + Register &data = registers[instr->storetest.reg]; + testBindingResult(*testBindingSource, bindingLine, bindingColumn, context, + scope, data, instr->storetest.regType); + } + QML_END_INSTR(TestV4Store, storetest) + + QML_BEGIN_INSTR(Store, store) + { + Register &data = registers[instr->store.reg]; + + if (data.isUndefined()) + THROW_EXCEPTION_STR(instr->store.exceptionId, QLatin1String("Unable to assign undefined value")); + + int status = -1; + void *argv[] = { data.typeDataPtr(), 0, &status, &storeFlags }; + QMetaObject::metacall(output, QMetaObject::WriteProperty, + instr->store.index, argv); + + goto programExit; + } + QML_END_INSTR(Store, store) + + QML_BEGIN_INSTR(Copy, copy) + registers[instr->copy.reg].copy(registers[instr->copy.src]); + if (registers[instr->copy.reg].gettype() >= FirstCleanupType) + MARK_REGISTER(instr->copy.reg); + QML_END_INSTR(Copy, copy) + + QML_BEGIN_INSTR(Jump, jump) + if (instr->jump.reg == -1 || !registers[instr->jump.reg].getbool()) + code += instr->jump.count; + QML_END_INSTR(Jump, jump) + + QML_BEGIN_INSTR(BranchTrue, branchop) + if (registers[instr->branchop.reg].getbool()) + code += instr->branchop.offset; + QML_END_INSTR(BranchTrue, branchop) + + QML_BEGIN_INSTR(BranchFalse, branchop) + if (! registers[instr->branchop.reg].getbool()) + code += instr->branchop.offset; + QML_END_INSTR(BranchFalse, branchop) + + QML_BEGIN_INSTR(Branch, branchop) + code += instr->branchop.offset; + QML_END_INSTR(Branch, branchop) + + QML_BEGIN_INSTR(Block, blockop) + executedBlocks |= instr->blockop.block; + QML_END_INSTR(Block, blockop) + + QML_BEGIN_INSTR(InitString, initstring) + if (!identifiers[instr->initstring.offset].identifier) { + quint32 len = *(quint32 *)(data + instr->initstring.dataIdx); + QChar *strdata = (QChar *)(data + instr->initstring.dataIdx + sizeof(quint32)); + + QString str = QString::fromRawData(strdata, len); + + identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str); + } + QML_END_INSTR(InitString, initstring) + + QML_BEGIN_INSTR(CleanupRegister, cleanup) + registers[instr->cleanup.reg].cleanup(); + QML_END_INSTR(CleanupRegister, cleanup) + +#ifdef QML_THREADED_INTERPRETER + // nothing to do +#else + default: + qFatal("QDeclarativeV4: Unknown instruction %d encountered.", instr->common.type); + break; + } // switch + + } // while +#endif + + Q_ASSERT(!"Unreachable code reached"); + +programExit: +exceptionExit: + delete testBindingSource; + + int reg = 0; + while (cleanupRegisterMask) { + if (cleanupRegisterMask & 0x1) + registers[reg].cleanup(); + + reg++; + cleanupRegisterMask >>= 1; + } +} + +QT_END_NAMESPACE diff --git a/src/declarative/qml/v4/qdeclarativev4bindings_p.h b/src/declarative/qml/v4/qdeclarativev4bindings_p.h new file mode 100644 index 0000000000..9f225b65b6 --- /dev/null +++ b/src/declarative/qml/v4/qdeclarativev4bindings_p.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEV4BINDINGS_P_H +#define QDECLARATIVEV4BINDINGS_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 "private/qdeclarativeexpression_p.h" +#include "private/qdeclarativebinding_p.h" +#include "private/qdeclarativev4instruction_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QDeclarativeV4BindingsPrivate; +class QDeclarativeV4Bindings : public QObject, + public QDeclarativeAbstractExpression, + public QDeclarativeRefCount +{ +public: + QDeclarativeV4Bindings(const char *program, QDeclarativeContextData *context); + virtual ~QDeclarativeV4Bindings(); + + QDeclarativeAbstractBinding *configBinding(int index, QObject *target, QObject *scope, int property); + +#ifdef QML_THREADED_INTERPRETER + static void **getDecodeInstrTable(); +#endif + +protected: + int qt_metacall(QMetaObject::Call, int, void **); + +private: + Q_DISABLE_COPY(QDeclarativeV4Bindings) + Q_DECLARE_PRIVATE(QDeclarativeV4Bindings) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEV4BINDINGS_P_H + diff --git a/src/declarative/qml/v4/qdeclarativev4compiler.cpp b/src/declarative/qml/v4/qdeclarativev4compiler.cpp new file mode 100644 index 0000000000..a7eecce0c9 --- /dev/null +++ b/src/declarative/qml/v4/qdeclarativev4compiler.cpp @@ -0,0 +1,1340 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativev4compiler_p.h" +#include "qdeclarativev4compiler_p_p.h" +#include "qdeclarativev4program_p.h" +#include "qdeclarativev4ir_p.h" +#include "qdeclarativev4irbuilder_p.h" + +#include +#include +#include +#include // For AnchorLine +#include // For AnchorLine + +QT_BEGIN_NAMESPACE + +DEFINE_BOOL_CONFIG_OPTION(bindingsDump, QML_BINDINGS_DUMP) +DEFINE_BOOL_CONFIG_OPTION(qmlDisableOptimizer, QML_DISABLE_OPTIMIZER) +DEFINE_BOOL_CONFIG_OPTION(qmlExperimental, QML_EXPERIMENTAL) +DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER) +DEFINE_BOOL_CONFIG_OPTION(qmlBindingsTestEnv, QML_BINDINGS_TEST) + +Q_GLOBAL_STATIC(QDeclarativeFastProperties, fastProperties) + +static bool qmlBindingsTest = false; + +using namespace QDeclarativeJS; +QDeclarativeV4CompilerPrivate::QDeclarativeV4CompilerPrivate() +: _function(0) , _block(0) , _discarded(false) +{ +} + +// +// tracing +// +void QDeclarativeV4CompilerPrivate::trace(int line, int column) +{ + bytecode.clear(); + + this->currentReg = _function->tempCount; + + foreach (IR::BasicBlock *bb, _function->basicBlocks) { + if (! bb->isTerminated() && (bb->index + 1) < _function->basicBlocks.size()) + bb->JUMP(_function->basicBlocks.at(bb->index + 1)); + } + + QVector blocks; + trace(&blocks); + currentBlockMask = 0x00000001; + + + for (int i = 0; i < blocks.size(); ++i) { + IR::BasicBlock *block = blocks.at(i); + IR::BasicBlock *next = i + 1 < blocks.size() ? blocks.at(i + 1) : 0; + if (IR::Stmt *terminator = block->terminator()) { + if (IR::CJump *cj = terminator->asCJump()) { + if (cj->iffalse != next) { + block->i(new IR::Jump(cj->iffalse)); + } + } else if (IR::Jump *j = terminator->asJump()) { + if (j->target == next) { + delete block->statements.back(); + block->statements.resize(block->statements.size() - 1); + } + } + } + + block->offset = bytecode.size(); + + if (bytecode.isEmpty()) { + if (qmlBindingsTest || bindingsDump()) { + Instr id; + id.common.type = Instr::BindingId; + id.id.column = column; + id.id.line = line; + gen(id); + } + + if (qmlBindingsTest) { + QString str = expression->expression.asScript(); + QByteArray strdata((const char *)str.constData(), str.length() * sizeof(QChar)); + int offset = data.count(); + data += strdata; + + Instr test; + test.common.type = Instr::EnableV4Test; + test.string_value.reg = 0; + test.string_value.offset = offset; + test.string_value.length = str.length(); + gen(test); + } + } + + bool usic = false; + int patchesCount = patches.count(); + qSwap(usedSubscriptionIdsChanged, usic); + + int blockopIndex = bytecode.size(); + Instr blockop; + blockop.block(currentBlockMask); + gen(blockop); + + foreach (IR::Stmt *s, block->statements) + s->accept(this); + + qSwap(usedSubscriptionIdsChanged, usic); + + if (usic) { + if (currentBlockMask == 0x80000000) { + discard(); + return; + } + currentBlockMask <<= 1; + } else { + const int adjust = bytecode.remove(blockopIndex); + // Correct patches + for (int ii = patchesCount; ii < patches.count(); ++ii) + patches[ii].offset -= adjust; + } + } + +#ifdef DEBUG_IR_STRUCTURE + IR::IRDump dump; + for (int i = 0; i < blocks.size(); ++i) { + dump.basicblock(blocks.at(i)); + } +#endif + + + // back patching + foreach (const Patch &patch, patches) { + Instr &instr = bytecode[patch.offset]; + instr.branchop.offset = patch.block->offset - patch.offset - instr.size(); + } + + patches.clear(); +} + +void QDeclarativeV4CompilerPrivate::trace(QVector *blocks) +{ + QList todo = QList::fromVector(_function->basicBlocks); + while (! todo.isEmpty()) { + IR::BasicBlock *block = todo.takeFirst(); + + while (! blocks->contains(block)) { + blocks->append(block); + + if (IR::Stmt *terminator = block->terminator()) { + if (IR::CJump *cj = terminator->asCJump()) + block = cj->iffalse; + else if (IR::Jump *j = terminator->asJump()) + block = j->target; + } + } + } +} + +void QDeclarativeV4CompilerPrivate::traceExpression(IR::Expr *e, quint8 r) +{ + if (!e) { + discard(); + } else { + qSwap(currentReg, r); + e->accept(this); + qSwap(currentReg, r); + } +} + +// +// expressions +// +void QDeclarativeV4CompilerPrivate::visitConst(IR::Const *e) +{ + Instr i; + switch (e->type) { + case IR::BoolType: + i.move_reg_bool(currentReg, e->value); + gen(i); + break; + + case IR::IntType: + i.move_reg_int(currentReg, e->value); + gen(i); + break; + + case IR::RealType: + i.move_reg_qreal(currentReg, e->value); + gen(i); + break; + + default: + if (qmlVerboseCompiler()) + qWarning() << Q_FUNC_INFO << "unexpected type"; + discard(); + } +} + +void QDeclarativeV4CompilerPrivate::visitString(IR::String *e) +{ + registerLiteralString(currentReg, e->value); +} + +void QDeclarativeV4CompilerPrivate::visitName(IR::Name *e) +{ + if (e->base) { + // fetch the object and store it in reg. + traceExpression(e->base, currentReg); + } else { + _subscribeName.clear(); + } + + if (e->storage == IR::Name::RootStorage) { + + Instr instr; + instr.load_root(currentReg); + gen(instr); + + if (e->symbol == IR::Name::IdObject) { + // The ID is a reference to the root object + return; + } + + } else if (e->storage == IR::Name::ScopeStorage) { + + Instr instr; + instr.load_scope(currentReg); + gen(instr); + + _subscribeName << contextName(); + + } else if (e->storage == IR::Name::IdStorage) { + + Instr instr; + instr.load_id(currentReg, e->index); + gen(instr); + + _subscribeName << QLatin1String("$$$ID_") + e->id; + + if (blockNeedsSubscription(_subscribeName)) { + Instr sub; + sub.subscribeId(currentReg, subscriptionIndex(_subscribeName), instr.load.index); + gen(sub); + } + + return; + } else { + // No action needed + } + + switch (e->symbol) { + case IR::Name::Unbound: + case IR::Name::IdObject: + case IR::Name::Slot: + case IR::Name::Object: { + Q_ASSERT(!"Unreachable"); + discard(); + } break; + + case IR::Name::AttachType: { + _subscribeName << e->id; + + Instr attached; + attached.common.type = Instr::LoadAttached; + attached.attached.output = currentReg; + attached.attached.reg = currentReg; + attached.attached.exceptionId = exceptionId(e->line, e->column); + Q_ASSERT(e->declarativeType->attachedPropertiesId() != -1); + attached.attached.id = e->declarativeType->attachedPropertiesId(); + gen(attached); + } break; + + case IR::Name::Property: { + _subscribeName << e->id; + + QMetaProperty prop = e->meta->property(e->index); + int fastFetchIndex = fastProperties()->accessorIndexForProperty(e->meta, e->index); + + const int propTy = prop.userType(); + QDeclarativeRegisterType regType; + + switch (propTy) { + case QMetaType::QReal: + regType = QRealType; + break; + case QMetaType::Bool: + regType = BoolType; + break; + case QMetaType::Int: + regType = IntType; + break; + case QMetaType::QString: + regType = QStringType; + break; + + default: + if (propTy == qMetaTypeId()) { + regType = PODValueType; + } else if (propTy == qMetaTypeId()) { + regType = PODValueType; + } else if (QDeclarativeMetaType::isQObject(propTy)) { + regType = QObjectStarType; + } else { + if (qmlVerboseCompiler()) + qWarning() << "Discard unsupported property type:" << QMetaType::typeName(propTy); + discard(); // Unsupported type + return; + } + + break; + } // switch + + Instr fetch; + + if (fastFetchIndex != -1) { + fetch.common.type = Instr::FetchAndSubscribe; + fetch.fetchAndSubscribe.reg = currentReg; + fetch.fetchAndSubscribe.function = fastFetchIndex; + fetch.fetchAndSubscribe.subscription = subscriptionIndex(_subscribeName); + fetch.fetchAndSubscribe.exceptionId = exceptionId(e->line, e->column); + fetch.fetchAndSubscribe.valueType = regType; + } else { + if (blockNeedsSubscription(_subscribeName) && prop.hasNotifySignal() && prop.notifySignalIndex() != -1) { + Instr sub; + sub.subscribe(currentReg, subscriptionIndex(_subscribeName), prop.notifySignalIndex()); + gen(sub); + } + + fetch.common.type = Instr::Fetch; + fetch.fetch.reg = currentReg; + fetch.fetch.index = e->index; + fetch.fetch.exceptionId = exceptionId(e->line, e->column); + fetch.fetch.valueType = regType; + } + + gen(fetch); + + } break; + } // switch +} + +void QDeclarativeV4CompilerPrivate::visitTemp(IR::Temp *e) +{ + if (currentReg != e->index) { + Instr i; + i.move_reg_reg(currentReg, e->index); + gen(i); + } +} + +void QDeclarativeV4CompilerPrivate::visitUnop(IR::Unop *e) +{ + Instr i; + + quint8 src = currentReg; + + if (IR::Temp *temp = e->expr->asTemp()) { + src = temp->index; + } else { + traceExpression(e->expr, src); + } + + switch (e->op) { + case IR::OpInvalid: + Q_ASSERT(!"unreachable"); + break; + + case IR::OpIfTrue: + if (src != currentReg) { + i.move_reg_reg(currentReg, src); + gen(i); + } else { + // nothing to do + } + break; + + case IR::OpNot: + i.unary_not(currentReg, src); + gen(i); + break; + + case IR::OpUMinus: + if (e->expr->type == IR::RealType) { + i.uminus_real(currentReg, src); + gen(i); + } else if (e->expr->type == IR::IntType) { + convertToReal(e->expr, currentReg); + i.uminus_real(currentReg, src); + gen(i); + } else { + discard(); + } + break; + + case IR::OpUPlus: + if (e->expr->type == IR::RealType) { + i.uplus_real(currentReg, src); + gen(i); + } else if (e->expr->type == IR::IntType) { + convertToReal(e->expr, currentReg); + i.uplus_real(currentReg, src); + gen(i); + } else { + discard(); + } + break; + + case IR::OpCompl: + i.ucompl_real(currentReg, src); + gen(i); + discard(); // ??? + break; + + case IR::OpBitAnd: + case IR::OpBitOr: + case IR::OpBitXor: + case IR::OpAdd: + case IR::OpSub: + case IR::OpMul: + case IR::OpDiv: + case IR::OpMod: + case IR::OpLShift: + case IR::OpRShift: + case IR::OpURShift: + case IR::OpGt: + case IR::OpLt: + case IR::OpGe: + case IR::OpLe: + case IR::OpEqual: + case IR::OpNotEqual: + case IR::OpStrictEqual: + case IR::OpStrictNotEqual: + case IR::OpAnd: + case IR::OpOr: + Q_ASSERT(!"unreachable"); + break; + } // switch +} + +void QDeclarativeV4CompilerPrivate::convertToReal(IR::Expr *expr, int reg) +{ + if (expr->type == IR::RealType) + return; + + Instr conv; + conv.unaryop.output = reg; + conv.unaryop.src = reg; + + switch (expr->type) { + case IR::BoolType: + conv.common.type = Instr::ConvertBoolToReal; + gen(conv); + break; + + case IR::IntType: + conv.common.type = Instr::ConvertIntToReal; + gen(conv); + break; + + case IR::RealType: + // nothing to do + return; + + default: + discard(); + break; + } // switch +} + +void QDeclarativeV4CompilerPrivate::convertToInt(IR::Expr *expr, int reg) +{ + if (expr->type == IR::IntType) + return; + + Instr conv; + conv.unaryop.output = reg; + conv.unaryop.src = reg; + + switch (expr->type) { + case IR::BoolType: + conv.common.type = Instr::ConvertBoolToInt; + gen(conv); + break; + + case IR::IntType: + // nothing to do + return; + + case IR::RealType: + conv.common.type = Instr::ConvertRealToInt; + gen(conv); + break; + + default: + discard(); + break; + } // switch +} + +void QDeclarativeV4CompilerPrivate::convertToBool(IR::Expr *expr, int reg) +{ + if (expr->type == IR::BoolType) + return; + + Instr conv; + conv.unaryop.output = reg; + conv.unaryop.src = reg; + + switch (expr->type) { + case IR::BoolType: + // nothing to do + break; + + case IR::IntType: + conv.common.type = Instr::ConvertIntToBool; + gen(conv); + break; + + case IR::RealType: + conv.common.type = Instr::ConvertRealToBool; + gen(conv); + return; + + case IR::StringType: + conv.common.type = Instr::ConvertStringToBool; + gen(conv); + return; + + default: + discard(); + break; + } // switch +} + +quint8 QDeclarativeV4CompilerPrivate::instructionOpcode(IR::Binop *e) +{ + switch (e->op) { + case IR::OpInvalid: + return Instr::Noop; + + case IR::OpIfTrue: + case IR::OpNot: + case IR::OpUMinus: + case IR::OpUPlus: + case IR::OpCompl: + return Instr::Noop; + + case IR::OpBitAnd: + return Instr::BitAndInt; + + case IR::OpBitOr: + return Instr::BitOrInt; + + case IR::OpBitXor: + return Instr::BitXorInt; + + case IR::OpAdd: + if (e->type == IR::StringType) + return Instr::AddString; + return Instr::AddReal; + + case IR::OpSub: + return Instr::SubReal; + + case IR::OpMul: + return Instr::MulReal; + + case IR::OpDiv: + return Instr::DivReal; + + case IR::OpMod: + return Instr::ModReal; + + case IR::OpLShift: + return Instr::LShiftInt; + + case IR::OpRShift: + return Instr::RShiftInt; + + case IR::OpURShift: + return Instr::URShiftInt; + + case IR::OpGt: + if (e->left->type == IR::StringType) + return Instr::GtString; + return Instr::GtReal; + + case IR::OpLt: + if (e->left->type == IR::StringType) + return Instr::LtString; + return Instr::LtReal; + + case IR::OpGe: + if (e->left->type == IR::StringType) + return Instr::GeString; + return Instr::GeReal; + + case IR::OpLe: + if (e->left->type == IR::StringType) + return Instr::LeString; + return Instr::LeReal; + + case IR::OpEqual: + if (e->left->type == IR::StringType) + return Instr::EqualString; + return Instr::EqualReal; + + case IR::OpNotEqual: + if (e->left->type == IR::StringType) + return Instr::NotEqualString; + return Instr::NotEqualReal; + + case IR::OpStrictEqual: + if (e->left->type == IR::StringType) + return Instr::StrictEqualString; + return Instr::StrictEqualReal; + + case IR::OpStrictNotEqual: + if (e->left->type == IR::StringType) + return Instr::StrictNotEqualString; + return Instr::StrictNotEqualReal; + + case IR::OpAnd: + case IR::OpOr: + return Instr::Noop; + + } // switch + + return Instr::Noop; +} + +void QDeclarativeV4CompilerPrivate::visitBinop(IR::Binop *e) +{ + int left = currentReg; + int right = currentReg + 1; + + if (e->left->asTemp() && e->type != IR::StringType) // Not sure if the e->type != String test is needed + left = e->left->asTemp()->index; + else + traceExpression(e->left, left); + + if (IR::Temp *t = e->right->asTemp()) + right = t->index; + else + traceExpression(e->right, right); + + if (e->left->type != e->right->type) { + if (qmlVerboseCompiler()) + qWarning().nospace() << "invalid operands to binary operator " << IR::binaryOperator(e->op) + << "(`" << IR::binaryOperator(e->left->type) + << "' and `" + << IR::binaryOperator(e->right->type) + << "'"; + discard(); + return; + } + + switch (e->op) { + case IR::OpInvalid: + discard(); + break; + + // unary + case IR::OpIfTrue: + case IR::OpNot: + case IR::OpUMinus: + case IR::OpUPlus: + case IR::OpCompl: + discard(); + break; + + case IR::OpBitAnd: + case IR::OpBitOr: + case IR::OpBitXor: + case IR::OpLShift: + case IR::OpRShift: + case IR::OpURShift: + convertToInt(e->left, left); + convertToInt(e->right, right); + break; + + case IR::OpAdd: + if (e->type != IR::StringType) { + convertToReal(e->left, left); + convertToReal(e->right, right); + } + break; + + case IR::OpSub: + case IR::OpMul: + case IR::OpDiv: + case IR::OpMod: + convertToReal(e->left, left); + convertToReal(e->right, right); + break; + + case IR::OpGt: + case IR::OpLt: + case IR::OpGe: + case IR::OpLe: + case IR::OpEqual: + case IR::OpNotEqual: + case IR::OpStrictEqual: + case IR::OpStrictNotEqual: + if (e->left->type != IR::StringType) { + convertToReal(e->left, left); + convertToReal(e->right, right); + } + break; + + case IR::OpAnd: + case IR::OpOr: + discard(); // ### unreachable + break; + } // switch + + const quint8 opcode = instructionOpcode(e); + if (opcode != Instr::Noop) { + Instr instr; + instr.common.type = opcode; + instr.binaryop.output = currentReg; + instr.binaryop.left = left; + instr.binaryop.right = right; + gen(instr); + } +} + +void QDeclarativeV4CompilerPrivate::visitCall(IR::Call *call) +{ + if (IR::Name *name = call->base->asName()) { + if (call->args.size() == 1 && call->args.at(0)->type == IR::RealType) { + traceExpression(call->args.at(0), currentReg); + + Instr instr; + instr.common.type = Instr::Noop; + + switch (name->builtin) { + case IR::NoBuiltinSymbol: + break; + + case IR::MathSinBultinFunction: + instr.math_sin_real(currentReg); + break; + + case IR::MathCosBultinFunction: + instr.math_cos_real(currentReg); + break; + + case IR::MathRoundBultinFunction: + instr.math_round_real(currentReg); + break; + + case IR::MathFloorBultinFunction: + instr.math_floor_real(currentReg); + break; + + case IR::MathPIBuiltinConstant: + break; + } // switch + + if (instr.common.type != Instr::Noop) { + gen(instr); + return; + } + } + } + + if (qmlVerboseCompiler()) + qWarning() << "TODO:" << Q_FUNC_INFO << __LINE__; + discard(); +} + + +// +// statements +// +void QDeclarativeV4CompilerPrivate::visitExp(IR::Exp *s) +{ + traceExpression(s->expr, currentReg); +} + +void QDeclarativeV4CompilerPrivate::visitMove(IR::Move *s) +{ + IR::Temp *target = s->target->asTemp(); + Q_ASSERT(target != 0); + + quint8 dest = target->index; + + if (target->type != s->source->type) { + quint8 src = dest; + + if (IR::Temp *t = s->source->asTemp()) + src = t->index; + else + traceExpression(s->source, dest); + + Instr conv; + conv.common.type = Instr::Noop; + if (target->type == IR::BoolType) { + switch (s->source->type) { + case IR::IntType: conv.common.type = Instr::ConvertIntToBool; break; + case IR::RealType: conv.common.type = Instr::ConvertRealToBool; break; + case IR::StringType: conv.common.type = Instr::ConvertStringToBool; break; + default: break; + } // switch + } else if (target->type == IR::IntType) { + switch (s->source->type) { + case IR::BoolType: conv.common.type = Instr::ConvertBoolToInt; break; + case IR::RealType: { + if (s->isMoveForReturn) + conv.common.type = Instr::MathRoundReal; + else + conv.common.type = Instr::ConvertRealToInt; + break; + } + case IR::StringType: conv.common.type = Instr::ConvertStringToInt; break; + default: break; + } // switch + } else if (target->type == IR::RealType) { + switch (s->source->type) { + case IR::BoolType: conv.common.type = Instr::ConvertBoolToReal; break; + case IR::IntType: conv.common.type = Instr::ConvertIntToReal; break; + case IR::StringType: conv.common.type = Instr::ConvertStringToReal; break; + default: break; + } // switch + } else if (target->type == IR::StringType) { + switch (s->source->type) { + case IR::BoolType: conv.common.type = Instr::ConvertBoolToString; break; + case IR::IntType: conv.common.type = Instr::ConvertIntToString; break; + case IR::RealType: conv.common.type = Instr::ConvertRealToString; break; + default: break; + } // switch + } + if (conv.common.type != Instr::Noop) { + conv.unaryop.output = dest; + conv.unaryop.src = src; + gen(conv); + } else { + discard(); + } + } else { + traceExpression(s->source, dest); + } +} + +void QDeclarativeV4CompilerPrivate::visitJump(IR::Jump *s) +{ + patches.append(Patch(s->target, bytecode.size())); + + Instr i; + i.branch(0); // ### backpatch + gen(i); +} + +void QDeclarativeV4CompilerPrivate::visitCJump(IR::CJump *s) +{ + traceExpression(s->cond, currentReg); + + patches.append(Patch(s->iftrue, bytecode.size())); + + Instr i; + i.branch_true(currentReg, 0); // ### backpatch + gen(i); +} + +void QDeclarativeV4CompilerPrivate::visitRet(IR::Ret *s) +{ + Q_ASSERT(s->expr != 0); + + int storeReg = currentReg; + + if (IR::Temp *temp = s->expr->asTemp()) { + storeReg = temp->index; + } else { + traceExpression(s->expr, storeReg); + } + + if (qmlBindingsTest) { + Instr test; + test.common.type = Instr::TestV4Store; + test.storetest.reg = storeReg; + switch (s->type) { + case IR::StringType: + test.storetest.regType = QMetaType::QString; + break; + case IR::UrlType: + test.storetest.regType = QMetaType::QUrl; + break; + case IR::AnchorLineType: + test.storetest.regType = qMetaTypeId(); + break; + case IR::SGAnchorLineType: + test.storetest.regType = qMetaTypeId(); + break; + case IR::ObjectType: + test.storetest.regType = QMetaType::QObjectStar; + break; + case IR::BoolType: + test.storetest.regType = QMetaType::Bool; + break; + case IR::IntType: + test.storetest.regType = QMetaType::Int; + break; + case IR::RealType: + test.storetest.regType = QMetaType::QReal; + break; + default: + discard(); + return; + } + gen(test); + } + + Instr store; + store.common.type = Instr::Store; + store.store.output = 0; + store.store.index = expression->property->index; + store.store.reg = storeReg; + store.store.exceptionId = exceptionId(s->line, s->column); + gen(store); +} + +void QDeclarativeV4Compiler::dump(const QByteArray &programData) +{ + const QDeclarativeV4Program *program = (const QDeclarativeV4Program *)programData.constData(); + + qWarning() << "Program.bindings:" << program->bindings; + qWarning() << "Program.dataLength:" << program->dataLength; + qWarning() << "Program.subscriptions:" << program->subscriptions; + qWarning() << "Program.indentifiers:" << program->identifiers; + + const int programSize = program->instructionCount; + const char *start = program->instructions(); + const char *code = start; + const char *end = code + programSize; + while (code < end) { + Instr *instr = (Instr *) code; + instr->dump(code - start); + code += instr->size(); + } +} + +QDeclarativeFastProperties *QDeclarativeV4Compiler::fastPropertyAccessor() +{ + return fastProperties(); +} + +/*! +Clear the state associated with attempting to compile a specific binding. +This does not clear the global "committed binding" states. +*/ +void QDeclarativeV4CompilerPrivate::resetInstanceState() +{ + registerCleanups.clear(); + data = committed.data; + exceptions = committed.exceptions; + usedSubscriptionIds.clear(); + subscriptionIds = committed.subscriptionIds; + registeredStrings = committed.registeredStrings; + bytecode.clear(); + patches.clear(); + currentReg = 0; +} + +/*! +Mark the last compile as successful, and add it to the "committed data" +section. + +Returns the index for the committed binding. +*/ +int QDeclarativeV4CompilerPrivate::commitCompile() +{ + int rv = committed.count(); + committed.offsets << committed.bytecode.count(); + committed.dependencies << usedSubscriptionIds; + committed.bytecode += bytecode.code(); + committed.data = data; + committed.exceptions = exceptions; + committed.subscriptionIds = subscriptionIds; + committed.registeredStrings = registeredStrings; + return rv; +} + +bool QDeclarativeV4CompilerPrivate::compile(QDeclarativeJS::AST::Node *node) +{ + resetInstanceState(); + + if (expression->property->type == -1) + return false; + + AST::SourceLocation location; + if (AST::ExpressionNode *astExpression = node->expressionCast()) { + location = astExpression->firstSourceLocation(); + } else if (AST::Statement *astStatement = node->statementCast()) { + if (AST::Block *block = AST::cast(astStatement)) + location = block->lbraceToken; + else if (AST::IfStatement *ifStmt = AST::cast(astStatement)) + location = ifStmt->ifToken; + else + return false; + } else { + return false; + } + + IR::Module module; + IR::Function *function = 0; + + QDeclarativeV4IRBuilder irBuilder(expression, engine); + if (!(function = irBuilder(&module, node))) + return false; + + bool discarded = false; + qSwap(_discarded, discarded); + qSwap(_function, function); + trace(location.startLine, location.startColumn); + qSwap(_function, function); + qSwap(_discarded, discarded); + + if (qmlVerboseCompiler()) { + QTextStream qerr(stderr, QIODevice::WriteOnly); + if (discarded) + qerr << "======== TODO ====== " << endl; + else + qerr << "==================== " << endl; + qerr << "\tline: " << location.startLine + << "\tcolumn: " << location.startColumn + << endl; + foreach (IR::BasicBlock *bb, function->basicBlocks) + bb->dump(qerr); + qerr << endl; + } + + if (discarded || subscriptionIds.count() > 0xFFFF || registeredStrings.count() > 0xFFFF) + return false; + + return true; +} + +// Returns a reg +int QDeclarativeV4CompilerPrivate::registerLiteralString(quint8 reg, const QString &str) +{ + // ### string cleanup + + QByteArray strdata((const char *)str.constData(), str.length() * sizeof(QChar)); + int offset = data.count(); + data += strdata; + + Instr string; + string.common.type = Instr::String; + string.string_value.reg = reg; + string.string_value.offset = offset; + string.string_value.length = str.length(); + gen(string); + + return reg; +} + +// Returns an identifier offset +int QDeclarativeV4CompilerPrivate::registerString(const QString &string) +{ + Q_ASSERT(!string.isEmpty()); + + QHash >::ConstIterator iter = registeredStrings.find(string); + + if (iter == registeredStrings.end()) { + quint32 len = string.length(); + QByteArray lendata((const char *)&len, sizeof(quint32)); + QByteArray strdata((const char *)string.constData(), string.length() * sizeof(QChar)); + strdata.prepend(lendata); + int rv = data.count(); + data += strdata; + + iter = registeredStrings.insert(string, qMakePair(registeredStrings.count(), rv)); + } + + Instr reg; + reg.common.type = Instr::InitString; + reg.initstring.offset = iter->first; + reg.initstring.dataIdx = iter->second; + gen(reg); + return reg.initstring.offset; +} + +/*! +Returns true if the current expression has not already subscribed to \a sub in currentBlockMask. +*/ +bool QDeclarativeV4CompilerPrivate::blockNeedsSubscription(const QStringList &sub) +{ + QString str = sub.join(QLatin1String(".")); + + QHash::ConstIterator iter = subscriptionIds.find(str); + if (iter == subscriptionIds.end()) + return true; + + QHash::ConstIterator uiter = usedSubscriptionIds.find(*iter); + if (uiter == usedSubscriptionIds.end()) + return true; + else + return !(*uiter & currentBlockMask); +} + +int QDeclarativeV4CompilerPrivate::subscriptionIndex(const QStringList &sub) +{ + QString str = sub.join(QLatin1String(".")); + QHash::ConstIterator iter = subscriptionIds.find(str); + if (iter == subscriptionIds.end()) + iter = subscriptionIds.insert(str, subscriptionIds.count()); + if (!(usedSubscriptionIds[*iter] & currentBlockMask)) { + usedSubscriptionIds[*iter] |= currentBlockMask; + usedSubscriptionIdsChanged = true; + } + return *iter; +} + +quint32 QDeclarativeV4CompilerPrivate::subscriptionBlockMask(const QStringList &sub) +{ + QString str = sub.join(QLatin1String(".")); + + QHash::ConstIterator iter = subscriptionIds.find(str); + Q_ASSERT(iter != subscriptionIds.end()); + + QHash::ConstIterator uiter = usedSubscriptionIds.find(*iter); + Q_ASSERT(uiter != usedSubscriptionIds.end()); + + return *uiter; +} + +quint8 QDeclarativeV4CompilerPrivate::exceptionId(quint32 line, quint32 column) +{ + quint8 rv = 0xFF; + if (exceptions.count() < 0xFF) { + rv = (quint8)exceptions.count(); + quint64 e = line; + e <<= 32; + e |= column; + exceptions.append(e); + } + return rv; +} + +quint8 QDeclarativeV4CompilerPrivate::exceptionId(QDeclarativeJS::AST::ExpressionNode *n) +{ + quint8 rv = 0xFF; + if (n && exceptions.count() < 0xFF) { + QDeclarativeJS::AST::SourceLocation l = n->firstSourceLocation(); + rv = exceptionId(l.startLine, l.startColumn); + } + return rv; +} + +QDeclarativeV4Compiler::QDeclarativeV4Compiler() +: d(new QDeclarativeV4CompilerPrivate) +{ + qmlBindingsTest |= qmlBindingsTestEnv(); +} + +QDeclarativeV4Compiler::~QDeclarativeV4Compiler() +{ + delete d; d = 0; +} + +/* +Returns true if any bindings were compiled. +*/ +bool QDeclarativeV4Compiler::isValid() const +{ + return !d->committed.bytecode.isEmpty(); +} + +/* +-1 on failure, otherwise the binding index to use. +*/ +int QDeclarativeV4Compiler::compile(const Expression &expression, QDeclarativeEnginePrivate *engine) +{ + if (!expression.expression.asAST()) return false; + + if (!qmlExperimental() && expression.property->isValueTypeSubProperty) + return -1; + + if (qmlDisableOptimizer()) + return -1; + + d->expression = &expression; + d->engine = engine; + + if (d->compile(expression.expression.asAST())) { + return d->commitCompile(); + } else { + return -1; + } +} + +QByteArray QDeclarativeV4CompilerPrivate::buildSignalTable() const +{ + QHash > > table; + + for (int ii = 0; ii < committed.count(); ++ii) { + const QHash &deps = committed.dependencies.at(ii); + for (QHash::ConstIterator iter = deps.begin(); iter != deps.end(); ++iter) + table[iter.key()].append(qMakePair(ii, iter.value())); + } + + QVector header; + QVector data; + for (int ii = 0; ii < committed.subscriptionIds.count(); ++ii) { + header.append(committed.subscriptionIds.count() + data.count()); + const QList > &bindings = table[ii]; + data.append(bindings.count()); + for (int jj = 0; jj < bindings.count(); ++jj) { + data.append(bindings.at(jj).first); + data.append(bindings.at(jj).second); + } + } + header << data; + + return QByteArray((const char *)header.constData(), header.count() * sizeof(quint32)); +} + +QByteArray QDeclarativeV4CompilerPrivate::buildExceptionData() const +{ + QByteArray rv; + rv.resize(committed.exceptions.count() * sizeof(quint64)); + ::memcpy(rv.data(), committed.exceptions.constData(), rv.size()); + return rv; +} + +/* +Returns the compiled program. +*/ +QByteArray QDeclarativeV4Compiler::program() const +{ + QByteArray programData; + + if (isValid()) { + QDeclarativeV4Program prog; + prog.bindings = d->committed.count(); + + Bytecode bc; + Instr jump; + jump.common.type = Instr::Jump; + jump.jump.reg = -1; + + for (int ii = 0; ii < d->committed.count(); ++ii) { + jump.jump.count = d->committed.count() - ii - 1; + jump.jump.count*= jump.size(); + jump.jump.count+= d->committed.offsets.at(ii); + bc.append(jump); + } + + + QByteArray bytecode = bc.code(); + bytecode += d->committed.bytecode; + + QByteArray data = d->committed.data; + while (data.count() % 4) data.append('\0'); + prog.signalTableOffset = data.count(); + data += d->buildSignalTable(); + while (data.count() % 4) data.append('\0'); + prog.exceptionDataOffset = data.count(); + data += d->buildExceptionData(); + + prog.dataLength = 4 * ((data.size() + 3) / 4); + prog.subscriptions = d->committed.subscriptionIds.count(); + prog.identifiers = d->committed.registeredStrings.count(); + prog.instructionCount = bytecode.count(); + int size = sizeof(QDeclarativeV4Program) + bytecode.count(); + size += prog.dataLength; + + programData.resize(size); + memcpy(programData.data(), &prog, sizeof(QDeclarativeV4Program)); + if (prog.dataLength) + memcpy((char *)((QDeclarativeV4Program *)programData.data())->data(), data.constData(), + data.size()); + memcpy((char *)((QDeclarativeV4Program *)programData.data())->instructions(), bytecode.constData(), + bytecode.count()); + } + + if (bindingsDump()) { + qWarning().nospace() << "Subscription slots:"; + + for (QHash::ConstIterator iter = d->committed.subscriptionIds.begin(); + iter != d->committed.subscriptionIds.end(); + ++iter) { + qWarning().nospace() << " " << iter.value() << "\t-> " << iter.key(); + } + + + QDeclarativeV4Compiler::dump(programData); + } + + return programData; +} + +void QDeclarativeV4Compiler::enableBindingsTest(bool e) +{ + if (e) + qmlBindingsTest = true; + else + qmlBindingsTest = qmlBindingsTestEnv(); +} + +QT_END_NAMESPACE diff --git a/src/declarative/qml/v4/qdeclarativev4compiler_p.h b/src/declarative/qml/v4/qdeclarativev4compiler_p.h new file mode 100644 index 0000000000..c10691dc87 --- /dev/null +++ b/src/declarative/qml/v4/qdeclarativev4compiler_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEV4COMPILER_P_H +#define QDECLARATIVEV4COMPILER_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 "private/qdeclarativeexpression_p.h" +#include "private/qdeclarativebinding_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QDeclarativeFastProperties; +class QDeclarativeTypeNameCache; +class QDeclarativeV4CompilerPrivate; +class Q_AUTOTEST_EXPORT QDeclarativeV4Compiler +{ +public: + QDeclarativeV4Compiler(); + ~QDeclarativeV4Compiler(); + + // Returns true if bindings were compiled + bool isValid() const; + + struct Expression + { + QDeclarativeParser::Object *component; + QDeclarativeParser::Object *context; + QDeclarativeParser::Property *property; + QDeclarativeParser::Variant expression; + QHash ids; + QDeclarativeTypeNameCache *importCache; + QDeclarativeImports imports; + }; + + // -1 on failure, otherwise the binding index to use + int compile(const Expression &, QDeclarativeEnginePrivate *); + + // Returns the compiled program + QByteArray program() const; + + static void dump(const QByteArray &); + static QDeclarativeFastProperties *fastPropertyAccessor(); + static void enableBindingsTest(bool); +private: + QDeclarativeV4CompilerPrivate *d; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEV4COMPILER_P_H + diff --git a/src/declarative/qml/v4/qdeclarativev4compiler_p_p.h b/src/declarative/qml/v4/qdeclarativev4compiler_p_p.h new file mode 100644 index 0000000000..1b2a998422 --- /dev/null +++ b/src/declarative/qml/v4/qdeclarativev4compiler_p_p.h @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEV4COMPILER_P_P_H +#define QDECLARATIVEV4COMPILER_P_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 "qdeclarativev4instruction_p.h" +#include "qdeclarativev4ir_p.h" +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QDeclarativeV4CompilerPrivate: protected QDeclarativeJS::IR::ExprVisitor, + protected QDeclarativeJS::IR::StmtVisitor +{ +public: + QDeclarativeV4CompilerPrivate(); + + void resetInstanceState(); + int commitCompile(); + + const QDeclarativeV4Compiler::Expression *expression; + QDeclarativeEnginePrivate *engine; + + QString contextName() const { return QLatin1String("$$$SCOPE_") + QString::number((quintptr)expression->context, 16); } + + bool compile(QDeclarativeJS::AST::Node *); + + QHash > registerCleanups; + + int registerLiteralString(quint8 reg, const QString &); + int registerString(const QString &); + QHash > registeredStrings; + QByteArray data; + + bool blockNeedsSubscription(const QStringList &); + int subscriptionIndex(const QStringList &); + quint32 subscriptionBlockMask(const QStringList &); + + quint8 exceptionId(quint32 line, quint32 column); + quint8 exceptionId(QDeclarativeJS::AST::ExpressionNode *); + QVector exceptions; + + QHash usedSubscriptionIds; + + QHash subscriptionIds; + QDeclarativeJS::Bytecode bytecode; + + // back patching + struct Patch { + QDeclarativeJS::IR::BasicBlock *block; // the basic block + int offset; // the index of the instruction to patch + Patch(QDeclarativeJS::IR::BasicBlock *block = 0, int index = -1) + : block(block), offset(index) {} + }; + QVector patches; + + // Committed binding data + struct { + QList offsets; + QList > dependencies; + + //QDeclarativeJS::Bytecode bytecode; + QByteArray bytecode; + QByteArray data; + QHash subscriptionIds; + QVector exceptions; + + QHash > registeredStrings; + + int count() const { return offsets.count(); } + } committed; + + QByteArray buildSignalTable() const; + QByteArray buildExceptionData() const; + + void convertToReal(QDeclarativeJS::IR::Expr *expr, int reg); + void convertToInt(QDeclarativeJS::IR::Expr *expr, int reg); + void convertToBool(QDeclarativeJS::IR::Expr *expr, int reg); + quint8 instructionOpcode(QDeclarativeJS::IR::Binop *e); + +protected: + + // + // tracing + // + void trace(int line, int column); + void trace(QVector *blocks); + void traceExpression(QDeclarativeJS::IR::Expr *e, quint8 r); + + inline void gen(const QDeclarativeJS::Instr &i) { bytecode.append(i); } + + // + // expressions + // + virtual void visitConst(QDeclarativeJS::IR::Const *e); + virtual void visitString(QDeclarativeJS::IR::String *e); + virtual void visitName(QDeclarativeJS::IR::Name *e); + virtual void visitTemp(QDeclarativeJS::IR::Temp *e); + virtual void visitUnop(QDeclarativeJS::IR::Unop *e); + virtual void visitBinop(QDeclarativeJS::IR::Binop *e); + virtual void visitCall(QDeclarativeJS::IR::Call *e); + + // + // statements + // + virtual void visitExp(QDeclarativeJS::IR::Exp *s); + virtual void visitMove(QDeclarativeJS::IR::Move *s); + virtual void visitJump(QDeclarativeJS::IR::Jump *s); + virtual void visitCJump(QDeclarativeJS::IR::CJump *s); + virtual void visitRet(QDeclarativeJS::IR::Ret *s); + +private: + QStringList _subscribeName; + QDeclarativeJS::IR::Function *_function; + QDeclarativeJS::IR::BasicBlock *_block; + void discard() { _discarded = true; } + bool _discarded; + quint8 currentReg; + + bool usedSubscriptionIdsChanged; + quint32 currentBlockMask; +}; + + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEV4COMPILER_P_P_H + diff --git a/src/declarative/qml/v4/qdeclarativev4instruction.cpp b/src/declarative/qml/v4/qdeclarativev4instruction.cpp new file mode 100644 index 0000000000..1f24f30c25 --- /dev/null +++ b/src/declarative/qml/v4/qdeclarativev4instruction.cpp @@ -0,0 +1,559 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativev4instruction_p.h" +#include "qdeclarativev4bindings_p.h" + +#include +#include + +// Define this to do a test dump of all the instructions at startup. This is +// helpful to test that each instruction's Instr::dump() case uses the correct +// number of tabs etc and otherwise looks correct. +// #define DEBUG_INSTR_DUMP + +QT_BEGIN_NAMESPACE + +DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER) + +namespace QDeclarativeJS { + +#ifdef DEBUG_INSTR_DUMP +static struct DumpInstrAtStartup { + DumpInstrAtStartup() { +#define DUMP_INSTR_AT_STARTUP(Type, FMT) { Instr i; i.common.type = Instr::Type; i.dump(0); } + FOR_EACH_QML_INSTR(DUMP_INSTR_AT_STARTUP); + } +} dump_instr_at_startup; +#endif + +int Instr::size() const +{ +#define QML_RETURN_INSTR_SIZE(I, FMT) case I: return QML_INSTR_SIZE(I, FMT); + switch (common.type) { + FOR_EACH_QML_INSTR(QML_RETURN_INSTR_SIZE) + } +#undef QML_RETURN_INSTR_SIZE + return 0; +} + +void Instr::dump(int address) const +{ + QByteArray leading; + if (address != -1) { + leading = QByteArray::number(address); + leading.prepend(QByteArray(8 - leading.count(), ' ')); + leading.append("\t"); + } + +#define INSTR_DUMP qWarning().nospace() << leading.constData() + + switch (common.type) { + case Instr::Noop: + INSTR_DUMP << "\t" << "Noop"; + break; + case Instr::BindingId: + INSTR_DUMP << id.line << ":" << id.column << ":"; + break; + case Instr::Subscribe: + INSTR_DUMP << "\t" << "Subscribe" << "\t\t" << "Object_Reg(" << subscribeop.reg << ") Notify_Signal(" << subscribeop.index << ") -> Subscribe_Slot(" << subscribeop.offset << ")"; + break; + case Instr::SubscribeId: + INSTR_DUMP << "\t" << "SubscribeId" << "\t\t" << "Id_Offset(" << subscribeop.index << ") -> Subscribe_Slot(" << subscribeop.offset << ")"; + break; + case Instr::FetchAndSubscribe: + INSTR_DUMP << "\t" << "FetchAndSubscribe" << "\t" << "Object_Reg(" << fetchAndSubscribe.reg << ") Fast_Accessor(" << fetchAndSubscribe.function << ") -> Output_Reg(" << fetchAndSubscribe.reg << ") Subscription_Slot(" << fetchAndSubscribe.subscription << ")"; + break; + case Instr::LoadId: + INSTR_DUMP << "\t" << "LoadId" << "\t\t\t" << "Id_Offset(" << load.index << ") -> Output_Reg(" << load.reg << ")"; + break; + case Instr::LoadScope: + INSTR_DUMP << "\t" << "LoadScope" << "\t\t" << "-> Output_Reg(" << load.reg << ")"; + break; + case Instr::LoadRoot: + INSTR_DUMP << "\t" << "LoadRoot" << "\t\t" << "-> Output_Reg(" << load.reg << ")"; + break; + case Instr::LoadAttached: + INSTR_DUMP << "\t" << "LoadAttached" << "\t\t" << "Object_Reg(" << attached.reg << ") Attached_Index(" << attached.id << ") -> Output_Reg(" << attached.output << ")"; + break; + case Instr::UnaryNot: + INSTR_DUMP << "\t" << "UnaryNot" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::UnaryMinusReal: + INSTR_DUMP << "\t" << "UnaryMinusReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::UnaryMinusInt: + INSTR_DUMP << "\t" << "UnaryMinusInt" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::UnaryPlusReal: + INSTR_DUMP << "\t" << "UnaryPlusReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::UnaryPlusInt: + INSTR_DUMP << "\t" << "UnaryPlusInt" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::ConvertBoolToInt: + INSTR_DUMP << "\t" << "ConvertBoolToInt" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::ConvertBoolToReal: + INSTR_DUMP << "\t" << "ConvertBoolToReal" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::ConvertBoolToString: + INSTR_DUMP << "\t" << "ConvertBoolToString" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::ConvertIntToBool: + INSTR_DUMP << "\t" << "ConvertIntToBool" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::ConvertIntToReal: + INSTR_DUMP << "\t" << "ConvertIntToReal" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::ConvertIntToString: + INSTR_DUMP << "\t" << "ConvertIntToString" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::ConvertRealToBool: + INSTR_DUMP << "\t" << "ConvertRealToBool" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::ConvertRealToInt: + INSTR_DUMP << "\t" << "ConvertRealToInt" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::ConvertRealToString: + INSTR_DUMP << "\t" << "ConvertRealToString" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::ConvertStringToBool: + INSTR_DUMP << "\t" << "ConvertStringToBool" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::ConvertStringToInt: + INSTR_DUMP << "\t" << "ConvertStringToInt" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::ConvertStringToReal: + INSTR_DUMP << "\t" << "ConvertStringToReal" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::MathSinReal: + INSTR_DUMP << "\t" << "MathSinReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::MathCosReal: + INSTR_DUMP << "\t" << "MathCosReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::MathRoundReal: + INSTR_DUMP << "\t" << "MathRoundReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::MathFloorReal: + INSTR_DUMP << "\t" << "MathFloorReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::MathPIReal: + INSTR_DUMP << "\t" << "MathPIReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")"; + break; + case Instr::Real: + INSTR_DUMP << "\t" << "Real" << "\t\t\t" << "Constant(" << real_value.value << ") -> Output_Reg(" << real_value.reg << ")"; + break; + case Instr::Int: + INSTR_DUMP << "\t" << "Int" << "\t\t\t" << "Constant(" << int_value.value << ") -> Output_Reg(" << int_value.reg << ")"; + break; + case Instr::Bool: + INSTR_DUMP << "\t" << "Bool" << "\t\t\t" << "Constant(" << bool_value.value << ") -> Output_Reg(" << bool_value.reg << ")"; + break; + case Instr::String: + INSTR_DUMP << "\t" << "String" << "\t\t\t" << "String_DataIndex(" << string_value.offset << ") String_Length(" << string_value.length << ") -> Output_Register(" << string_value.reg << ")"; + break; + case Instr::EnableV4Test: + INSTR_DUMP << "\t" << "EnableV4Test" << "\t\t" << "String_DataIndex(" << string_value.offset << ") String_Length(" << string_value.length << ")"; + break; + case Instr::TestV4Store: + INSTR_DUMP << "\t" << "TestV4Store" << "\t\t" << "Input_Reg(" << storetest.reg << ") Reg_Type(" << storetest.regType << ")"; + break; + case Instr::BitAndInt: + INSTR_DUMP << "\t" << "BitAndInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::BitOrInt: + INSTR_DUMP << "\t" << "BitOrInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::BitXorInt: + INSTR_DUMP << "\t" << "BitXorInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::AddReal: + INSTR_DUMP << "\t" << "AddReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::AddString: + INSTR_DUMP << "\t" << "AddString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::SubReal: + INSTR_DUMP << "\t" << "SubReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::MulReal: + INSTR_DUMP << "\t" << "MulReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::DivReal: + INSTR_DUMP << "\t" << "DivReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::ModReal: + INSTR_DUMP << "\t" << "ModReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::LShiftInt: + INSTR_DUMP << "\t" << "LShiftInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::RShiftInt: + INSTR_DUMP << "\t" << "RShiftInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::URShiftInt: + INSTR_DUMP << "\t" << "URShiftInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::GtReal: + INSTR_DUMP << "\t" << "GtReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::LtReal: + INSTR_DUMP << "\t" << "LtReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::GeReal: + INSTR_DUMP << "\t" << "GeReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::LeReal: + INSTR_DUMP << "\t" << "LeReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::EqualReal: + INSTR_DUMP << "\t" << "EqualReal" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::NotEqualReal: + INSTR_DUMP << "\t" << "NotEqualReal" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::StrictEqualReal: + INSTR_DUMP << "\t" << "StrictEqualReal" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::StrictNotEqualReal: + INSTR_DUMP << "\t" << "StrictNotEqualReal" << "\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::GtString: + INSTR_DUMP << "\t" << "GtString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::LtString: + INSTR_DUMP << "\t" << "LtString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::GeString: + INSTR_DUMP << "\t" << "GeString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::LeString: + INSTR_DUMP << "\t" << "LeString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::EqualString: + INSTR_DUMP << "\t" << "EqualString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::NotEqualString: + INSTR_DUMP << "\t" << "NotEqualString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::StrictEqualString: + INSTR_DUMP << "\t" << "StrictEqualString" << "\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::StrictNotEqualString: + INSTR_DUMP << "\t" << "StrictNotEqualString" << "\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")"; + break; + case Instr::NewString: + INSTR_DUMP << "\t" << "NewString" << "\t\t" << "Register(" << construct.reg << ")"; + break; + case Instr::NewUrl: + INSTR_DUMP << "\t" << "NewUrl" << "\t\t\t" << "Register(" << construct.reg << ")"; + break; + case Instr::CleanupRegister: + INSTR_DUMP << "\t" << "CleanupRegister" << "\t\t" << "Register(" << cleanup.reg << ")"; + break; + case Instr::Fetch: + INSTR_DUMP << "\t" << "Fetch" << "\t\t\t" << "Object_Reg(" << fetch.reg << ") Property_Index(" << fetch.index << ") -> Output_Reg(" << fetch.reg << ")"; + break; + case Instr::Store: + INSTR_DUMP << "\t" << "Store" << "\t\t\t" << "Input_Reg(" << store.reg << ") -> Object_Reg(" << store.output << ") Property_Index(" << store.index << ")"; + break; + case Instr::Copy: + INSTR_DUMP << "\t" << "Copy" << "\t\t\t" << "Input_Reg(" << copy.src << ") -> Output_Reg(" << copy.reg << ")"; + break; + case Instr::Jump: + if (jump.reg != -1) { + INSTR_DUMP << "\t" << "Jump" << "\t\t\t" << "Address(" << (address + size() + jump.count) << ") [if false == Input_Reg(" << jump.reg << ")]"; + } else { + INSTR_DUMP << "\t" << "Jump" << "\t\t\t" << "Address(" << (address + size() + jump.count) << ")"; + } + break; + case Instr::BranchFalse: + INSTR_DUMP << "\t" << "BranchFalse" << "\t\t" << "Address(" << (address + size() + branchop.offset) << ") [if false == Input_Reg(" << branchop.reg << ")]"; + break; + case Instr::BranchTrue: + INSTR_DUMP << "\t" << "BranchTrue" << "\t\t" << "Address(" << (address + size() + branchop.offset) << ") [if true == Input_Reg(" << branchop.reg << ")]"; + break; + case Instr::Branch: + INSTR_DUMP << "\t" << "Branch" << "\t\t\t" << "Address(" << (address + size() + branchop.offset) << ")"; + break; + case Instr::InitString: + INSTR_DUMP << "\t" << "InitString" << "\t\t" << "String_DataIndex(" << initstring.dataIdx << ") -> String_Slot(" << initstring.offset << ")"; + break; + case Instr::Block: + INSTR_DUMP << "\t" << "Block" << "\t\t\t" << "Mask(" << QByteArray::number(blockop.block, 16).constData() << ")"; + break; + default: + INSTR_DUMP << "\t" << "Unknown"; + break; + } +} + +void Instr::noop() +{ + common.type = Noop; +} + +void Instr::load_root(quint8 reg) +{ + common.type = LoadRoot; + load.reg = reg; + load.index = 0; +} + +void Instr::load_scope(quint8 reg) +{ + common.type = LoadScope; + load.reg = reg; + load.index = 0; +} + +void Instr::load_id(quint8 reg, quint32 idIndex) +{ + common.type = LoadId; + load.reg = reg; + load.index = idIndex; +} + +void Instr::subscribe(qint8 reg, quint16 subscribeSlot, quint32 notifyIndex) +{ + common.type = Instr::Subscribe; + subscribeop.reg = reg; + subscribeop.offset = subscribeSlot; + subscribeop.index = notifyIndex; +} + +void Instr::subscribeId(qint8 reg, quint16 subscribeSlot, quint32 idIndex) +{ + common.type = Instr::SubscribeId; + subscribeop.reg = reg; + subscribeop.offset = subscribeSlot; + subscribeop.index = idIndex; +} + +void Instr::move_reg_bool(quint8 reg, bool value) +{ + common.type = Bool; + bool_value.reg = reg; + bool_value.value = value; +} + +void Instr::move_reg_int(quint8 reg, int value) +{ + common.type = Int; + int_value.reg = reg; + int_value.value = value; +} + +void Instr::move_reg_qreal(quint8 reg, qreal value) +{ + common.type = Real; + real_value.reg = reg; + real_value.value = value; +} + +void Instr::move_reg_reg(quint8 reg, quint8 src) +{ + common.type = Copy; + copy.reg = reg; + copy.src = src; +} + +void Instr::unary_not(quint8 dest, quint8 src) +{ + common.type = UnaryNot; + unaryop.src = src; + unaryop.output = dest; +} + +void Instr::uminus_real(quint8 dest, quint8 src) +{ + common.type = UnaryMinusReal; + unaryop.src = src; + unaryop.output = dest; +} + +void Instr::uminus_int(quint8 dest, quint8 src) +{ + common.type = UnaryMinusInt; + unaryop.src = src; + unaryop.output = dest; +} + +void Instr::uplus_real(quint8 dest, quint8 src) +{ + common.type = UnaryPlusReal; + unaryop.src = src; + unaryop.output = dest; +} + +void Instr::uplus_int(quint8 dest, quint8 src) +{ + common.type = UnaryPlusInt; + unaryop.src = src; + unaryop.output = dest; +} + +void Instr::ucompl_real(quint8 dest, quint8 src) +{ + Q_UNUSED(dest); + Q_UNUSED(src); + if (qmlVerboseCompiler()) + qWarning() << "TODO" << Q_FUNC_INFO; +} + +void Instr::ucompl_int(quint8 dest, quint8 src) +{ + Q_UNUSED(dest); + Q_UNUSED(src); + if (qmlVerboseCompiler()) + qWarning() << "TODO" << Q_FUNC_INFO; +} + +void Instr::math_sin_real(quint8 reg) +{ + common.type = MathSinReal; + unaryop.src = reg; + unaryop.output = reg; +} + +void Instr::math_cos_real(quint8 reg) +{ + common.type = MathCosReal; + unaryop.src = reg; + unaryop.output = reg; +} + +void Instr::math_round_real(quint8 reg) +{ + common.type = MathRoundReal; + unaryop.src = reg; + unaryop.output = reg; +} + +void Instr::math_floor_real(quint8 reg) +{ + common.type = MathFloorReal; + unaryop.src = reg; + unaryop.output = reg; +} + +void Instr::math_pi_real(quint8 reg) +{ + common.type = MathPIReal; + unaryop.src = reg; + unaryop.output = reg; +} + +void Instr::branch_true(quint8 reg, qint16 offset) +{ + common.type = BranchTrue; + branchop.reg = reg; + branchop.offset = offset; +} + +void Instr::branch_false(quint8 reg, qint16 offset) +{ + common.type = BranchFalse; + branchop.reg = reg; + branchop.offset = offset; +} + +void Instr::branch(qint16 offset) +{ + common.type = Branch; + branchop.offset = offset; +} + +void Instr::block(quint32 mask) +{ + common.type = Block; + blockop.block = mask; +} + +Bytecode::Bytecode() +{ +#ifdef QML_THREADED_INTERPRETER + decodeInstr = QDeclarativeV4Bindings::getDecodeInstrTable(); +#endif +} + +void Bytecode::append(const Instr &instr) +{ + const char *it; +#ifdef QML_THREADED_INTERPRETER + Instr i = instr; + i.common.code = decodeInstr[i.common.type]; + it = (const char *) &i; +#else + it = (const char *) &instr; +#endif + d.append(it, instr.size()); +} + +void Bytecode::append(const QVector &instrs) +{ + foreach (const Instr &i, instrs) + append(i); +} + +int Bytecode::remove(int offset) +{ + const Instr *instr = (const Instr *) (d.begin() + offset); + const int instrSize = instr->size(); + d.remove(offset, instrSize); + return instrSize; +} + +const Instr &Bytecode::operator[](int offset) const +{ + return *((const Instr *) (d.begin() + offset)); +} + +Instr &Bytecode::operator[](int offset) +{ + return *((Instr *) (d.begin() + offset)); +} + +} + +QT_END_NAMESPACE diff --git a/src/declarative/qml/v4/qdeclarativev4instruction_p.h b/src/declarative/qml/v4/qdeclarativev4instruction_p.h new file mode 100644 index 0000000000..f6e0bc734a --- /dev/null +++ b/src/declarative/qml/v4/qdeclarativev4instruction_p.h @@ -0,0 +1,444 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEV4INSTRUCTION_P_H +#define QDECLARATIVEV4INSTRUCTION_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 +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define FOR_EACH_QML_INSTR(F) \ + F(Noop, common) \ + F(BindingId, id) \ + F(Subscribe, subscribeop) \ + F(SubscribeId, subscribeop) \ + F(FetchAndSubscribe, fetchAndSubscribe) \ + F(LoadId, load) \ + F(LoadScope, load) \ + F(LoadRoot, load) \ + F(LoadAttached, attached) \ + F(UnaryNot, unaryop) \ + F(UnaryMinusReal, unaryop) \ + F(UnaryMinusInt, unaryop) \ + F(UnaryPlusReal, unaryop) \ + F(UnaryPlusInt, unaryop) \ + F(ConvertBoolToInt, unaryop) \ + F(ConvertBoolToReal, unaryop) \ + F(ConvertBoolToString, unaryop) \ + F(ConvertIntToBool, unaryop) \ + F(ConvertIntToReal, unaryop) \ + F(ConvertIntToString, unaryop) \ + F(ConvertRealToBool, unaryop) \ + F(ConvertRealToInt, unaryop) \ + F(ConvertRealToString, unaryop) \ + F(ConvertStringToBool, unaryop) \ + F(ConvertStringToInt, unaryop) \ + F(ConvertStringToReal, unaryop) \ + F(MathSinReal, unaryop) \ + F(MathCosReal, unaryop) \ + F(MathRoundReal, unaryop) \ + F(MathFloorReal, unaryop) \ + F(MathPIReal, unaryop) \ + F(Real, real_value) \ + F(Int, int_value) \ + F(Bool, bool_value) \ + F(String, string_value) \ + F(EnableV4Test, string_value) \ + F(TestV4Store, storetest) \ + F(BitAndInt, binaryop) \ + F(BitOrInt, binaryop) \ + F(BitXorInt, binaryop) \ + F(AddReal, binaryop) \ + F(AddString, binaryop) \ + F(SubReal, binaryop) \ + F(MulReal, binaryop) \ + F(DivReal, binaryop) \ + F(ModReal, binaryop) \ + F(LShiftInt, binaryop) \ + F(RShiftInt, binaryop) \ + F(URShiftInt, binaryop) \ + F(GtReal, binaryop) \ + F(LtReal, binaryop) \ + F(GeReal, binaryop) \ + F(LeReal, binaryop) \ + F(EqualReal, binaryop) \ + F(NotEqualReal, binaryop) \ + F(StrictEqualReal, binaryop) \ + F(StrictNotEqualReal, binaryop) \ + F(GtString, binaryop) \ + F(LtString, binaryop) \ + F(GeString, binaryop) \ + F(LeString, binaryop) \ + F(EqualString, binaryop) \ + F(NotEqualString, binaryop) \ + F(StrictEqualString, binaryop) \ + F(StrictNotEqualString, binaryop) \ + F(NewString, construct) \ + F(NewUrl, construct) \ + F(CleanupRegister, cleanup) \ + F(Copy, copy) \ + F(Fetch, fetch) \ + F(Store, store) \ + F(Jump, jump) \ + F(BranchTrue, branchop) \ + F(BranchFalse, branchop) \ + F(Branch, branchop) \ + F(Block, blockop) \ + /* Speculative property resolution */ \ + F(InitString, initstring) + +#if defined(Q_CC_GNU) && (!defined(Q_CC_INTEL) || __INTEL_COMPILER >= 1200) +# define QML_THREADED_INTERPRETER +#endif + +#ifdef Q_ALIGNOF +# define QML_INSTR_ALIGN_MASK (Q_ALIGNOF(Instr) - 1) +#else +# define QML_INSTR_ALIGN_MASK (sizeof(void *) - 1) +#endif + +#define QML_INSTR_ENUM(I, FMT) I, +#define QML_INSTR_ADDR(I, FMT) &&op_##I, +#define QML_INSTR_SIZE(I, FMT) ((sizeof(Instr::instr_##FMT) + QML_INSTR_ALIGN_MASK) & ~QML_INSTR_ALIGN_MASK) + +#ifdef QML_THREADED_INTERPRETER +# define QML_BEGIN_INSTR(I,FMT) op_##I: +# define QML_END_INSTR(I,FMT) code += QML_INSTR_SIZE(I, FMT); instr = (const Instr *) code; goto *instr->common.code; +# define QML_INSTR_HEADER void *code; +#else +# define QML_BEGIN_INSTR(I,FMT) case Instr::I: +# define QML_END_INSTR(I,FMT) code += QML_INSTR_SIZE(I, FMT); instr = (const Instr *) code; break; +# define QML_INSTR_HEADER +#endif + +namespace QDeclarativeJS { + +union Instr { + int size() const; + void dump(int = -1) const; + void noop(); + void load_root(quint8 reg); + void load_scope(quint8 reg); + void load_id(quint8 reg, quint32 idIndex); + void subscribe(qint8 reg, quint16 offset, quint32 index); + void subscribeId(qint8 reg, quint16 offset, quint32 index); + void move_reg_bool(quint8 reg, bool value); + void move_reg_int(quint8 reg, int value); + void move_reg_qreal(quint8 reg, qreal value); + void move_reg_reg(quint8 reg, quint8 src); + + void unary_not(quint8 dest, quint8 src); + void uminus_real(quint8 dest, quint8 src); + void uminus_int(quint8 dest, quint8 src); + void uplus_real(quint8 dest, quint8 src); + void uplus_int(quint8 dest, quint8 src); + void ucompl_real(quint8 dest, quint8 src); + void ucompl_int(quint8 dest, quint8 src); + + void math_sin_real(quint8 reg); + void math_cos_real(quint8 reg); + void math_round_real(quint8 reg); + void math_floor_real(quint8 reg); + void math_pi_real(quint8 reg); + void branch_true(quint8 reg, qint16 offset); + void branch_false(quint8 reg, qint16 offset); + void branch(qint16 offset); + void block(quint32 mask); + + enum { + FOR_EACH_QML_INSTR(QML_INSTR_ENUM) + }; + + struct instr_common { + QML_INSTR_HEADER + quint8 type; + }; + + struct instr_id { + QML_INSTR_HEADER + quint8 type; + quint16 column; + quint32 line; + }; + + struct instr_init { + QML_INSTR_HEADER + quint8 type; + quint16 subscriptions; + quint16 identifiers; + }; + + struct instr_subscribeop { + QML_INSTR_HEADER + quint8 type; + qint8 reg; + quint16 offset; + quint32 index; + }; + + struct instr_load { + QML_INSTR_HEADER + quint8 type; + qint8 reg; + quint32 index; + }; + + struct instr_attached { + QML_INSTR_HEADER + quint8 type; + qint8 output; + qint8 reg; + quint8 exceptionId; + quint32 id; + }; + + struct instr_store { + QML_INSTR_HEADER + quint8 type; + qint8 output; + qint8 reg; + quint8 exceptionId; + quint32 index; + }; + + struct instr_storetest { + QML_INSTR_HEADER + quint8 type; + qint8 reg; + qint32 regType; + }; + + struct instr_fetchAndSubscribe { + QML_INSTR_HEADER + quint8 type; + qint8 reg; + quint8 exceptionId; + quint8 valueType; + quint16 subscription; + quint16 function; + }; + + struct instr_fetch{ + QML_INSTR_HEADER + quint8 type; + qint8 reg; + quint8 exceptionId; + quint8 valueType; + quint32 index; + }; + + struct instr_copy { + QML_INSTR_HEADER + quint8 type; + qint8 reg; + qint8 src; + }; + + struct instr_construct { + QML_INSTR_HEADER + quint8 type; + qint8 reg; + }; + + struct instr_real_value { + QML_INSTR_HEADER + quint8 type; + qint8 reg; + qreal value; // XXX Makes the instruction 12 bytes + }; + + struct instr_int_value { + QML_INSTR_HEADER + quint8 type; + qint8 reg; + int value; + }; + + struct instr_bool_value { + QML_INSTR_HEADER + quint8 type; + qint8 reg; + bool value; + }; + + struct instr_string_value { + QML_INSTR_HEADER + quint8 type; + qint8 reg; + quint16 length; + quint32 offset; + }; + + struct instr_binaryop { + QML_INSTR_HEADER + quint8 type; + qint8 output; + qint8 left; + qint8 right; + }; + + struct instr_unaryop { + QML_INSTR_HEADER + quint8 type; + qint8 output; + qint8 src; + }; + + struct instr_jump { + QML_INSTR_HEADER + quint8 type; + qint8 reg; + quint32 count; + }; + + struct instr_find { + QML_INSTR_HEADER + quint8 type; + qint8 reg; + qint8 src; + quint8 exceptionId; + quint16 name; + quint16 subscribeIndex; + }; + + struct instr_cleanup { + QML_INSTR_HEADER + quint8 type; + qint8 reg; + }; + + struct instr_initstring { + QML_INSTR_HEADER + quint8 type; + quint16 offset; + quint32 dataIdx; + }; + + struct instr_branchop { + QML_INSTR_HEADER + quint8 type; + quint8 reg; + qint16 offset; + }; + + struct instr_blockop { + QML_INSTR_HEADER + quint8 type; + quint32 block; + }; + + instr_common common; + instr_id id; + instr_init init; + instr_subscribeop subscribeop; + instr_load load; + instr_attached attached; + instr_store store; + instr_storetest storetest; + instr_fetchAndSubscribe fetchAndSubscribe; + instr_fetch fetch; + instr_copy copy; + instr_construct construct; + instr_real_value real_value; + instr_int_value int_value; + instr_bool_value bool_value; + instr_string_value string_value; + instr_binaryop binaryop; + instr_unaryop unaryop; + instr_jump jump; + instr_find find; + instr_cleanup cleanup; + instr_initstring initstring; + instr_branchop branchop; + instr_blockop blockop; +}; + +class Bytecode +{ + Q_DISABLE_COPY(Bytecode) + +public: + Bytecode(); + + QByteArray code() const { return d; } + const char *constData() const { return d.constData(); } + int size() const { return d.size(); } + int count() const { return d.count(); } + void clear() { d.clear(); } + bool isEmpty() const { return d.isEmpty(); } + void append(const Instr &instr); + void append(const QVector &instrs); + int remove(int index); + + const Instr &operator[](int offset) const; + Instr &operator[](int offset); + +private: + QByteArray d; +#ifdef QML_THREADED_INTERPRETER + void **decodeInstr; +#endif +}; + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEV4INSTRUCTION_P_H + diff --git a/src/declarative/qml/v4/qdeclarativev4ir.cpp b/src/declarative/qml/v4/qdeclarativev4ir.cpp new file mode 100644 index 0000000000..7876e6ccea --- /dev/null +++ b/src/declarative/qml/v4/qdeclarativev4ir.cpp @@ -0,0 +1,832 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativev4ir_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QDeclarativeJS { +namespace IR { + +inline const char *typeName(Type t) +{ + switch (t) { + case InvalidType: return "invalid"; + case UndefinedType: return "undefined"; + case NullType: return "null"; + case VoidType: return "void"; + case StringType: return "string"; + case UrlType: return "url"; + case AnchorLineType: return "AnchorLine"; + case SGAnchorLineType: return "SGAnchorLine"; + case AttachType: return "AttachType"; + case ObjectType: return "object"; + case BoolType: return "bool"; + case IntType: return "int"; + case RealType: return "qreal"; + case RealNaNType: return "NaN"; + default: return "invalid"; + } +} + +IR::Type maxType(IR::Type left, IR::Type right) +{ + if (left == right) + return left; + else if (left >= IR::FirstNumberType && right >= IR::FirstNumberType) + return qMax(left, right); + else if ((left >= IR::FirstNumberType && right == IR::StringType) || + (right >= IR::FirstNumberType && left == IR::StringType)) + return IR::StringType; + else + return IR::InvalidType; +} + + +const char *opname(AluOp op) +{ + switch (op) { + case OpInvalid: return "?"; + + case OpIfTrue: return "(bool)"; + case OpNot: return "!"; + case OpUMinus: return "-"; + case OpUPlus: return "+"; + case OpCompl: return "~"; + + case OpBitAnd: return "&"; + case OpBitOr: return "|"; + case OpBitXor: return "^"; + + case OpAdd: return "+"; + case OpSub: return "-"; + case OpMul: return "*"; + case OpDiv: return "/"; + case OpMod: return "%"; + + case OpLShift: return "<<"; + case OpRShift: return ">>"; + case OpURShift: return ">>>"; + + case OpGt: return ">"; + case OpLt: return "<"; + case OpGe: return ">="; + case OpLe: return "<="; + case OpEqual: return "=="; + case OpNotEqual: return "!="; + case OpStrictEqual: return "==="; + case OpStrictNotEqual: return "!=="; + + case OpAnd: return "&&"; + case OpOr: return "||"; + + default: return "?"; + + } // switch +} + +AluOp binaryOperator(int op) +{ + switch (static_cast(op)) { + case QSOperator::Add: return OpAdd; + case QSOperator::And: return OpAnd; + case QSOperator::BitAnd: return OpBitAnd; + case QSOperator::BitOr: return OpBitOr; + case QSOperator::BitXor: return OpBitXor; + case QSOperator::Div: return OpDiv; + case QSOperator::Equal: return OpEqual; + case QSOperator::Ge: return OpGe; + case QSOperator::Gt: return OpGt; + case QSOperator::Le: return OpLe; + case QSOperator::LShift: return OpLShift; + case QSOperator::Lt: return OpLt; + case QSOperator::Mod: return OpMod; + case QSOperator::Mul: return OpMul; + case QSOperator::NotEqual: return OpNotEqual; + case QSOperator::Or: return OpOr; + case QSOperator::RShift: return OpRShift; + case QSOperator::StrictEqual: return OpStrictEqual; + case QSOperator::StrictNotEqual: return OpStrictNotEqual; + case QSOperator::Sub: return OpSub; + case QSOperator::URShift: return OpURShift; + default: return OpInvalid; + } +} + +void Const::dump(QTextStream &out) +{ + out << value; +} + +void String::dump(QTextStream &out) +{ + out << '"' << escape(value) << '"'; +} + +QString String::escape(const QString &s) +{ + QString r; + foreach (const QChar &ch, s) { + if (ch == QLatin1Char('\n')) + r += QLatin1String("\\n"); + else if (ch == QLatin1Char('\r')) + r += QLatin1String("\\r"); + else if (ch == QLatin1Char('\\')) + r += QLatin1String("\\\\"); + else if (ch == QLatin1Char('"')) + r += QLatin1String("\\\""); + else if (ch == QLatin1Char('\'')) + r += QLatin1String("\\'"); + else + r += ch; + } + return r; +} + +Name::Name(Name *base, Type type, const QString &id, Symbol symbol, quint32 line, quint32 column) +: Expr(type) + , base(base) + , id(id) + , symbol(symbol) + , ptr(0) + , index(-1) + , storage(MemberStorage) + , builtin(NoBuiltinSymbol) + , line(line) + , column(column) +{ + if (id.length() == 8 && id == QLatin1String("Math.sin")) { + builtin = MathSinBultinFunction; + } else if (id.length() == 8 && id == QLatin1String("Math.cos")) { + builtin = MathCosBultinFunction; + } else if (id.length() == 10 && id == QLatin1String("Math.round")) { + builtin = MathRoundBultinFunction; + } else if (id.length() == 10 && id == QLatin1String("Math.floor)")) { + builtin = MathFloorBultinFunction; + } else if (id.length() == 7 && id == QLatin1String("Math.PI")) { + builtin = MathPIBuiltinConstant; + type = RealType; + } +} + +void Name::dump(QTextStream &out) +{ + if (base) { + base->dump(out); + out << '.'; + } + + out << id; +} + +void Temp::dump(QTextStream &out) +{ + out << 't' << index; +} + +void Unop::dump(QTextStream &out) +{ + out << opname(op); + expr->dump(out); +} + +Type Unop::typeForOp(AluOp op, Expr *expr) +{ + switch (op) { + case OpIfTrue: return BoolType; + case OpNot: return BoolType; + + case OpUMinus: + case OpUPlus: + case OpCompl: + return maxType(expr->type, RealType); + + default: + break; + } + + return InvalidType; +} + +void Binop::dump(QTextStream &out) +{ + left->dump(out); + out << ' ' << opname(op) << ' '; + right->dump(out); +} + +Type Binop::typeForOp(AluOp op, Expr *left, Expr *right) +{ + if (! (left && right)) + return InvalidType; + + switch (op) { + case OpInvalid: + return InvalidType; + + // unary operators + case OpIfTrue: + case OpNot: + case OpUMinus: + case OpUPlus: + case OpCompl: + return InvalidType; + + // bit fields + case OpBitAnd: + case OpBitOr: + case OpBitXor: + return IntType; + + case OpAdd: + if (left->type == StringType) + return StringType; + return RealType; + + case OpSub: + case OpMul: + case OpDiv: + case OpMod: + return RealType; + + case OpLShift: + case OpRShift: + case OpURShift: + return IntType; + + case OpAnd: + case OpOr: + return BoolType; + + case OpGt: + case OpLt: + case OpGe: + case OpLe: + case OpEqual: + case OpNotEqual: + case OpStrictEqual: + case OpStrictNotEqual: + return BoolType; + } // switch + + return InvalidType; +} + +void Call::dump(QTextStream &out) +{ + base->dump(out); + out << '('; + for (int i = 0; i < args.size(); ++i) { + if (i) + out << ", "; + args.at(i)->dump(out); + } + out << ')'; +} + +Type Call::typeForFunction(Expr *base) +{ + if (! base) + return InvalidType; + + if (Name *name = base->asName()) { + switch (name->builtin) { + case MathSinBultinFunction: + case MathCosBultinFunction: + return RealType; + + case MathRoundBultinFunction: + case MathFloorBultinFunction: + return IntType; + + case NoBuiltinSymbol: + case MathPIBuiltinConstant: + break; + } + } // switch + + return InvalidType; +} + +void Exp::dump(QTextStream &out, Mode) +{ + out << "(void) "; + expr->dump(out); + out << ';'; +} + +void Move::dump(QTextStream &out, Mode) +{ + target->dump(out); + out << " = "; + if (source->type != target->type) + out << typeName(source->type) << "_to_" << typeName(target->type) << '('; + source->dump(out); + if (source->type != target->type) + out << ')'; + out << ';'; +} + +void Jump::dump(QTextStream &out, Mode mode) +{ + Q_UNUSED(mode); + out << "goto " << 'L' << target << ';'; +} + +void CJump::dump(QTextStream &out, Mode mode) +{ + Q_UNUSED(mode); + out << "if ("; + cond->dump(out); + out << ") goto " << 'L' << iftrue << "; else goto " << 'L' << iffalse << ';'; +} + +void Ret::dump(QTextStream &out, Mode) +{ + out << "return"; + if (expr) { + out << ' '; + expr->dump(out); + } + out << ';'; +} + +Function::~Function() +{ + qDeleteAll(basicBlocks); + qDeleteAll(temps); +} + +BasicBlock *Function::newBasicBlock() +{ + const int index = basicBlocks.size(); + return i(new BasicBlock(this, index)); +} + +void Function::dump(QTextStream &out) +{ + QString fname; + if (name) + fname = name->asString(); + else + fname = QLatin1String("$anonymous"); + out << "function " << fname << "() {" << endl; + foreach (BasicBlock *bb, basicBlocks) { + bb->dump(out); + } + out << '}' << endl; +} + +Temp *BasicBlock::TEMP(Type type, int index) +{ + return function->e(new Temp(type, index)); +} + +Temp *BasicBlock::TEMP(Type type) +{ + return TEMP(type, function->tempCount++); +} + +Expr *BasicBlock::CONST(double value) +{ + return CONST(IR::RealType, value); +} + +Expr *BasicBlock::CONST(Type type, double value) +{ + return function->e(new Const(type, value)); +} + +Expr *BasicBlock::STRING(const QString &value) +{ + return function->e(new String(value)); +} + +Name *BasicBlock::NAME(const QString &id, quint32 line, quint32 column) +{ + return NAME(0, id, line, column); +} + +Name *BasicBlock::NAME(Name *base, const QString &id, quint32 line, quint32 column) +{ + return function->e(new Name(base, InvalidType, id, Name::Unbound, line, column)); +} + +Name *BasicBlock::SYMBOL(Type type, const QString &id, const QMetaObject *meta, int index, Name::Storage storage, + quint32 line, quint32 column) +{ + Name *name = SYMBOL(/*base = */ 0, type, id, meta, index, line, column); + name->storage = storage; + return name; +} + +Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, int index, Name::Storage storage, + quint32 line, quint32 column) +{ + Name *name = new Name(base, type, id, Name::Property, line, column); + name->meta = meta; + name->index = index; + name->storage = storage; + return function->e(name); +} + +Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, int index, + quint32 line, quint32 column) +{ + Name *name = new Name(base, type, id, Name::Property, line, column); + name->meta = meta; + name->index = index; + return function->e(name); +} + +Name *BasicBlock::ID_OBJECT(const QString &id, const QDeclarativeParser::Object *object, quint32 line, quint32 column) +{ + Name *name = new Name(/*base = */ 0, IR::ObjectType, id, Name::IdObject, line, column); + name->idObject = object; + name->index = object->idIndex; + name->storage = Name::IdStorage; + return function->e(name); +} + +Name *BasicBlock::ATTACH_TYPE(const QString &id, const QDeclarativeType *attachType, Name::Storage storage, + quint32 line, quint32 column) +{ + Name *name = new Name(/*base = */ 0, IR::AttachType, id, Name::AttachType, line, column); + name->declarativeType = attachType; + name->storage = storage; + return function->e(name); +} + + +Expr *BasicBlock::UNOP(AluOp op, Expr *expr) +{ + return function->e(new Unop(op, expr)); +} + +Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right) +{ + if (left && right) { + if (Const *c1 = left->asConst()) { + if (Const *c2 = right->asConst()) { + switch (op) { + case OpAdd: return CONST(c1->value + c2->value); + case OpAnd: return CONST(c1->value ? c2->value : 0); + case OpBitAnd: return CONST(int(c1->value) & int(c2->value)); + case OpBitOr: return CONST(int(c1->value) | int(c2->value)); + case OpBitXor: return CONST(int(c1->value) ^ int(c2->value)); + case OpDiv: return CONST(c1->value / c2->value); + case OpEqual: return CONST(c1->value == c2->value); + case OpGe: return CONST(c1->value >= c2->value); + case OpGt: return CONST(c1->value > c2->value); + case OpLe: return CONST(c1->value <= c2->value); + case OpLShift: return CONST(int(c1->value) << int(c2->value)); + case OpLt: return CONST(c1->value < c2->value); + case OpMod: return CONST(::fmod(c1->value, c2->value)); + case OpMul: return CONST(c1->value * c2->value); + case OpNotEqual: return CONST(c1->value != c2->value); + case OpOr: return CONST(c1->value ? c1->value : c2->value); + case OpRShift: return CONST(int(c1->value) >> int(c2->value)); + case OpStrictEqual: return CONST(c1->value == c2->value); + case OpStrictNotEqual: return CONST(c1->value != c2->value); + case OpSub: return CONST(c1->value - c2->value); + case OpURShift: return CONST(unsigned(c1->value) >> int(c2->value)); + + case OpIfTrue: // unary ops + case OpNot: + case OpUMinus: + case OpUPlus: + case OpCompl: + case OpInvalid: + break; + } + } + } + } + + return function->e(new Binop(op, left, right)); +} + +Expr *BasicBlock::CALL(Expr *base, const QVector &args) +{ + return function->e(new Call(base, args)); +} + +Stmt *BasicBlock::EXP(Expr *expr) +{ + return i(new Exp(expr)); +} + +Stmt *BasicBlock::MOVE(Expr *target, Expr *source, bool isMoveForReturn) +{ + return i(new Move(target, source, isMoveForReturn)); +} + +Stmt *BasicBlock::JUMP(BasicBlock *target) +{ + if (isTerminated()) + return 0; + else + return i(new Jump(target)); +} + +Stmt *BasicBlock::CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse) +{ + if (isTerminated()) + return 0; + return i(new CJump(cond, iftrue, iffalse)); +} + +Stmt *BasicBlock::RET(Expr *expr, Type type, quint32 line, quint32 column) +{ + if (isTerminated()) + return 0; + else + return i(new Ret(expr, type, line, column)); +} + +void BasicBlock::dump(QTextStream &out) +{ + out << 'L' << this << ':' << endl; + foreach (Stmt *s, statements) { + out << '\t'; + s->dump(out); + out << endl; + } +} + +void Module::dump(QTextStream &out) +{ + foreach (Function *fun, functions) { + fun->dump(out); + out << endl; + } +} + +#ifdef DEBUG_IR_STRUCTURE + +static const char *symbolname(Name::Symbol s) +{ + switch (s) { + case Name::Unbound: + return "Unbound"; + case Name::IdObject: + return "IdObject"; + case Name::AttachType: + return "AttachType"; + case Name::Object: + return "Object"; + case Name::Property: + return "Property"; + case Name::Slot: + return "Slot"; + default: + Q_ASSERT(!"Unreachable"); + return "Unknown"; + } +} + +static const char *storagename(Name::Storage s) +{ + switch (s) { + case Name::MemberStorage: + return "MemberStorage"; + case Name::IdStorage: + return "IdStorage"; + case Name::RootStorage: + return "RootStorage"; + case Name::ScopeStorage: + return "ScopeStorage"; + default: + Q_ASSERT(!"Unreachable"); + return "UnknownStorage"; + } +} + +IRDump::IRDump() +: indentSize(0) +{ +} + +void IRDump::inc() +{ + indentSize++; + indentData = QByteArray(indentSize * 4, ' '); +} + +void IRDump::dec() +{ + indentSize--; + indentData = QByteArray(indentSize * 4, ' '); +} + +void IRDump::dec(); + +void IRDump::expression(QDeclarativeJS::IR::Expr *e) +{ + inc(); + + e->accept(this); + + dec(); +} + +void IRDump::basicblock(QDeclarativeJS::IR::BasicBlock *b) +{ + inc(); + + qWarning().nospace() << indent() << "BasicBlock " << b << " {"; + for (int ii = 0; ii < b->statements.count(); ++ii) { + statement(b->statements.at(ii)); + if (ii != (b->statements.count() - 1)) + qWarning(); + } + qWarning().nospace() << indent() << "}"; + + dec(); +} + +void IRDump::statement(QDeclarativeJS::IR::Stmt *s) +{ + inc(); + + s->accept(this); + + dec(); +} + +void IRDump::function(QDeclarativeJS::IR::Function *f) +{ + inc(); + + qWarning().nospace() << indent() << "Function {"; + for (int ii = 0; ii < f->basicBlocks.count(); ++ii) { + basicblock(f->basicBlocks.at(ii)); + } + qWarning().nospace() << indent() << "}"; + + dec(); +} + +const char *IRDump::indent() +{ + return indentData.constData(); +} + +void IRDump::visitConst(QDeclarativeJS::IR::Const *e) +{ + qWarning().nospace() << indent() << "Const:Expr { type: " << typeName(e->type) << ", value: " << e->value << "}"; +} + +void IRDump::visitString(QDeclarativeJS::IR::String *e) +{ + qWarning().nospace() << indent() << "String:Expr { type: " << typeName(e->type) << ", value: " << e->value << "}"; +} + +static void namedumprecur(QDeclarativeJS::IR::Name *e, const char *indent) +{ + if (e->base) namedumprecur(e->base, indent); + qWarning().nospace() << indent << " { type: " << typeName(e->type) << ", symbol: " << symbolname(e->symbol) << ", storage: " << storagename(e->storage) << ", id: " << e->id << "}"; +} + +void IRDump::visitName(QDeclarativeJS::IR::Name *e) +{ + qWarning().nospace() << indent() << "Name:Expr {"; + namedumprecur(e, indent()); + qWarning().nospace() << indent() << "}"; +} + +void IRDump::visitTemp(QDeclarativeJS::IR::Temp *e) +{ + qWarning().nospace() << indent() << "Temp:Expr { type: " << typeName(e->type) << ", index: " << e->index << " }"; +} + +void IRDump::visitUnop(QDeclarativeJS::IR::Unop *e) +{ + qWarning().nospace() << indent() << "Unop:Expr { "; + qWarning().nospace() << indent() << " type: " << typeName(e->type) << ", op: " << opname(e->op); + qWarning().nospace() << indent() << " expr: {"; + expression(e->expr); + qWarning().nospace() << indent() << " }"; + qWarning().nospace() << indent() << "}"; +} + +void IRDump::visitBinop(QDeclarativeJS::IR::Binop *e) +{ + qWarning().nospace() << indent() << "Binop:Expr { "; + qWarning().nospace() << indent() << " type: " << typeName(e->type) << ", op: " << opname(e->op); + qWarning().nospace() << indent() << " left: {"; + inc(); + expression(e->left); + dec(); + qWarning().nospace() << indent() << " },"; + qWarning().nospace() << indent() << " right: {"; + inc(); + expression(e->right); + dec(); + qWarning().nospace() << indent() << " }"; + qWarning().nospace() << indent() << "}"; +} + +void IRDump::visitCall(QDeclarativeJS::IR::Call *e) +{ + Q_UNUSED(e); + qWarning().nospace() << indent() << "Exp::Call { }"; +} + +void IRDump::visitExp(QDeclarativeJS::IR::Exp *s) +{ + qWarning().nospace() << indent() << "Exp:Stmt {"; + expression(s->expr); + qWarning().nospace() << indent() << "}"; +} + +void IRDump::visitMove(QDeclarativeJS::IR::Move *s) +{ + qWarning().nospace() << indent() << "Move:Stmt {"; + qWarning().nospace() << indent() << " isMoveForReturn: " << s->isMoveForReturn; + qWarning().nospace() << indent() << " target: {"; + inc(); + expression(s->target); + dec(); + qWarning().nospace() << indent() << " },"; + qWarning().nospace() << indent() << " source: {"; + inc(); + expression(s->source); + dec(); + qWarning().nospace() << indent() << " }"; + qWarning().nospace() << indent() << "}"; +} + +void IRDump::visitJump(QDeclarativeJS::IR::Jump *s) +{ + qWarning().nospace() << indent() << "Jump:Stmt { BasicBlock(" << s->target << ") }"; +} + +void IRDump::visitCJump(QDeclarativeJS::IR::CJump *s) +{ + qWarning().nospace() << indent() << "CJump:Stmt {"; + qWarning().nospace() << indent() << " cond: {"; + inc(); + expression(s->cond); + dec(); + qWarning().nospace() << indent() << " }"; + qWarning().nospace() << indent() << " iftrue: BasicBlock(" << s->iftrue << ")"; + qWarning().nospace() << indent() << " iffalse: BasicBlock(" << s->iffalse << ")"; + qWarning().nospace() << indent() << "}"; +} + +void IRDump::visitRet(QDeclarativeJS::IR::Ret *s) +{ + qWarning().nospace() << indent() << "Ret:Stmt {"; + qWarning().nospace() << indent() << " type: " << typeName(s->type); + expression(s->expr); + qWarning().nospace() << indent() << "}"; +} +#endif + +} // end of namespace IR +} // end of namespace QDeclarativeJS + +QT_END_NAMESPACE diff --git a/src/declarative/qml/v4/qdeclarativev4ir_p.h b/src/declarative/qml/v4/qdeclarativev4ir_p.h new file mode 100644 index 0000000000..93815e9154 --- /dev/null +++ b/src/declarative/qml/v4/qdeclarativev4ir_p.h @@ -0,0 +1,546 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEV4IR_P_H +#define QDECLARATIVEV4IR_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 +#include +#include +#include +#include +#include + +#include + +// #define DEBUG_IR_STRUCTURE + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QTextStream; +class QDeclarativeType; + +namespace QDeclarativeJS { + +namespace IR { + +struct BasicBlock; +struct Function; +struct Module; + +struct Stmt; +struct Expr; + +// expressions +struct Const; +struct String; +struct Name; +struct Temp; +struct Unop; +struct Binop; +struct Call; + +// statements +struct Exp; +struct Move; +struct Jump; +struct CJump; +struct Ret; + +enum AluOp { + OpInvalid = 0, + + OpIfTrue, + OpNot, + OpUMinus, + OpUPlus, + OpCompl, + + OpBitAnd, + OpBitOr, + OpBitXor, + + OpAdd, + OpSub, + OpMul, + OpDiv, + OpMod, + + OpLShift, + OpRShift, + OpURShift, + + OpGt, + OpLt, + OpGe, + OpLe, + OpEqual, + OpNotEqual, + OpStrictEqual, + OpStrictNotEqual, + + OpAnd, + OpOr +}; +AluOp binaryOperator(int op); + +enum Type { + InvalidType, + UndefinedType, + NullType, + VoidType, + StringType, + UrlType, + AnchorLineType, + SGAnchorLineType, + AttachType, + ObjectType, + + FirstNumberType, + BoolType = FirstNumberType, + IntType, + RealType, + RealNaNType +}; +Type maxType(IR::Type left, IR::Type right); + +struct ExprVisitor { + virtual ~ExprVisitor() {} + virtual void visitConst(Const *) {} + virtual void visitString(String *) {} + virtual void visitName(Name *) {} + virtual void visitTemp(Temp *) {} + virtual void visitUnop(Unop *) {} + virtual void visitBinop(Binop *) {} + virtual void visitCall(Call *) {} +}; + +struct StmtVisitor { + virtual ~StmtVisitor() {} + virtual void visitExp(Exp *) {} + virtual void visitMove(Move *) {} + virtual void visitJump(Jump *) {} + virtual void visitCJump(CJump *) {} + virtual void visitRet(Ret *) {} +}; + +struct Expr { + Type type; + + Expr(Type type): type(type) {} + virtual ~Expr() {} + virtual void accept(ExprVisitor *) = 0; + virtual Const *asConst() { return 0; } + virtual String *asString() { return 0; } + virtual Name *asName() { return 0; } + virtual Temp *asTemp() { return 0; } + virtual Unop *asUnop() { return 0; } + virtual Binop *asBinop() { return 0; } + virtual Call *asCall() { return 0; } + virtual void dump(QTextStream &out) = 0; +}; + +struct Const: Expr { + double value; + Const(Type type, double value): Expr(type), value(value) {} + + virtual void accept(ExprVisitor *v) { v->visitConst(this); } + virtual Const *asConst() { return this; } + + virtual void dump(QTextStream &out); +}; + +struct String: Expr { + QString value; + String(const QString &value): Expr(StringType), value(value) {} + + virtual void accept(ExprVisitor *v) { v->visitString(this); } + virtual String *asString() { return this; } + + virtual void dump(QTextStream &out); + static QString escape(const QString &s); +}; + +enum BuiltinSymbol { + NoBuiltinSymbol, + MathSinBultinFunction, + MathCosBultinFunction, + MathRoundBultinFunction, + MathFloorBultinFunction, + + MathPIBuiltinConstant +}; + +struct Name: Expr { + enum Symbol { + Unbound, + IdObject, // This is a load of a id object. Storage will always be IdStorage + AttachType, // This is a load of an attached object + Object, // XXX what is this for? + Property, // This is a load of a regular property + Slot // XXX what is this for? + }; + + enum Storage { + MemberStorage, // This is a property of a previously fetched object + IdStorage, // This is a load of a id object. Symbol will always be IdObject + RootStorage, // This is a property of the root object + ScopeStorage // This is a property of the scope object + }; + + Name *base; + QString id; + Symbol symbol; + union { + void *ptr; + const QMetaObject *meta; + const QDeclarativeType *declarativeType; + const QDeclarativeParser::Object *idObject; + }; + int index; + Storage storage; + BuiltinSymbol builtin; + quint32 line; + quint32 column; + + Name(Name *base, Type type, const QString &id, Symbol symbol, quint32 line, quint32 column); + + inline bool is(Symbol s) const { return s == symbol; } + inline bool isNot(Symbol s) const { return s != symbol; } + + virtual void accept(ExprVisitor *v) { v->visitName(this); } + virtual Name *asName() { return this; } + + virtual void dump(QTextStream &out); +}; + +struct Temp: Expr { + int index; + Temp(Type type, int index): Expr(type), index(index) {} + + virtual void accept(ExprVisitor *v) { v->visitTemp(this); } + virtual Temp *asTemp() { return this; } + + virtual void dump(QTextStream &out); +}; + +struct Unop: Expr { + AluOp op; + Expr *expr; + + Unop(AluOp op, Expr *expr) + : Expr(typeForOp(op, expr)), op(op), expr(expr) {} + + virtual void accept(ExprVisitor *v) { v->visitUnop(this); } + virtual Unop *asUnop() { return this; } + + virtual void dump(QTextStream &out); + +private: + static Type typeForOp(AluOp op, Expr *expr); +}; + +struct Binop: Expr { + AluOp op; + Expr *left; + Expr *right; + Binop(AluOp op, Expr *left, Expr *right) + : Expr(typeForOp(op, left, right)), op(op), left(left), right(right) {} + + virtual void accept(ExprVisitor *v) { v->visitBinop(this); } + virtual Binop *asBinop() { return this; } + + virtual void dump(QTextStream &out); + +private: + static Type typeForOp(AluOp op, Expr *left, Expr *right); +}; + +struct Call: Expr { + Expr *base; + QVector args; + + Call(Expr *base, const QVector &args) + : Expr(typeForFunction(base)), base(base), args(args) {} + + virtual void accept(ExprVisitor *v) { v->visitCall(this); } + virtual Call *asCall() { return this; } + + virtual void dump(QTextStream &out); + +private: + static Type typeForFunction(Expr *base); +}; + +struct Stmt { + enum Mode { + HIR, + MIR + }; + + virtual ~Stmt() {} + virtual Stmt *asTerminator() { return 0; } + + virtual void accept(StmtVisitor *) = 0; + virtual Exp *asExp() { return 0; } + virtual Move *asMove() { return 0; } + virtual Jump *asJump() { return 0; } + virtual CJump *asCJump() { return 0; } + virtual Ret *asRet() { return 0; } + virtual void dump(QTextStream &out, Mode mode = HIR) = 0; +}; + +struct Exp: Stmt { + Expr *expr; + Exp(Expr *expr): expr(expr) {} + + virtual void accept(StmtVisitor *v) { v->visitExp(this); } + virtual Exp *asExp() { return this; } + + virtual void dump(QTextStream &out, Mode); +}; + +struct Move: Stmt { + Expr *target; + Expr *source; + bool isMoveForReturn; + Move(Expr *target, Expr *source, bool isMoveForReturn): target(target), source(source), isMoveForReturn(isMoveForReturn) {} + + virtual void accept(StmtVisitor *v) { v->visitMove(this); } + virtual Move *asMove() { return this; } + + virtual void dump(QTextStream &out, Mode); +}; + +struct Jump: Stmt { + BasicBlock *target; + Jump(BasicBlock *target): target(target) {} + + virtual Stmt *asTerminator() { return this; } + + virtual void accept(StmtVisitor *v) { v->visitJump(this); } + virtual Jump *asJump() { return this; } + + virtual void dump(QTextStream &out, Mode mode); +}; + +struct CJump: Stmt { + Expr *cond; + BasicBlock *iftrue; + BasicBlock *iffalse; + CJump(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse) + : cond(cond), iftrue(iftrue), iffalse(iffalse) {} + + virtual Stmt *asTerminator() { return this; } + + virtual void accept(StmtVisitor *v) { v->visitCJump(this); } + virtual CJump *asCJump() { return this; } + + virtual void dump(QTextStream &out, Mode mode); +}; + +struct Ret: Stmt { + Expr *expr; + Type type; + quint32 line; + quint32 column; + Ret(Expr *expr, Type type, quint32 line, quint32 column): expr(expr), type(type), line(line), column(column) {} + + virtual Stmt *asTerminator() { return this; } + + virtual void accept(StmtVisitor *v) { v->visitRet(this); } + virtual Ret *asRet() { return this; } + + virtual void dump(QTextStream &out, Mode); +}; + +struct Function { + Module *module; + const NameId *name; + int tempCount; + QVector basicBlocks; + QVector temps; + + template inline BB i(BB i) { basicBlocks.append(i); return i; } + template inline E e(E e) { temps.append(e); return e; } + + Function(Module *module, const NameId *name = 0): module(module), name(name), tempCount(0) {} + ~Function(); + + BasicBlock *newBasicBlock(); + + virtual void dump(QTextStream &out); +}; + +struct BasicBlock { + Function *function; + int index; + QVector statements; + int offset; + + BasicBlock(Function *function, int index): function(function), index(index), offset(-1) {} + ~BasicBlock() { qDeleteAll(statements); } + + template inline Instr i(Instr i) { statements.append(i); return i; } + + inline bool isEmpty() const { + return statements.isEmpty(); + } + + inline Stmt *terminator() const { + if (! statements.isEmpty() && statements.last()->asTerminator() != 0) + return statements.last(); + return 0; + } + + inline bool isTerminated() const { + if (terminator() != 0) + return true; + return false; + } + + Temp *TEMP(Type type, int index); + Temp *TEMP(Type type); + + Expr *CONST(double value); + Expr *CONST(Type type, double value); + Expr *STRING(const QString &value); + + Name *NAME(const QString &id, quint32 line, quint32 column); + Name *NAME(Name *base, const QString &id, quint32 line, quint32 column); + Name *SYMBOL(Type type, const QString &id, const QMetaObject *meta, int index, Name::Storage storage, quint32 line, quint32 column); + Name *SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, int index, quint32 line, quint32 column); + Name *SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, int index, Name::Storage storage, quint32 line, quint32 column); + Name *ID_OBJECT(const QString &id, const QDeclarativeParser::Object *object, quint32 line, quint32 column); + Name *ATTACH_TYPE(const QString &id, const QDeclarativeType *attachType, Name::Storage storage, quint32 line, quint32 column); + + Expr *UNOP(AluOp op, Expr *expr); + Expr *BINOP(AluOp op, Expr *left, Expr *right); + Expr *CALL(Expr *base, const QVector &args); + + Stmt *EXP(Expr *expr); + Stmt *MOVE(Expr *target, Expr *source, bool = false); + + Stmt *JUMP(BasicBlock *target); + Stmt *CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse); + Stmt *RET(Expr *expr, Type type, quint32 line, quint32 column); + + virtual void dump(QTextStream &out); +}; + +struct Module { + QVector functions; + + Module() {} + ~Module() { qDeleteAll(functions); } + + template inline BB i(BB i) { functions.append(i); return i; } + + Function *newFunction(const NameId *name = 0) { return i(new Function(this, name)); } + + virtual void dump(QTextStream &out); +}; + +#ifdef DEBUG_IR_STRUCTURE +struct IRDump : public ExprVisitor, + public StmtVisitor +{ +public: + IRDump(); + + void expression(QDeclarativeJS::IR::Expr *); + void basicblock(QDeclarativeJS::IR::BasicBlock *); + void statement(QDeclarativeJS::IR::Stmt *); + void function(QDeclarativeJS::IR::Function *); +protected: + + const char *indent(); + + // + // expressions + // + virtual void visitConst(QDeclarativeJS::IR::Const *e); + virtual void visitString(QDeclarativeJS::IR::String *e); + virtual void visitName(QDeclarativeJS::IR::Name *e); + virtual void visitTemp(QDeclarativeJS::IR::Temp *e); + virtual void visitUnop(QDeclarativeJS::IR::Unop *e); + virtual void visitBinop(QDeclarativeJS::IR::Binop *e); + virtual void visitCall(QDeclarativeJS::IR::Call *e); + + // + // statements + // + virtual void visitExp(QDeclarativeJS::IR::Exp *s); + virtual void visitMove(QDeclarativeJS::IR::Move *s); + virtual void visitJump(QDeclarativeJS::IR::Jump *s); + virtual void visitCJump(QDeclarativeJS::IR::CJump *s); + virtual void visitRet(QDeclarativeJS::IR::Ret *s); + +private: + int indentSize; + QByteArray indentData; + void inc(); + void dec(); +}; +#endif + +} // end of namespace IR + +} // end of namespace QDeclarativeJS + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEV4IR_P_H diff --git a/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp new file mode 100644 index 0000000000..103d5ba0df --- /dev/null +++ b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp @@ -0,0 +1,1315 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativev4irbuilder_p.h" + +#include // For illegalNames +#include // For AnchorLine +#include // For AnchorLine +#include + +DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER) + +QT_BEGIN_NAMESPACE + +using namespace QDeclarativeJS; + +static IR::Type irTypeFromVariantType(int t, QDeclarativeEnginePrivate *engine, const QMetaObject *meta) +{ + switch (t) { + case QMetaType::Bool: + return IR::BoolType; + + case QMetaType::Int: + return IR::IntType; + + case QMetaType::QReal: + return IR::RealType; + + case QMetaType::QString: + return IR::StringType; + + case QMetaType::QUrl: + return IR::UrlType; + + default: + if (t == qMetaTypeId()) + return IR::AnchorLineType; + else if (t == qMetaTypeId()) + return IR::SGAnchorLineType; + else if (const QMetaObject *m = engine->metaObjectForType(t)) { + meta = m; + return IR::ObjectType; + } + + return IR::InvalidType; + } +} + +QDeclarativeV4IRBuilder::QDeclarativeV4IRBuilder(const QDeclarativeV4Compiler::Expression *expr, + QDeclarativeEnginePrivate *engine) +: m_expression(expr), m_engine(engine), _module(0), _function(0), _block(0), _discard(false) +{ +} + +QDeclarativeJS::IR::Function * +QDeclarativeV4IRBuilder::operator()(QDeclarativeJS::IR::Module *module, + QDeclarativeJS::AST::Node *ast) +{ + bool discarded = false; + + qSwap(_module, module); + + IR::Function *function = _module->newFunction(); + IR::BasicBlock *block = function->newBasicBlock(); + + qSwap(_discard, discarded); + qSwap(_function, function); + qSwap(_block, block); + + ExprResult r; + AST::SourceLocation location; + if (AST::ExpressionNode *asExpr = ast->expressionCast()) { + r = expression(asExpr); + location = asExpr->firstSourceLocation(); + } else if (AST::Statement *asStmt = ast->statementCast()) { + r = statement(asStmt); + location = asStmt->firstSourceLocation(); + } + + //_block->MOVE(_block->TEMP(IR::InvalidType), r.code); + if (r.code) { + const QMetaObject *m = 0; + const IR::Type targetType = irTypeFromVariantType(m_expression->property->type, m_engine, m); + if (targetType != r.type()) { + IR::Expr *x = _block->TEMP(targetType); + _block->MOVE(x, r, true); + r.code = x; + } + _block->RET(r.code, targetType, location.startLine, location.startColumn); + } + + qSwap(_block, block); + qSwap(_function, function); + qSwap(_discard, discarded); + + qSwap(_module, module); + + return discarded?0:function; +} + +bool QDeclarativeV4IRBuilder::buildName(QStringList &name, + AST::Node *node, + QList *nodes) +{ + if (node->kind == AST::Node::Kind_IdentifierExpression) { + name << static_cast(node)->name->asString(); + if (nodes) *nodes << static_cast(node); + } else if (node->kind == AST::Node::Kind_FieldMemberExpression) { + AST::FieldMemberExpression *expr = + static_cast(node); + + if (!buildName(name, expr->base, nodes)) + return false; + + name << expr->name->asString(); + if (nodes) *nodes << expr; + } else { + return false; + } + + return true; +} + +void QDeclarativeV4IRBuilder::discard() +{ + _discard = true; +} + +QDeclarativeV4IRBuilder::ExprResult +QDeclarativeV4IRBuilder::expression(AST::ExpressionNode *ast) +{ + ExprResult r; + if (ast) { + qSwap(_expr, r); + accept(ast); + qSwap(_expr, r); + + if (r.is(IR::InvalidType)) + discard(); + else { + Q_ASSERT(r.hint == r.format); + } + } + + return r; +} + +void QDeclarativeV4IRBuilder::condition(AST::ExpressionNode *ast, IR::BasicBlock *iftrue, IR::BasicBlock *iffalse) +{ + if (! ast) + return; + ExprResult r(iftrue, iffalse); + qSwap(_expr, r); + accept(ast); + qSwap(_expr, r); + + if (r.format != ExprResult::cx) { + if (! r.code) + discard(); + + Q_ASSERT(r.hint == ExprResult::cx); + Q_ASSERT(r.format == ExprResult::ex); + + if (r.type() != IR::BoolType) { + IR::Temp *t = _block->TEMP(IR::BoolType); + _block->MOVE(t, r); + r = t; + } + + _block->CJUMP(_block->UNOP(IR::OpIfTrue, r), iftrue, iffalse); + } +} + +QDeclarativeV4IRBuilder::ExprResult +QDeclarativeV4IRBuilder::statement(AST::Statement *ast) +{ + ExprResult r; + if (ast) { + qSwap(_expr, r); + accept(ast); + qSwap(_expr, r); + + if (r.is(IR::InvalidType)) + discard(); + else { + Q_ASSERT(r.hint == r.format); + } + } + + return r; +} + +void QDeclarativeV4IRBuilder::sourceElement(AST::SourceElement *ast) +{ + accept(ast); +} + +void QDeclarativeV4IRBuilder::implicitCvt(ExprResult &expr, IR::Type type) +{ + if (expr.type() == type) + return; // nothing to do + + IR::Expr *x = _block->TEMP(type); + _block->MOVE(x, expr.code); + expr.code = x; +} + +// QML +bool QDeclarativeV4IRBuilder::visit(AST::UiProgram *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::UiImportList *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::UiImport *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::UiPublicMember *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::UiSourceElement *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::UiObjectDefinition *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::UiObjectInitializer *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::UiObjectBinding *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::UiScriptBinding *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::UiArrayBinding *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::UiObjectMemberList *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::UiArrayMemberList *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::UiQualifiedId *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::UiSignature *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::UiFormalList *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::UiFormal *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + + +// JS +bool QDeclarativeV4IRBuilder::visit(AST::Program *ast) +{ + _function = _module->newFunction(); + _block = _function->newBasicBlock(); + accept(ast->elements); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::SourceElements *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::FunctionSourceElement *) +{ + return true; // look inside +} + +bool QDeclarativeV4IRBuilder::visit(AST::StatementSourceElement *) +{ + return true; // look inside +} + +// object literals +bool QDeclarativeV4IRBuilder::visit(AST::PropertyNameAndValueList *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::IdentifierPropertyName *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::StringLiteralPropertyName *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::NumericLiteralPropertyName *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + + +// array literals +bool QDeclarativeV4IRBuilder::visit(AST::ElementList *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::Elision *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + + +// function calls +bool QDeclarativeV4IRBuilder::visit(AST::ArgumentList *) +{ + Q_ASSERT(!"unreachable"); + return false; +} + +// expressions +bool QDeclarativeV4IRBuilder::visit(AST::ObjectLiteral *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::ArrayLiteral *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::ThisExpression *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::IdentifierExpression *ast) +{ + const quint32 line = ast->identifierToken.startLine; + const quint32 column = ast->identifierToken.startColumn; + + const QString name = ast->name->asString(); + + if (name.at(0) == QLatin1Char('u') && name.length() == 9 && name == QLatin1String("undefined")) { + _expr.code = _block->CONST(IR::UndefinedType, 0); // ### undefined value + } else if(m_engine->globalClass->illegalNames().contains(name) ) { + if (qmlVerboseCompiler()) qWarning() << "*** illegal symbol:" << name; + return false; + } else if (const QDeclarativeParser::Object *obj = m_expression->ids.value(name)) { + IR::Name *code = _block->ID_OBJECT(name, obj, line, column); + if (obj == m_expression->component) + code->storage = IR::Name::RootStorage; + _expr.code = code; + } else if (QDeclarativeTypeNameCache::Data *typeNameData = m_expression->importCache->data(name)) { + if (typeNameData->importedScriptIndex != -1) { + // We don't support invoking imported scripts + } else if (typeNameData->type) { + _expr.code = _block->ATTACH_TYPE(name, typeNameData->type, IR::Name::ScopeStorage, line, column); + } else if (typeNameData->typeNamespace) { + // We don't support namespaces + } else { + Q_ASSERT(!"Unreachable"); + } + } else { + bool found = false; + + if (m_expression->context != m_expression->component) { + // RootStorage is more efficient than ScopeStorage, so prefer that if they are the same + QDeclarativePropertyCache *cache = m_expression->context->synthCache; + const QMetaObject *metaObject = m_expression->context->metaObject(); + if (!cache) cache = m_engine->cache(metaObject); + + QDeclarativePropertyCache::Data *data = cache->property(name); + + if (data && data->revision != 0) { + if (qmlVerboseCompiler()) + qWarning() << "*** versioned symbol:" << name; + discard(); + return false; + } + + if (data && !(data->flags & QDeclarativePropertyCache::Data::IsFunction)) { + IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject); + _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::ScopeStorage, line, column); + found = true; + } + } + + if (!found) { + QDeclarativePropertyCache *cache = m_expression->component->synthCache; + const QMetaObject *metaObject = m_expression->component->metaObject(); + if (!cache) cache = m_engine->cache(metaObject); + + QDeclarativePropertyCache::Data *data = cache->property(name); + + if (data && data->revision != 0) { + if (qmlVerboseCompiler()) + qWarning() << "*** versioned symbol:" << name; + discard(); + return false; + } + + if (data && !(data->flags & QDeclarativePropertyCache::Data::IsFunction)) { + IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject); + _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::RootStorage, line, column); + found = true; + } + } + + if (!found && qmlVerboseCompiler()) + qWarning() << "*** unknown symbol:" << name; + } + + if (_expr.code && _expr.hint == ExprResult::cx) { + _expr.format = ExprResult::cx; + + if (_expr.type() != IR::BoolType) { + IR::Temp *t = _block->TEMP(IR::BoolType); + _block->MOVE(t, _expr); + _expr.code = t; + } + + _block->CJUMP(_expr.code, _expr.iftrue, _expr.iffalse); + _expr.code = 0; + } + + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::NullExpression *) +{ + // ### TODO: cx format + _expr.code = _block->CONST(IR::NullType, 0); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::TrueLiteral *) +{ + // ### TODO: cx format + _expr.code = _block->CONST(IR::BoolType, 1); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::FalseLiteral *) +{ + // ### TODO: cx format + _expr.code = _block->CONST(IR::BoolType, 0); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::StringLiteral *ast) +{ + // ### TODO: cx format + _expr.code = _block->STRING(ast->value->asString()); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::NumericLiteral *ast) +{ + if (_expr.hint == ExprResult::cx) { + _expr.format = ExprResult::cx; + _block->JUMP(ast->value ? _expr.iftrue : _expr.iffalse); + } else { + _expr.code = _block->CONST(ast->value); + } + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::RegExpLiteral *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::NestedExpression *) +{ + return true; // the value of the nested expression +} + +bool QDeclarativeV4IRBuilder::visit(AST::ArrayMemberExpression *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::FieldMemberExpression *ast) +{ + if (IR::Expr *left = expression(ast->base)) { + if (IR::Name *baseName = left->asName()) { + const quint32 line = ast->identifierToken.startLine; + const quint32 column = ast->identifierToken.startColumn; + + QString name = ast->name->asString(); + + switch(baseName->symbol) { + case IR::Name::Unbound: + break; + + case IR::Name::AttachType: + if (name.at(0).isUpper()) { + QByteArray utf8Name = name.toUtf8(); + const char *enumName = utf8Name.constData(); + + const QMetaObject *meta = baseName->declarativeType->metaObject(); + bool found = false; + for (int ii = 0; !found && ii < meta->enumeratorCount(); ++ii) { + QMetaEnum e = meta->enumerator(ii); + for (int jj = 0; !found && jj < e.keyCount(); ++jj) { + if (0 == strcmp(e.key(jj), enumName)) { + found = true; + _expr.code = _block->CONST(IR::IntType, e.value(jj)); + } + } + } + + if (!found && qmlVerboseCompiler()) + qWarning() << "*** unresolved enum:" + << (baseName->id + QLatin1String(".") + ast->name->asString()); + } else if(const QMetaObject *attachedMeta = baseName->declarativeType->attachedPropertiesType()) { + QDeclarativePropertyCache *cache = m_engine->cache(attachedMeta); + QDeclarativePropertyCache::Data *data = cache->property(name); + + if (!data || data->flags & QDeclarativePropertyCache::Data::IsFunction) + return false; // Don't support methods (or non-existing properties ;) + + if(!(data->flags & QDeclarativePropertyCache::Data::IsFinal)) { + if (qmlVerboseCompiler()) + qWarning() << "*** non-final attached property:" + << (baseName->id + QLatin1String(".") + ast->name->asString()); + return false; // We don't know enough about this property + } + + IR::Type irType = irTypeFromVariantType(data->propType, m_engine, attachedMeta); + _expr.code = _block->SYMBOL(baseName, irType, name, attachedMeta, data->coreIndex, line, column); + } + break; + + case IR::Name::IdObject: { + const QDeclarativeParser::Object *idObject = baseName->idObject; + QDeclarativePropertyCache *cache = + idObject->synthCache?idObject->synthCache:m_engine->cache(idObject->metaObject()); + + QDeclarativePropertyCache::Data *data = cache->property(name); + + if (!data || data->flags & QDeclarativePropertyCache::Data::IsFunction) + return false; // Don't support methods (or non-existing properties ;) + + if (data->revision != 0) { + if (qmlVerboseCompiler()) + qWarning() << "*** versioned symbol:" << name; + discard(); + return false; + } + + IR::Type irType = irTypeFromVariantType(data->propType, m_engine, idObject->metaObject()); + _expr.code = _block->SYMBOL(baseName, irType, name, + idObject->metaObject(), data->coreIndex, line, column); + } + break; + + case IR::Name::Property: + if (baseName->type == IR::ObjectType) { + const QMetaObject *m = + m_engine->metaObjectForType(baseName->meta->property(baseName->index).userType()); + QDeclarativePropertyCache *cache = m_engine->cache(m); + + QDeclarativePropertyCache::Data *data = cache->property(name); + + if (!data || data->flags & QDeclarativePropertyCache::Data::IsFunction) + return false; // Don't support methods (or non-existing properties ;) + + if(!(data->flags & QDeclarativePropertyCache::Data::IsFinal)) { + if (qmlVerboseCompiler()) + qWarning() << "*** non-final property access:" + << (baseName->id + QLatin1String(".") + ast->name->asString()); + return false; // We don't know enough about this property + } + + IR::Type irType = irTypeFromVariantType(data->propType, m_engine, baseName->meta); + _expr.code = _block->SYMBOL(baseName, irType, name, + baseName->meta, data->coreIndex, line, column); + } + break; + + case IR::Name::Object: + case IR::Name::Slot: + break; + } + } + } + + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::NewMemberExpression *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::NewExpression *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::CallExpression *ast) +{ + QStringList names; + QList nameNodes; + if (buildName(names, ast->base, &nameNodes)) { + //ExprResult base = expression(ast->base); + const QString id = names.join(QLatin1String(".")); + const quint32 line = nameNodes.last()->firstSourceLocation().startLine; + const quint32 column = nameNodes.last()->firstSourceLocation().startColumn; + IR::Expr *base = _block->NAME(id, line, column); + + QVector args; + for (AST::ArgumentList *it = ast->arguments; it; it = it->next) + args.append(expression(it->expression)); + + IR::Temp *r = _block->TEMP(IR::InvalidType); + IR::Expr *call = _block->CALL(base, args); + _block->MOVE(r, call); + r->type = call->type; + _expr.code = r; + } + + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::PostIncrementExpression *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::PostDecrementExpression *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::DeleteExpression *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::VoidExpression *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::TypeOfExpression *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::PreIncrementExpression *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::PreDecrementExpression *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::UnaryPlusExpression *ast) +{ + ExprResult expr = expression(ast->expression); + if (expr.isNot(IR::InvalidType)) { + if (expr.code->asConst() != 0) { + _expr = expr; + return false; + } + + IR::Expr *code = _block->UNOP(IR::OpUPlus, expr); + _expr.code = _block->TEMP(code->type); + _block->MOVE(_expr, code); + } + + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::UnaryMinusExpression *ast) +{ + ExprResult expr = expression(ast->expression); + if (expr.isNot(IR::InvalidType)) { + if (IR::Const *c = expr.code->asConst()) { + _expr = expr; + _expr.code = _block->CONST(-c->value); + return false; + } + + IR::Expr *code = _block->UNOP(IR::OpUMinus, expr); + _expr.code = _block->TEMP(code->type); + _block->MOVE(_expr, code); + } + + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::TildeExpression *ast) +{ + ExprResult expr = expression(ast->expression); + if (expr.isNot(IR::InvalidType)) { + if (IR::Const *c = expr.code->asConst()) { + _expr = expr; + _expr.code = _block->CONST(~int(c->value)); + return false; + } + IR::Expr *code = _block->UNOP(IR::OpCompl, expr); + _expr.code = _block->TEMP(code->type); + _block->MOVE(_expr, code); + } + + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::NotExpression *ast) +{ + ExprResult expr = expression(ast->expression); + + if (expr.isNot(IR::InvalidType)) { + if (IR::Const *c = expr.code->asConst()) { + _expr = expr; + _expr.code = _block->CONST(!c->value); + return false; + } + + IR::Expr *code = _block->UNOP(IR::OpNot, expr); + _expr.code = _block->TEMP(code->type); + _block->MOVE(_expr, code); + + } else if (expr.hint == ExprResult::cx) { + expr.format = ExprResult::cx; + _block->CJUMP(_block->UNOP(IR::OpNot, expr), _expr.iftrue, _expr.iffalse); + return false; + } + + return false; +} + +void QDeclarativeV4IRBuilder::binop(AST::BinaryExpression *ast, ExprResult left, ExprResult right) +{ + if (IR::Type t = maxType(left.type(), right.type())) { + implicitCvt(left, t); + implicitCvt(right, t); + + if (_expr.hint == ExprResult::cx) { + _expr.format = ExprResult::cx; + _block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse); + } else { + IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right); + _expr.code = _block->TEMP(code->type); + _block->MOVE(_expr.code, code); + } + } +} + +bool QDeclarativeV4IRBuilder::visit(AST::BinaryExpression *ast) +{ + switch (ast->op) { + case QSOperator::And: { + if (_expr.hint == ExprResult::cx) { + _expr.format = ExprResult::cx; + + Q_ASSERT(_expr.iffalse != 0); + Q_ASSERT(_expr.iftrue != 0); + + IR::BasicBlock *iftrue = _function->newBasicBlock(); + condition(ast->left, iftrue, _expr.iffalse); + + _block = iftrue; + condition(ast->right, _expr.iftrue, _expr.iffalse); + } else { + IR::BasicBlock *iftrue = _function->newBasicBlock(); + IR::BasicBlock *iffalse = _function->newBasicBlock(); + IR::BasicBlock *endif = _function->newBasicBlock(); + + condition(ast->left, iftrue, iffalse); + + IR::Temp *r = _block->TEMP(IR::InvalidType); + + _block = iffalse; + _block->MOVE(r, _block->CONST(0)); // ### use the right null value + _block->JUMP(endif); + + _block = iftrue; + ExprResult right = expression(ast->right); + _block->MOVE(r, right); + _block->JUMP(endif); + + _block = endif; + + r->type = right.type(); // ### not exactly, it can be IR::BoolType. + _expr.code = r; + } + } break; + + case QSOperator::Or: { + IR::BasicBlock *iftrue = _function->newBasicBlock(); + IR::BasicBlock *endif = _function->newBasicBlock(); + + ExprResult left = expression(ast->left); + IR::Temp *r = _block->TEMP(left.type()); + _block->MOVE(r, left); + + IR::Expr *cond = r; + if (r->type != IR::BoolType) { + cond = _block->TEMP(IR::BoolType); + _block->MOVE(cond, r); + } + + _block->CJUMP(_block->UNOP(IR::OpNot, cond), iftrue, endif); + + _block = iftrue; + ExprResult right = expression(ast->right); + _block->MOVE(r, right); + + if (left.type() != right.type()) + discard(); + + _expr.code = r; + + _block = endif; + } break; + + case QSOperator::Lt: + case QSOperator::Gt: + case QSOperator::Le: + case QSOperator::Ge: { + ExprResult left = expression(ast->left); + ExprResult right = expression(ast->right); + if (left.type() == IR::StringType && right.type() == IR::StringType) { + binop(ast, left, right); + } else if (left.isValid() && right.isValid()) { + implicitCvt(left, IR::RealType); + implicitCvt(right, IR::RealType); + binop(ast, left, right); + } + } break; + + case QSOperator::NotEqual: + case QSOperator::Equal: { + ExprResult left = expression(ast->left); + ExprResult right = expression(ast->right); + if ((left.type() == IR::NullType || left.type() == IR::UndefinedType) && + (right.type() == IR::NullType || right.type() == IR::UndefinedType)) { + const bool isEq = ast->op == QSOperator::Equal; + if (_expr.hint == ExprResult::cx) { + _expr.format = ExprResult::cx; + _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse); + } else { + _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0); + } + } else if ((left.type() == IR::StringType && right.type() >= IR::FirstNumberType) || + (left.type() >= IR::FirstNumberType && right.type() == IR::StringType)) { + implicitCvt(left, IR::RealType); + implicitCvt(right, IR::RealType); + binop(ast, left, right); + } else if (left.type() == IR::BoolType || right.type() == IR::BoolType) { + implicitCvt(left, IR::BoolType); + implicitCvt(right, IR::BoolType); + } else if (left.isValid() && right.isValid()) { + binop(ast, left, right); + } + } break; + + case QSOperator::StrictEqual: + case QSOperator::StrictNotEqual: { + ExprResult left = expression(ast->left); + ExprResult right = expression(ast->right); + if (left.type() == right.type()) { + binop(ast, left, right); + } else if (left.type() >= IR::BoolType && right.type() >= IR::BoolType) { + // left and right have numeric type (int or real) + binop(ast, left, right); + } else if (left.isValid() && right.isValid()) { + const bool isEq = ast->op == QSOperator::StrictEqual; + if (_expr.hint == ExprResult::cx) { + _expr.format = ExprResult::cx; + _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse); + } else { + _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0); + } + } + } break; + + case QSOperator::BitAnd: + case QSOperator::BitOr: + case QSOperator::BitXor: + case QSOperator::LShift: + case QSOperator::RShift: + case QSOperator::URShift: { + ExprResult left = expression(ast->left); + if (left.is(IR::InvalidType)) + return false; + + ExprResult right = expression(ast->right); + if (right.is(IR::InvalidType)) + return false; + + implicitCvt(left, IR::IntType); + implicitCvt(right, IR::IntType); + + IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right); + _expr.code = _block->TEMP(code->type); + _block->MOVE(_expr.code, code); + + } break; + + case QSOperator::Add: { + ExprResult left = expression(ast->left); + if (left.is(IR::InvalidType)) + return false; + + ExprResult right = expression(ast->right); + if (right.is(IR::InvalidType)) + return false; + + if (left.isPrimitive() && right.isPrimitive()) { + if (left.type() == IR::StringType || right.type() == IR::StringType) { + implicitCvt(left, IR::StringType); + implicitCvt(right, IR::StringType); + } + binop(ast, left, right); + } + } break; + + case QSOperator::Div: + case QSOperator::Mod: + case QSOperator::Mul: + case QSOperator::Sub: { + ExprResult left = expression(ast->left); + if (left.is(IR::InvalidType)) + return false; + + ExprResult right = expression(ast->right); + if (right.is(IR::InvalidType)) + return false; + + IR::Type t = maxType(left.type(), right.type()); + if (t >= IR::FirstNumberType) { + implicitCvt(left, IR::RealType); + implicitCvt(right, IR::RealType); + + IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right); + _expr.code = _block->TEMP(code->type); + _block->MOVE(_expr.code, code); + } + } break; + + case QSOperator::In: + case QSOperator::InstanceOf: + case QSOperator::Assign: + case QSOperator::InplaceAnd: + case QSOperator::InplaceSub: + case QSOperator::InplaceDiv: + case QSOperator::InplaceAdd: + case QSOperator::InplaceLeftShift: + case QSOperator::InplaceMod: + case QSOperator::InplaceMul: + case QSOperator::InplaceOr: + case QSOperator::InplaceRightShift: + case QSOperator::InplaceURightShift: + case QSOperator::InplaceXor: + // yup, we don't do those. + break; + } // switch + + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::ConditionalExpression *ast) +{ + IR::BasicBlock *iftrue = _function->newBasicBlock(); + IR::BasicBlock *iffalse = _function->newBasicBlock(); + IR::BasicBlock *endif = _function->newBasicBlock(); + + condition(ast->expression, iftrue, iffalse); + + IR::Temp *r = _block->TEMP(IR::InvalidType); + + qSwap(_block, iftrue); + ExprResult ok = expression(ast->ok); + _block->MOVE(r, ok); + _block->JUMP(endif); + qSwap(_block, iftrue); + + qSwap(_block, iffalse); + ExprResult ko = expression(ast->ko); + _block->MOVE(r, ko); + _block->JUMP(endif); + qSwap(_block, iffalse); + + r->type = maxType(ok.type(), ko.type()); + _expr.code = r; + + _block = endif; + + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::Expression *ast) +{ + _block->EXP(expression(ast->left)); + _expr = expression(ast->right); + + return false; +} + + +// statements +bool QDeclarativeV4IRBuilder::visit(AST::Block *ast) +{ + if (ast->statements && ! ast->statements->next) { + // we have one and only one statement + accept(ast->statements->statement); + } + + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::StatementList *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::VariableStatement *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::VariableDeclarationList *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::VariableDeclaration *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::EmptyStatement *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::ExpressionStatement *ast) +{ + if (ast->expression) { + // return the value of this expression + return true; + } + + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::IfStatement *ast) +{ + if (! ast->ko) { + // This is an if statement without an else branch. + discard(); + } else { + IR::BasicBlock *iftrue = _function->newBasicBlock(); + IR::BasicBlock *iffalse = _function->newBasicBlock(); + IR::BasicBlock *endif = _function->newBasicBlock(); + + condition(ast->expression, iftrue, iffalse); + + IR::Temp *r = _block->TEMP(IR::InvalidType); + + qSwap(_block, iftrue); + ExprResult ok = statement(ast->ok); + _block->MOVE(r, ok); + _block->JUMP(endif); + qSwap(_block, iftrue); + + qSwap(_block, iffalse); + ExprResult ko = statement(ast->ko); + _block->MOVE(r, ko); + _block->JUMP(endif); + qSwap(_block, iffalse); + + r->type = maxType(ok.type(), ko.type()); + _expr.code = r; + + _block = endif; + } + + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::DoWhileStatement *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::WhileStatement *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::ForStatement *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::LocalForStatement *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::ForEachStatement *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::LocalForEachStatement *) +{ + discard(); + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::ContinueStatement *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::BreakStatement *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::ReturnStatement *ast) +{ + if (ast->expression) { + // return the value of the expression + return true; + } + + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::WithStatement *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::SwitchStatement *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::CaseBlock *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::CaseClauses *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::CaseClause *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::DefaultClause *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::LabelledStatement *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::ThrowStatement *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::TryStatement *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::Catch *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::Finally *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::FunctionDeclaration *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::FunctionExpression *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::FormalParameterList *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::FunctionBody *) +{ + return false; +} + +bool QDeclarativeV4IRBuilder::visit(AST::DebuggerStatement *) +{ + return false; +} + +QT_END_NAMESPACE diff --git a/src/declarative/qml/v4/qdeclarativev4irbuilder_p.h b/src/declarative/qml/v4/qdeclarativev4irbuilder_p.h new file mode 100644 index 0000000000..f0bfd6624c --- /dev/null +++ b/src/declarative/qml/v4/qdeclarativev4irbuilder_p.h @@ -0,0 +1,242 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEV4IRBUILDER_P_H +#define QDECLARATIVEV4IRBUILDER_P_H + +#include + +#include "qdeclarativev4ir_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QDeclarativeV4IRBuilder : public QDeclarativeJS::AST::Visitor +{ +public: + QDeclarativeV4IRBuilder(const QDeclarativeV4Compiler::Expression *, QDeclarativeEnginePrivate *); + + QDeclarativeJS::IR::Function *operator()(QDeclarativeJS::IR::Module *, QDeclarativeJS::AST::Node *); + +protected: + struct ExprResult { + enum Format { + ex, // expression + cx // condition + }; + + QDeclarativeJS::IR::Expr *code; + QDeclarativeJS::IR::BasicBlock *iftrue; + QDeclarativeJS::IR::BasicBlock *iffalse; + Format hint; // requested format + Format format; // instruction format + + ExprResult(QDeclarativeJS::IR::Expr *expr = 0) + : code(expr), iftrue(0), iffalse(0), hint(ex), format(ex) {} + + ExprResult(QDeclarativeJS::IR::BasicBlock *iftrue, QDeclarativeJS::IR::BasicBlock *iffalse) + : code(0), iftrue(iftrue), iffalse(iffalse), hint(cx), format(ex) {} + + inline QDeclarativeJS::IR::Type type() const { return code ? code->type : QDeclarativeJS::IR::InvalidType; } + + inline QDeclarativeJS::IR::Expr *get() const { return code; } + inline operator QDeclarativeJS::IR::Expr *() const { return get(); } + inline QDeclarativeJS::IR::Expr *operator->() const { return get(); } + inline bool isValid() const { return code ? code->type != QDeclarativeJS::IR::InvalidType : false; } + inline bool is(QDeclarativeJS::IR::Type t) const { return type() == t; } + inline bool isNot(QDeclarativeJS::IR::Type t) const { return type() != t; } + + bool isPrimitive() const { + switch (type()) { + case QDeclarativeJS::IR::UndefinedType: // ### TODO + case QDeclarativeJS::IR::NullType: // ### TODO + case QDeclarativeJS::IR::UrlType: // ### TODO + return false; + + case QDeclarativeJS::IR::StringType: + case QDeclarativeJS::IR::BoolType: + case QDeclarativeJS::IR::IntType: + case QDeclarativeJS::IR::RealType: + case QDeclarativeJS::IR::RealNaNType: + return true; + + default: + return false; + } // switch + } + }; + + inline void accept(QDeclarativeJS::AST::Node *ast) { QDeclarativeJS::AST::Node::accept(ast, this); } + + ExprResult expression(QDeclarativeJS::AST::ExpressionNode *ast); + ExprResult statement(QDeclarativeJS::AST::Statement *ast); + void sourceElement(QDeclarativeJS::AST::SourceElement *ast); + void condition(QDeclarativeJS::AST::ExpressionNode *ast, QDeclarativeJS::IR::BasicBlock *iftrue, QDeclarativeJS::IR::BasicBlock *iffalse); + void binop(QDeclarativeJS::AST::BinaryExpression *ast, ExprResult left, ExprResult right); + + void implicitCvt(ExprResult &expr, QDeclarativeJS::IR::Type type); + + // QML + virtual bool visit(QDeclarativeJS::AST::UiProgram *ast); + virtual bool visit(QDeclarativeJS::AST::UiImportList *ast); + virtual bool visit(QDeclarativeJS::AST::UiImport *ast); + virtual bool visit(QDeclarativeJS::AST::UiPublicMember *ast); + virtual bool visit(QDeclarativeJS::AST::UiSourceElement *ast); + virtual bool visit(QDeclarativeJS::AST::UiObjectDefinition *ast); + virtual bool visit(QDeclarativeJS::AST::UiObjectInitializer *ast); + virtual bool visit(QDeclarativeJS::AST::UiObjectBinding *ast); + virtual bool visit(QDeclarativeJS::AST::UiScriptBinding *ast); + virtual bool visit(QDeclarativeJS::AST::UiArrayBinding *ast); + virtual bool visit(QDeclarativeJS::AST::UiObjectMemberList *ast); + virtual bool visit(QDeclarativeJS::AST::UiArrayMemberList *ast); + virtual bool visit(QDeclarativeJS::AST::UiQualifiedId *ast); + virtual bool visit(QDeclarativeJS::AST::UiSignature *ast); + virtual bool visit(QDeclarativeJS::AST::UiFormalList *ast); + virtual bool visit(QDeclarativeJS::AST::UiFormal *ast); + + // JS + virtual bool visit(QDeclarativeJS::AST::Program *ast); + virtual bool visit(QDeclarativeJS::AST::SourceElements *ast); + virtual bool visit(QDeclarativeJS::AST::FunctionSourceElement *ast); + virtual bool visit(QDeclarativeJS::AST::StatementSourceElement *ast); + + // object literals + virtual bool visit(QDeclarativeJS::AST::PropertyNameAndValueList *ast); + virtual bool visit(QDeclarativeJS::AST::IdentifierPropertyName *ast); + virtual bool visit(QDeclarativeJS::AST::StringLiteralPropertyName *ast); + virtual bool visit(QDeclarativeJS::AST::NumericLiteralPropertyName *ast); + + // array literals + virtual bool visit(QDeclarativeJS::AST::ElementList *ast); + virtual bool visit(QDeclarativeJS::AST::Elision *ast); + + // function calls + virtual bool visit(QDeclarativeJS::AST::ArgumentList *ast); + + // expressions + virtual bool visit(QDeclarativeJS::AST::ObjectLiteral *ast); + virtual bool visit(QDeclarativeJS::AST::ArrayLiteral *ast); + virtual bool visit(QDeclarativeJS::AST::ThisExpression *ast); + virtual bool visit(QDeclarativeJS::AST::IdentifierExpression *ast); + virtual bool visit(QDeclarativeJS::AST::NullExpression *ast); + virtual bool visit(QDeclarativeJS::AST::TrueLiteral *ast); + virtual bool visit(QDeclarativeJS::AST::FalseLiteral *ast); + virtual bool visit(QDeclarativeJS::AST::StringLiteral *ast); + virtual bool visit(QDeclarativeJS::AST::NumericLiteral *ast); + virtual bool visit(QDeclarativeJS::AST::RegExpLiteral *ast); + virtual bool visit(QDeclarativeJS::AST::NestedExpression *ast); + virtual bool visit(QDeclarativeJS::AST::ArrayMemberExpression *ast); + virtual bool visit(QDeclarativeJS::AST::FieldMemberExpression *ast); + virtual bool visit(QDeclarativeJS::AST::NewMemberExpression *ast); + virtual bool visit(QDeclarativeJS::AST::NewExpression *ast); + virtual bool visit(QDeclarativeJS::AST::CallExpression *ast); + virtual bool visit(QDeclarativeJS::AST::PostIncrementExpression *ast); + virtual bool visit(QDeclarativeJS::AST::PostDecrementExpression *ast); + virtual bool visit(QDeclarativeJS::AST::DeleteExpression *ast); + virtual bool visit(QDeclarativeJS::AST::VoidExpression *ast); + virtual bool visit(QDeclarativeJS::AST::TypeOfExpression *ast); + virtual bool visit(QDeclarativeJS::AST::PreIncrementExpression *ast); + virtual bool visit(QDeclarativeJS::AST::PreDecrementExpression *ast); + virtual bool visit(QDeclarativeJS::AST::UnaryPlusExpression *ast); + virtual bool visit(QDeclarativeJS::AST::UnaryMinusExpression *ast); + virtual bool visit(QDeclarativeJS::AST::TildeExpression *ast); + virtual bool visit(QDeclarativeJS::AST::NotExpression *ast); + virtual bool visit(QDeclarativeJS::AST::BinaryExpression *ast); + virtual bool visit(QDeclarativeJS::AST::ConditionalExpression *ast); + virtual bool visit(QDeclarativeJS::AST::Expression *ast); + + // statements + virtual bool visit(QDeclarativeJS::AST::Block *ast); + virtual bool visit(QDeclarativeJS::AST::StatementList *ast); + virtual bool visit(QDeclarativeJS::AST::VariableStatement *ast); + virtual bool visit(QDeclarativeJS::AST::VariableDeclarationList *ast); + virtual bool visit(QDeclarativeJS::AST::VariableDeclaration *ast); + virtual bool visit(QDeclarativeJS::AST::EmptyStatement *ast); + virtual bool visit(QDeclarativeJS::AST::ExpressionStatement *ast); + virtual bool visit(QDeclarativeJS::AST::IfStatement *ast); + virtual bool visit(QDeclarativeJS::AST::DoWhileStatement *ast); + virtual bool visit(QDeclarativeJS::AST::WhileStatement *ast); + virtual bool visit(QDeclarativeJS::AST::ForStatement *ast); + virtual bool visit(QDeclarativeJS::AST::LocalForStatement *ast); + virtual bool visit(QDeclarativeJS::AST::ForEachStatement *ast); + virtual bool visit(QDeclarativeJS::AST::LocalForEachStatement *ast); + virtual bool visit(QDeclarativeJS::AST::ContinueStatement *ast); + virtual bool visit(QDeclarativeJS::AST::BreakStatement *ast); + virtual bool visit(QDeclarativeJS::AST::ReturnStatement *ast); + virtual bool visit(QDeclarativeJS::AST::WithStatement *ast); + virtual bool visit(QDeclarativeJS::AST::SwitchStatement *ast); + virtual bool visit(QDeclarativeJS::AST::CaseBlock *ast); + virtual bool visit(QDeclarativeJS::AST::CaseClauses *ast); + virtual bool visit(QDeclarativeJS::AST::CaseClause *ast); + virtual bool visit(QDeclarativeJS::AST::DefaultClause *ast); + virtual bool visit(QDeclarativeJS::AST::LabelledStatement *ast); + virtual bool visit(QDeclarativeJS::AST::ThrowStatement *ast); + virtual bool visit(QDeclarativeJS::AST::TryStatement *ast); + virtual bool visit(QDeclarativeJS::AST::Catch *ast); + virtual bool visit(QDeclarativeJS::AST::Finally *ast); + virtual bool visit(QDeclarativeJS::AST::FunctionDeclaration *ast); + virtual bool visit(QDeclarativeJS::AST::FunctionExpression *ast); + virtual bool visit(QDeclarativeJS::AST::FormalParameterList *ast); + virtual bool visit(QDeclarativeJS::AST::FunctionBody *ast); + virtual bool visit(QDeclarativeJS::AST::DebuggerStatement *ast); + +private: + bool buildName(QStringList &name, QDeclarativeJS::AST::Node *node, + QList *nodes); + void discard(); + + const QDeclarativeV4Compiler::Expression *m_expression; + QDeclarativeEnginePrivate *m_engine; + + QDeclarativeJS::IR::Module *_module; + QDeclarativeJS::IR::Function *_function; + QDeclarativeJS::IR::BasicBlock *_block; + bool _discard; + + ExprResult _expr; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEV4IRBUILDER_P_H diff --git a/src/declarative/qml/v4/qdeclarativev4program_p.h b/src/declarative/qml/v4/qdeclarativev4program_p.h new file mode 100644 index 0000000000..d036bd6f73 --- /dev/null +++ b/src/declarative/qml/v4/qdeclarativev4program_p.h @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEV4PROGRAM_P_H +#define QDECLARATIVEV4PROGRAM_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 "qdeclarativev4instruction_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +struct QDeclarativeV4Program { + quint32 bindings; + quint32 dataLength; + quint32 signalTableOffset; + quint32 exceptionDataOffset; + quint16 subscriptions; + quint16 identifiers; + quint16 instructionCount; + + struct BindingReference { + quint32 binding; + quint32 blockMask; + }; + + struct BindingReferenceList { + quint32 count; + BindingReference bindings[]; + }; + + inline const char *data() const; + inline const char *instructions() const; + inline BindingReferenceList *signalTable(int signalIndex) const; +}; + +enum QDeclarativeRegisterType { + UndefinedType, + QObjectStarType, + QRealType, + IntType, + BoolType, + + PODValueType, + + FirstCleanupType, + QStringType = FirstCleanupType, + QUrlType, + QVariantType, +}; + +const char *QDeclarativeV4Program::data() const +{ + return ((const char *)this) + sizeof(QDeclarativeV4Program); +} + +const char *QDeclarativeV4Program::instructions() const +{ + return (const char *)(data() + dataLength); +} + +QDeclarativeV4Program::BindingReferenceList *QDeclarativeV4Program::signalTable(int signalIndex) const +{ + quint32 *signalTable = (quint32 *)(data() + signalTableOffset); + return (BindingReferenceList *)(signalTable + signalTable[signalIndex]); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEV4PROGRAM_P_H + diff --git a/src/declarative/qml/v4/v4.pri b/src/declarative/qml/v4/v4.pri new file mode 100644 index 0000000000..085f0ae443 --- /dev/null +++ b/src/declarative/qml/v4/v4.pri @@ -0,0 +1,17 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/qdeclarativev4compiler_p.h \ + $$PWD/qdeclarativev4compiler_p_p.h \ + $$PWD/qdeclarativev4ir_p.h \ + $$PWD/qdeclarativev4irbuilder_p.h \ + $$PWD/qdeclarativev4instruction_p.h \ + $$PWD/qdeclarativev4bindings_p.h \ + $$PWD/qdeclarativev4program_p.h \ + +SOURCES += \ + $$PWD/qdeclarativev4compiler.cpp \ + $$PWD/qdeclarativev4ir.cpp \ + $$PWD/qdeclarativev4irbuilder.cpp \ + $$PWD/qdeclarativev4instruction.cpp \ + $$PWD/qdeclarativev4bindings.cpp \ -- cgit v1.2.3 From 155faa3b8b1e04241bd53df3eb008d54a71cc667 Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Thu, 28 Apr 2011 15:42:46 +0200 Subject: Support mirroring the source rectangle of ShaderEffectSource. --- src/declarative/qml/qdeclarativeengine.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index b30b4cfb55..ba0ddbbfaf 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -1738,9 +1738,6 @@ QScriptValue QDeclarativeEnginePrivate::rect(QScriptContext *ctxt, QScriptEngine qsreal w = ctxt->argument(2).toNumber(); qsreal h = ctxt->argument(3).toNumber(); - if (w < 0 || h < 0) - return engine->nullValue(); - return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QRectF(x, y, w, h))); } -- cgit v1.2.3 From cff3c25ee616a7aee7bf1c0f983a190415668f5f Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 5 May 2011 11:07:59 +1000 Subject: Only include line numbers when necessary The mandatory line number bloats QML instructions for no reason. Moving it inline actually increases the instruction size further, but that will come down again once variable sized instruction support is added. Change-Id: I0ace03a50371ef57946edbb7c8e0e8c2fa4fdd76 --- src/declarative/qml/qdeclarativecompileddata.cpp | 2 +- src/declarative/qml/qdeclarativecompiler.cpp | 48 +++------ src/declarative/qml/qdeclarativeinstruction.cpp | 118 +++++++++++------------ src/declarative/qml/qdeclarativeinstruction_p.h | 22 ++++- src/declarative/qml/qdeclarativevme.cpp | 34 +++---- 5 files changed, 103 insertions(+), 121 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativecompileddata.cpp b/src/declarative/qml/qdeclarativecompileddata.cpp index 3d1e9255ad..ce57ccb33b 100644 --- a/src/declarative/qml/qdeclarativecompileddata.cpp +++ b/src/declarative/qml/qdeclarativecompileddata.cpp @@ -246,7 +246,7 @@ void QDeclarativeCompiledData::dumpInstructions() { if (!name.isEmpty()) qWarning() << name; - qWarning().nospace() << "Index\tLine\tOperation\t\tData1\tData2\tData3\tComments"; + qWarning().nospace() << "Index\tOperation\t\tData1\tData2\tData3\tComments"; qWarning().nospace() << "-------------------------------------------------------------------------------"; for (int ii = 0; ii < bytecode.count(); ++ii) { dump(&bytecode[ii], ii); diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index d325ac48dd..13a5d8769b 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -323,7 +323,6 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, QDeclarativeParser::Value *v) { QDeclarativeInstruction instr; - instr.line = v->location.start.line; if (prop.isEnumType()) { int value; if (v->value.isNumber()) { @@ -539,6 +538,7 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, instr.type = QDeclarativeInstruction::AssignCustomType; instr.assignCustomType.propertyIndex = prop.propertyIndex(); instr.assignCustomType.valueIndex = index; + instr.assignCustomType.line = v->location.start.line; QDeclarativeCompiledData::CustomTypeData data; data.index = output->indexForString(string); @@ -665,7 +665,6 @@ void QDeclarativeCompiler::compileTree(QDeclarativeParser::Object *tree) QDeclarativeInstruction import; import.type = QDeclarativeInstruction::StoreImportedScript; - import.line = 0; import.storeScript.value = output->scripts.count(); QDeclarativeScriptData *scriptData = script.script->scriptData(); @@ -687,7 +686,6 @@ void QDeclarativeCompiler::compileTree(QDeclarativeParser::Object *tree) QDeclarativeInstruction init; init.type = QDeclarativeInstruction::Init; - init.line = 0; init.init.bindingsSize = compileState.bindings.count(); init.init.parserStatusSize = compileState.parserStatusCount; init.init.contextCache = genContextCache(); @@ -700,7 +698,6 @@ void QDeclarativeCompiler::compileTree(QDeclarativeParser::Object *tree) genObject(tree); QDeclarativeInstruction def; - init.line = 0; def.type = QDeclarativeInstruction::SetDefault; output->bytecode << def; @@ -911,10 +908,10 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) QDeclarativeInstruction create; create.type = QDeclarativeInstruction::CreateSimpleObject; - create.line = obj->location.start.line; create.createSimple.create = output->types.at(obj->type).type->createFunction(); create.createSimple.typeSize = output->types.at(obj->type).type->createSize(); create.createSimple.type = obj->type; + create.createSimple.line = obj->location.start.line; create.createSimple.column = obj->location.start.column; output->bytecode << create; @@ -922,7 +919,7 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) QDeclarativeInstruction create; create.type = QDeclarativeInstruction::CreateObject; - create.line = obj->location.start.line; + create.create.line = obj->location.start.line; create.create.column = obj->location.start.column; create.create.data = -1; if (!obj->custom.isEmpty()) @@ -944,7 +941,6 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) if (!obj->metadata.isEmpty()) { QDeclarativeInstruction meta; meta.type = QDeclarativeInstruction::StoreMetaObject; - meta.line = 0; meta.storeMeta.data = output->indexForByteArray(obj->metadata); meta.storeMeta.aliasData = output->indexForByteArray(obj->synthdata); meta.storeMeta.propertyCache = output->propertyCaches.count(); @@ -979,7 +975,6 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) if (!obj->id.isEmpty()) { QDeclarativeInstruction id; id.type = QDeclarativeInstruction::SetId; - id.line = 0; id.setId.value = output->indexForString(obj->id); id.setId.index = obj->idIndex; output->bytecode << id; @@ -990,7 +985,6 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) QDeclarativeInstruction begin; begin.type = QDeclarativeInstruction::BeginObject; begin.begin.castValue = obj->parserStatusCast; - begin.line = obj->location.start.line; output->bytecode << begin; } @@ -1022,7 +1016,6 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) if (seenDefer) { QDeclarativeInstruction defer; defer.type = QDeclarativeInstruction::Defer; - defer.line = 0; defer.defer.deferCount = 0; int deferIdx = output->bytecode.count(); output->bytecode << defer; @@ -1055,7 +1048,7 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) QDeclarativeInstruction assign; assign.type = QDeclarativeInstruction::AssignSignalObject; - assign.line = v->location.start.line; + assign.assignSignalObject.line = v->location.start.line; assign.assignSignalObject.signal = output->indexForByteArray(prop->name); output->bytecode << assign; @@ -1066,12 +1059,12 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) QDeclarativeInstruction store; store.type = QDeclarativeInstruction::StoreSignal; - store.line = v->location.start.line; store.storeSignal.signalIndex = prop->index; store.storeSignal.value = output->indexForString(v->value.asScript().trimmed()); store.storeSignal.context = ctxt.stack; store.storeSignal.name = output->indexForByteArray(prop->name); + store.storeSignal.line = v->location.start.line; output->bytecode << store; } @@ -1081,15 +1074,14 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) foreach(Property *prop, obj->attachedProperties) { QDeclarativeInstruction fetch; fetch.type = QDeclarativeInstruction::FetchAttached; - fetch.line = prop->location.start.line; fetch.fetchAttached.id = prop->index; + fetch.fetchAttached.line = prop->location.start.line; output->bytecode << fetch; genObjectBody(prop->value); QDeclarativeInstruction pop; pop.type = QDeclarativeInstruction::PopFetchedObject; - pop.line = prop->location.start.line; output->bytecode << pop; } @@ -1097,13 +1089,12 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) QDeclarativeInstruction fetch; fetch.type = QDeclarativeInstruction::FetchObject; fetch.fetch.property = prop->index; - fetch.line = prop->location.start.line; + fetch.fetch.line = prop->location.start.line; output->bytecode << fetch; if (!prop->value->metadata.isEmpty()) { QDeclarativeInstruction meta; meta.type = QDeclarativeInstruction::StoreMetaObject; - meta.line = 0; meta.storeMeta.data = output->indexForByteArray(prop->value->metadata); meta.storeMeta.aliasData = output->indexForByteArray(prop->value->synthdata); meta.storeMeta.propertyCache = -1; @@ -1114,7 +1105,6 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) QDeclarativeInstruction pop; pop.type = QDeclarativeInstruction::PopFetchedObject; - pop.line = prop->location.start.line; output->bytecode << pop; } @@ -1143,7 +1133,6 @@ void QDeclarativeCompiler::genValueTypeProperty(QDeclarativeParser::Object *obj, fetch.fetchValue.property = prop->index; fetch.fetchValue.type = prop->type; fetch.fetchValue.bindingSkipList = 0; - fetch.line = prop->location.start.line; 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 @@ -1167,7 +1156,6 @@ void QDeclarativeCompiler::genValueTypeProperty(QDeclarativeParser::Object *obj, pop.fetchValue.property = prop->index; pop.fetchValue.type = prop->type; pop.fetchValue.bindingSkipList = 0; - pop.line = prop->location.start.line; output->bytecode << pop; } @@ -1178,7 +1166,7 @@ void QDeclarativeCompiler::genComponent(QDeclarativeParser::Object *obj) QDeclarativeInstruction create; create.type = QDeclarativeInstruction::CreateComponent; - create.line = root->location.start.line; + create.createComponent.line = root->location.start.line; create.createComponent.column = root->location.start.column; create.createComponent.endLine = root->location.end.line; output->bytecode << create; @@ -1196,13 +1184,11 @@ void QDeclarativeCompiler::genComponent(QDeclarativeParser::Object *obj) init.init.compiledBinding = -1; else init.init.compiledBinding = output->indexForByteArray(compileState.compiledBindingData); - init.line = obj->location.start.line; output->bytecode << init; genObject(root); QDeclarativeInstruction def; - init.line = 0; def.type = QDeclarativeInstruction::SetDefault; output->bytecode << def; @@ -1214,7 +1200,6 @@ void QDeclarativeCompiler::genComponent(QDeclarativeParser::Object *obj) if (!obj->id.isEmpty()) { QDeclarativeInstruction id; id.type = QDeclarativeInstruction::SetId; - id.line = 0; id.setId.value = output->indexForString(obj->id); id.setId.index = obj->idIndex; output->bytecode << id; @@ -1608,7 +1593,6 @@ void QDeclarativeCompiler::genListProperty(QDeclarativeParser::Property *prop, QDeclarativeInstruction fetch; fetch.type = QDeclarativeInstruction::FetchQList; - fetch.line = prop->location.start.line; fetch.fetchQmlList.property = prop->index; bool listTypeIsInterface = QDeclarativeMetaType::isInterface(listType); fetch.fetchQmlList.type = listType; @@ -1623,12 +1607,11 @@ void QDeclarativeCompiler::genListProperty(QDeclarativeParser::Property *prop, if (listTypeIsInterface) { QDeclarativeInstruction assign; assign.type = QDeclarativeInstruction::AssignObjectList; - assign.line = prop->location.start.line; + assign.assignObjectList.line = prop->location.start.line; output->bytecode << assign; } else { QDeclarativeInstruction store; store.type = QDeclarativeInstruction::StoreObjectQList; - store.line = prop->location.start.line; output->bytecode << store; } @@ -1642,7 +1625,6 @@ void QDeclarativeCompiler::genListProperty(QDeclarativeParser::Property *prop, QDeclarativeInstruction pop; pop.type = QDeclarativeInstruction::PopQList; - pop.line = prop->location.start.line; output->bytecode << pop; } @@ -1665,7 +1647,7 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p QDeclarativeInstruction store; store.type = QDeclarativeInstruction::StoreInterface; - store.line = v->object->location.start.line; + store.storeObject.line = v->object->location.start.line; store.storeObject.propertyIndex = prop->index; output->bytecode << store; @@ -1673,7 +1655,7 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p QDeclarativeInstruction store; store.type = QDeclarativeInstruction::StoreVariantObject; - store.line = v->object->location.start.line; + store.storeObject.line = v->object->location.start.line; store.storeObject.propertyIndex = prop->index; output->bytecode << store; @@ -1681,7 +1663,7 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p QDeclarativeInstruction store; store.type = QDeclarativeInstruction::StoreObject; - store.line = v->object->location.start.line; + store.storeObject.line = v->object->location.start.line; store.storeObject.propertyIndex = prop->index; output->bytecode << store; @@ -1711,7 +1693,6 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p QDeclarativeInstruction store; store.type = QDeclarativeInstruction::StoreValueSource; - store.line = v->object->location.start.line; if (valueTypeProperty) { store.assignValueSource.property = genValueTypeData(prop, valueTypeProperty); store.assignValueSource.owner = 1; @@ -1728,7 +1709,6 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p QDeclarativeInstruction store; store.type = QDeclarativeInstruction::StoreValueInterceptor; - store.line = v->object->location.start.line; if (valueTypeProperty) { store.assignValueInterceptor.property = genValueTypeData(prop, valueTypeProperty); store.assignValueInterceptor.owner = 1; @@ -2835,7 +2815,7 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeParser::Value *bindi ((prop->index & 0xFF) << 24); else store.assignBinding.property = prop->index; - store.line = binding->location.start.line; + store.assignBinding.line = binding->location.start.line; output->bytecode << store; return; } @@ -2848,7 +2828,7 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeParser::Value *bindi store.assignBinding.value = output->indexForByteArray(ref.compiledData); store.assignBinding.context = ref.bindingContext.stack; store.assignBinding.owner = ref.bindingContext.owner; - store.line = binding->location.start.line; + store.assignBinding.line = binding->location.start.line; Q_ASSERT(ref.bindingContext.owner == 0 || (ref.bindingContext.owner != 0 && valueTypeProperty)); diff --git a/src/declarative/qml/qdeclarativeinstruction.cpp b/src/declarative/qml/qdeclarativeinstruction.cpp index 556b7bc343..237cfa2a16 100644 --- a/src/declarative/qml/qdeclarativeinstruction.cpp +++ b/src/declarative/qml/qdeclarativeinstruction.cpp @@ -53,178 +53,168 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx) Q_UNUSED(instr) Q_UNUSED(idx) #else - QByteArray lineNumber = QByteArray::number(instr->line); - if (instr->line == (unsigned short)-1) - lineNumber = "NA"; - const char *line = lineNumber.constData(); - switch(instr->type) { case QDeclarativeInstruction::Init: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "INIT\t\t\t" << instr->init.bindingsSize << "\t" << instr->init.parserStatusSize << "\t" << instr->init.contextCache << "\t" << instr->init.compiledBinding; + 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 QDeclarativeInstruction::CreateObject: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "CREATE\t\t\t" << instr->create.type << "\t" << instr->create.bindingBits << "\t\t" << types.at(instr->create.type).className; + qWarning().nospace() << idx << "\t\t" << "CREATE\t\t\t" << instr->create.type << "\t" << instr->create.bindingBits << "\t\t" << types.at(instr->create.type).className; break; case QDeclarativeInstruction::CreateSimpleObject: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "CREATE_SIMPLE\t\t" << instr->createSimple.typeSize; + qWarning().nospace() << idx << "\t\t" << "CREATE_SIMPLE\t\t" << instr->createSimple.typeSize; break; case QDeclarativeInstruction::SetId: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "SETID\t\t\t" << instr->setId.value << "\t\t\t" << primitives.at(instr->setId.value); + qWarning().nospace() << idx << "\t\t" << "SETID\t\t\t" << instr->setId.value << "\t\t\t" << primitives.at(instr->setId.value); break; case QDeclarativeInstruction::SetDefault: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "SET_DEFAULT"; + qWarning().nospace() << idx << "\t\t" << "SET_DEFAULT"; break; case QDeclarativeInstruction::CreateComponent: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "CREATE_COMPONENT\t" << instr->createComponent.count; + qWarning().nospace() << idx << "\t\t" << "CREATE_COMPONENT\t" << instr->createComponent.count; break; case QDeclarativeInstruction::StoreMetaObject: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_META\t\t" << instr->storeMeta.data; + qWarning().nospace() << idx << "\t\t" << "STORE_META\t\t" << instr->storeMeta.data; break; - case QDeclarativeInstruction::StoreFloat: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_FLOAT\t\t" << instr->storeFloat.propertyIndex << "\t" << instr->storeFloat.value; + qWarning().nospace() << idx << "\t\t" << "STORE_FLOAT\t\t" << instr->storeFloat.propertyIndex << "\t" << instr->storeFloat.value; break; case QDeclarativeInstruction::StoreDouble: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_DOUBLE\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value; + qWarning().nospace() << idx << "\t\t" << "STORE_DOUBLE\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value; break; case QDeclarativeInstruction::StoreInteger: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_INTEGER\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value; + qWarning().nospace() << idx << "\t\t" << "STORE_INTEGER\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value; break; case QDeclarativeInstruction::StoreBool: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_BOOL\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value; + qWarning().nospace() << idx << "\t\t" << "STORE_BOOL\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value; break; case QDeclarativeInstruction::StoreString: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_STRING\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value); + 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 QDeclarativeInstruction::StoreByteArray: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_BYTEARRAY" << instr->storeByteArray.propertyIndex << "\t" << instr->storeByteArray.value << "\t\t" << datas.at(instr->storeByteArray.value); + qWarning().nospace() << idx << "\t\t" << "STORE_BYTEARRAY" << instr->storeByteArray.propertyIndex << "\t" << instr->storeByteArray.value << "\t\t" << datas.at(instr->storeByteArray.value); break; case QDeclarativeInstruction::StoreUrl: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_URL\t\t" << instr->storeUrl.propertyIndex << "\t" << instr->storeUrl.value << "\t\t" << urls.at(instr->storeUrl.value); + 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 QDeclarativeInstruction::StoreColor: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_COLOR\t\t" << instr->storeColor.propertyIndex << "\t\t\t" << QString::number(instr->storeColor.value, 16); + qWarning().nospace() << idx << "\t\t" << "STORE_COLOR\t\t" << instr->storeColor.propertyIndex << "\t\t\t" << QString::number(instr->storeColor.value, 16); break; case QDeclarativeInstruction::StoreDate: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_DATE\t\t" << instr->storeDate.propertyIndex << "\t" << instr->storeDate.value; + qWarning().nospace() << idx << "\t\t" << "STORE_DATE\t\t" << instr->storeDate.propertyIndex << "\t" << instr->storeDate.value; break; case QDeclarativeInstruction::StoreTime: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_TIME\t\t" << instr->storeTime.propertyIndex << "\t" << instr->storeTime.valueIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_TIME\t\t" << instr->storeTime.propertyIndex << "\t" << instr->storeTime.valueIndex; break; case QDeclarativeInstruction::StoreDateTime: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_DATETIME\t\t" << instr->storeDateTime.propertyIndex << "\t" << instr->storeDateTime.valueIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_DATETIME\t\t" << instr->storeDateTime.propertyIndex << "\t" << instr->storeDateTime.valueIndex; break; case QDeclarativeInstruction::StorePoint: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_POINT\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_POINT\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex; break; case QDeclarativeInstruction::StorePointF: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_POINTF\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_POINTF\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex; break; case QDeclarativeInstruction::StoreSize: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_SIZE\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_SIZE\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex; break; case QDeclarativeInstruction::StoreSizeF: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_SIZEF\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_SIZEF\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex; break; case QDeclarativeInstruction::StoreRect: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_RECT\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.valueIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_RECT\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.valueIndex; break; case QDeclarativeInstruction::StoreRectF: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_RECTF\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.valueIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_RECTF\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.valueIndex; break; case QDeclarativeInstruction::StoreVector3D: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VECTOR3D\t\t" << instr->storeVector3D.propertyIndex << "\t" << instr->storeVector3D.valueIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_VECTOR3D\t\t" << instr->storeVector3D.propertyIndex << "\t" << instr->storeVector3D.valueIndex; break; case QDeclarativeInstruction::StoreVariant: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VARIANT\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value); + 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 QDeclarativeInstruction::StoreVariantInteger: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VARIANT_INTEGER\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value; + qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT_INTEGER\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value; break; case QDeclarativeInstruction::StoreVariantDouble: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VARIANT_DOUBLE\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value; + qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT_DOUBLE\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value; break; case QDeclarativeInstruction::StoreVariantBool: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VARIANT_BOOL\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value; + qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT_BOOL\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value; break; case QDeclarativeInstruction::StoreObject: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_OBJECT\t\t" << instr->storeObject.propertyIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_OBJECT\t\t" << instr->storeObject.propertyIndex; break; case QDeclarativeInstruction::StoreVariantObject: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VARIANT_OBJECT\t" << instr->storeObject.propertyIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT_OBJECT\t" << instr->storeObject.propertyIndex; break; case QDeclarativeInstruction::StoreInterface: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_INTERFACE\t\t" << instr->storeObject.propertyIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_INTERFACE\t\t" << instr->storeObject.propertyIndex; break; - case QDeclarativeInstruction::StoreSignal: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_SIGNAL\t\t" << instr->storeSignal.signalIndex << "\t" << instr->storeSignal.value << "\t\t" << primitives.at(instr->storeSignal.value); + qWarning().nospace() << idx << "\t\t" << "STORE_SIGNAL\t\t" << instr->storeSignal.signalIndex << "\t" << instr->storeSignal.value << "\t\t" << primitives.at(instr->storeSignal.value); break; case QDeclarativeInstruction::StoreImportedScript: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_IMPORTED_SCRIPT\t" << instr->storeScript.value; + qWarning().nospace() << idx << "\t\t" << "STORE_IMPORTED_SCRIPT\t" << instr->storeScript.value; break; case QDeclarativeInstruction::StoreScriptString: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_SCRIPT_STRING\t" << instr->storeScriptString.propertyIndex << "\t" << instr->storeScriptString.value << "\t" << instr->storeScriptString.scope; + qWarning().nospace() << idx << "\t\t" << "STORE_SCRIPT_STRING\t" << instr->storeScriptString.propertyIndex << "\t" << instr->storeScriptString.value << "\t" << instr->storeScriptString.scope; break; - case QDeclarativeInstruction::AssignSignalObject: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "ASSIGN_SIGNAL_OBJECT\t" << instr->assignSignalObject.signal << "\t\t\t" << datas.at(instr->assignSignalObject.signal); + qWarning().nospace() << idx << "\t\t" << "ASSIGN_SIGNAL_OBJECT\t" << instr->assignSignalObject.signal << "\t\t\t" << datas.at(instr->assignSignalObject.signal); break; case QDeclarativeInstruction::AssignCustomType: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "ASSIGN_CUSTOMTYPE\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.valueIndex; + qWarning().nospace() << idx << "\t\t" << "ASSIGN_CUSTOMTYPE\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.valueIndex; break; - case QDeclarativeInstruction::StoreBinding: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context; + qWarning().nospace() << idx << "\t\t" << "STORE_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context; break; case QDeclarativeInstruction::StoreBindingOnAlias: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_BINDING_ALIAS\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context; + qWarning().nospace() << idx << "\t\t" << "STORE_BINDING_ALIAS\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context; break; case QDeclarativeInstruction::StoreCompiledBinding: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_COMPILED_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context; + qWarning().nospace() << idx << "\t\t" << "STORE_COMPILED_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context; break; case QDeclarativeInstruction::StoreValueSource: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property << "\t" << instr->assignValueSource.castValue; + qWarning().nospace() << idx << "\t\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property << "\t" << instr->assignValueSource.castValue; break; case QDeclarativeInstruction::StoreValueInterceptor: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VALUE_INTERCEPTOR\t" << instr->assignValueInterceptor.property << "\t" << instr->assignValueInterceptor.castValue; + qWarning().nospace() << idx << "\t\t" << "STORE_VALUE_INTERCEPTOR\t" << instr->assignValueInterceptor.property << "\t" << instr->assignValueInterceptor.castValue; break; - case QDeclarativeInstruction::BeginObject: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "BEGIN\t\t\t" << instr->begin.castValue; + qWarning().nospace() << idx << "\t\t" << "BEGIN\t\t\t" << instr->begin.castValue; break; case QDeclarativeInstruction::StoreObjectQList: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_OBJECT_QLIST"; + qWarning().nospace() << idx << "\t\t" << "STORE_OBJECT_QLIST"; break; case QDeclarativeInstruction::AssignObjectList: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "ASSIGN_OBJECT_LIST"; + qWarning().nospace() << idx << "\t\t" << "ASSIGN_OBJECT_LIST"; break; case QDeclarativeInstruction::FetchAttached: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "FETCH_ATTACHED\t\t" << instr->fetchAttached.id; + qWarning().nospace() << idx << "\t\t" << "FETCH_ATTACHED\t\t" << instr->fetchAttached.id; break; case QDeclarativeInstruction::FetchQList: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "FETCH_QLIST\t\t" << instr->fetch.property; + qWarning().nospace() << idx << "\t\t" << "FETCH_QLIST\t\t" << instr->fetch.property; break; case QDeclarativeInstruction::FetchObject: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "FETCH\t\t\t" << instr->fetch.property; + qWarning().nospace() << idx << "\t\t" << "FETCH\t\t\t" << instr->fetch.property; break; case QDeclarativeInstruction::FetchValueType: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "FETCH_VALUE\t\t" << instr->fetchValue.property << "\t" << instr->fetchValue.type << "\t" << instr->fetchValue.bindingSkipList; + qWarning().nospace() << idx << "\t\t" << "FETCH_VALUE\t\t" << instr->fetchValue.property << "\t" << instr->fetchValue.type << "\t" << instr->fetchValue.bindingSkipList; break; case QDeclarativeInstruction::PopFetchedObject: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "POP"; + qWarning().nospace() << idx << "\t\t" << "POP"; break; case QDeclarativeInstruction::PopQList: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "POP_QLIST"; + qWarning().nospace() << idx << "\t\t" << "POP_QLIST"; break; case QDeclarativeInstruction::PopValueType: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "POP_VALUE\t\t" << instr->fetchValue.property << "\t" << instr->fetchValue.type; + qWarning().nospace() << idx << "\t\t" << "POP_VALUE\t\t" << instr->fetchValue.property << "\t" << instr->fetchValue.type; break; case QDeclarativeInstruction::Defer: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "DEFER" << "\t\t\t" << instr->defer.deferCount; + qWarning().nospace() << idx << "\t\t" << "DEFER" << "\t\t\t" << instr->defer.deferCount; break; default: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "XXX UNKNOWN INSTRUCTION" << "\t" << instr->type; + qWarning().nospace() << idx << "\t\t" << "XXX UNKNOWN INSTRUCTION" << "\t" << instr->type; break; } #endif // QT_NO_DEBUG_STREAM diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h index a5521b6425..3032964a33 100644 --- a/src/declarative/qml/qdeclarativeinstruction_p.h +++ b/src/declarative/qml/qdeclarativeinstruction_p.h @@ -142,7 +142,7 @@ public: BeginObject, /* begin */ StoreObjectQList, /* NA */ - AssignObjectList, /* NA */ + AssignObjectList, /* assignObjectList */ FetchAttached, /* fetchAttached */ FetchQList, /* fetch */ @@ -163,11 +163,9 @@ public: // Defer /* defer */ }; - QDeclarativeInstruction() - : line(0) {} + QDeclarativeInstruction() {} Type type; - unsigned short line; struct InitInstruction { int bindingsSize; @@ -180,12 +178,14 @@ public: int data; int bindingBits; ushort column; + ushort line; }; struct CreateSimpleInstruction { void (*create)(void *); int typeSize; int type; ushort column; + ushort line; }; struct StoreMetaInstruction { int data; @@ -211,9 +211,11 @@ public: int value; short context; short owner; + ushort line; }; struct FetchInstruction { int property; + ushort line; }; struct FetchValueInstruction { int property; @@ -293,32 +295,41 @@ public: }; struct StoreObjectInstruction { int propertyIndex; + ushort line; }; struct AssignCustomTypeInstruction { int propertyIndex; int valueIndex; + ushort line; }; struct StoreSignalInstruction { int signalIndex; int value; short context; int name; + ushort line; }; struct AssignSignalObjectInstruction { int signal; + ushort line; }; struct CreateComponentInstruction { int count; - ushort column; int endLine; int metaObject; + ushort column; + ushort line; }; struct FetchAttachedInstruction { int id; + ushort line; }; struct DeferInstruction { int deferCount; }; + struct AssignObjectListInstruction { + ushort line; + }; union { InitInstruction init; @@ -356,6 +367,7 @@ public: CreateComponentInstruction createComponent; FetchAttachedInstruction fetchAttached; DeferInstruction defer; + AssignObjectListInstruction assignObjectList; }; void dump(QDeclarativeCompiledData *); diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index 6bbc47bcaf..af29991858 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -80,11 +80,11 @@ QDeclarativeVME::QDeclarativeVME() { } -#define VME_EXCEPTION(desc) \ +#define VME_EXCEPTION(desc, line) \ { \ QDeclarativeError error; \ error.setDescription(desc.trimmed()); \ - error.setLine(instr.line); \ + error.setLine(line); \ error.setUrl(comp->url); \ vmeErrors << error; \ break; \ @@ -207,7 +207,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, types.at(instr.create.type).createInstance(ctxt, bindings, &vmeErrors); if (!o) { - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.create.type).className))); + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.create.type).className)), instr.create.line); } QDeclarativeData *ddata = QDeclarativeData::get(o); @@ -232,7 +232,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, ddata->setImplicitDestructible(); ddata->outerContext = ctxt; - ddata->lineNumber = instr.line; + ddata->lineNumber = instr.create.line; ddata->columnNumber = instr.create.column; if (instr.create.data != -1) { @@ -271,7 +271,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, ddata->propertyCache = ref.typePropertyCache; ddata->propertyCache->addref(); } - ddata->lineNumber = instr.line; + ddata->lineNumber = instr.createSimple.line; ddata->columnNumber = instr.createSimple.column; QObjectPrivate::get(o)->declarativeData = ddata; @@ -319,8 +319,8 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, ddata->setImplicitDestructible(); ddata->outerContext = ctxt; - ddata->lineNumber = instr.line; - ddata->columnNumber = instr.create.column; + ddata->lineNumber = instr.createComponent.line; + ddata->columnNumber = instr.createComponent.column; QDeclarativeComponentPrivate::get(qcomp)->creationContext = ctxt; @@ -657,7 +657,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QMetaProperty prop = target->metaObject()->property(instr.assignCustomType.propertyIndex); if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type)) - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name()))); + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.assignCustomType.line); void *a[] = { (void *)v.data(), 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, @@ -679,15 +679,15 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign); if (method.signature() == 0) - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className()))); + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())), instr.assignSignalObject.line); if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature())) - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature()))); + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature())), instr.assignSignalObject.line); QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex()); } else { - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr))); + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr)), instr.assignSignalObject.line); } @@ -704,7 +704,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target); QDeclarativeExpression *expr = new QDeclarativeExpression(ctxt, context, primitives.at(instr.storeSignal.value)); - expr->setSourceLocation(comp->name, instr.line); + expr->setSourceLocation(comp->name, instr.storeSignal.line); static_cast(QObjectPrivate::get(expr))->name = datas.at(instr.storeSignal.name); bs->setExpression(expr); } @@ -758,7 +758,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, if ((stack.count() - instr.assignBinding.owner) == 1 && bindingSkipList.testBit(coreIndex)) break; - QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, comp->name, instr.line, 0); + QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, comp->name, instr.assignBinding.line, 0); bindValues.append(bind); bind->m_mePtr = &bindValues.values[bindValues.count - 1]; bind->setTarget(mp); @@ -841,7 +841,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, if (iid) ptr = assign->qt_metacast(iid); if (!ptr) - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list")); + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list"), instr.assignObjectList.line); list.qListProperty.append((QDeclarativeListProperty*)&list.qListProperty, ptr); @@ -884,7 +884,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, } if (!ok) - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property")); + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property"), instr.storeObject.line); } break; @@ -895,7 +895,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.fetchAttached.id, target); if (!qmlObject) - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object")); + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object"), instr.fetchAttached.line); stack.push(qmlObject); } @@ -927,7 +927,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, instr.fetch.property, a); if (!obj) - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.fetch.property).name()))); + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.fetch.property).name())), instr.fetch.line); stack.push(obj); } -- cgit v1.2.3 From cb661b8fd32b20b4a90b13fa49e2a21f41b2e87d Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 5 May 2011 13:48:29 +1000 Subject: Support variable length instructions in QML bytecode Reviewed-by: Martin Jones Change-Id: Ib04b8d46a78723d3a734e14d22a2f2256c1627c2 --- src/declarative/qml/qdeclarativecompileddata.cpp | 33 +- src/declarative/qml/qdeclarativecompiler.cpp | 219 +-- src/declarative/qml/qdeclarativecompiler_p.h | 6 +- src/declarative/qml/qdeclarativecomponent.cpp | 9 +- src/declarative/qml/qdeclarativecomponent.h | 2 +- src/declarative/qml/qdeclarativecomponent_p.h | 5 +- src/declarative/qml/qdeclarativeinstruction.cpp | 17 +- src/declarative/qml/qdeclarativeinstruction_p.h | 375 ++--- src/declarative/qml/qdeclarativevme.cpp | 1473 +++++++++----------- src/declarative/qml/qdeclarativevme_p.h | 7 +- src/declarative/qml/v4/qdeclarativev4bindings.cpp | 312 ++--- .../qml/v4/qdeclarativev4instruction.cpp | 8 +- .../qml/v4/qdeclarativev4instruction_p.h | 74 +- 13 files changed, 1265 insertions(+), 1275 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativecompileddata.cpp b/src/declarative/qml/qdeclarativecompileddata.cpp index ce57ccb33b..1f5d11141d 100644 --- a/src/declarative/qml/qdeclarativecompileddata.cpp +++ b/src/declarative/qml/qdeclarativecompileddata.cpp @@ -248,11 +248,40 @@ void QDeclarativeCompiledData::dumpInstructions() qWarning() << name; qWarning().nospace() << "Index\tOperation\t\tData1\tData2\tData3\tComments"; qWarning().nospace() << "-------------------------------------------------------------------------------"; - for (int ii = 0; ii < bytecode.count(); ++ii) { - dump(&bytecode[ii], ii); + + const char *instructionStream = bytecode.constData(); + const char *endInstructionStream = bytecode.constData() + bytecode.size(); + + int instructionCount = 0; + while (instructionStream < endInstructionStream) { + QDeclarativeInstruction *instr = (QDeclarativeInstruction *)instructionStream; + dump(instr, instructionCount); + instructionStream += instr->size(); + instructionCount++; } + qWarning().nospace() << "-------------------------------------------------------------------------------"; } +int QDeclarativeCompiledData::addInstruction(const QDeclarativeInstruction &instr) +{ + int ptrOffset = bytecode.size(); + int size = instr.size(); + bytecode.resize(bytecode.size() + size); + char *data = bytecode.data() + ptrOffset; + qMemCopy(data, &instr, size); + + return ptrOffset; +} + +int QDeclarativeCompiledData::nextInstructionIndex() +{ + return bytecode.size(); +} + +QDeclarativeInstruction *QDeclarativeCompiledData::instruction(int index) +{ + return (QDeclarativeInstruction *)(bytecode.constData() + index); +} QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 13a5d8769b..d8aa938943 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -336,10 +336,10 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, value = prop.enumerator().keyToValue(v->value.asString().toUtf8().constData()); } - instr.type = QDeclarativeInstruction::StoreInteger; + instr.setType(QDeclarativeInstruction::StoreInteger); instr.storeInteger.propertyIndex = prop.propertyIndex(); instr.storeInteger.value = value; - output->bytecode << instr; + output->addInstruction(instr); return; } @@ -352,20 +352,20 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, if (v->value.isNumber()) { double n = v->value.asNumber(); if (double(int(n)) == n) { - instr.type = QDeclarativeInstruction::StoreVariantInteger; + instr.setType(QDeclarativeInstruction::StoreVariantInteger); instr.storeInteger.propertyIndex = prop.propertyIndex(); instr.storeInteger.value = int(n); } else { - instr.type = QDeclarativeInstruction::StoreVariantDouble; + instr.setType(QDeclarativeInstruction::StoreVariantDouble); instr.storeDouble.propertyIndex = prop.propertyIndex(); instr.storeDouble.value = n; } } else if(v->value.isBoolean()) { - instr.type = QDeclarativeInstruction::StoreVariantBool; + instr.setType(QDeclarativeInstruction::StoreVariantBool); instr.storeBool.propertyIndex = prop.propertyIndex(); instr.storeBool.value = v->value.asBoolean(); } else { - instr.type = QDeclarativeInstruction::StoreVariant; + instr.setType(QDeclarativeInstruction::StoreVariant); instr.storeString.propertyIndex = prop.propertyIndex(); instr.storeString.value = output->indexForString(string); } @@ -373,21 +373,21 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, break; case QVariant::String: { - instr.type = QDeclarativeInstruction::StoreString; + instr.setType(QDeclarativeInstruction::StoreString); instr.storeString.propertyIndex = prop.propertyIndex(); instr.storeString.value = output->indexForString(string); } break; case QVariant::ByteArray: { - instr.type = QDeclarativeInstruction::StoreByteArray; + instr.setType(QDeclarativeInstruction::StoreByteArray); instr.storeByteArray.propertyIndex = prop.propertyIndex(); instr.storeByteArray.value = output->indexForByteArray(string.toLatin1()); } break; case QVariant::Url: { - instr.type = QDeclarativeInstruction::StoreUrl; + instr.setType(QDeclarativeInstruction::StoreUrl); QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(QUrl(string)); instr.storeUrl.propertyIndex = prop.propertyIndex(); instr.storeUrl.value = output->indexForUrl(u); @@ -395,28 +395,28 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, break; case QVariant::UInt: { - instr.type = QDeclarativeInstruction::StoreInteger; + instr.setType(QDeclarativeInstruction::StoreInteger); instr.storeInteger.propertyIndex = prop.propertyIndex(); instr.storeInteger.value = uint(v->value.asNumber()); } break; case QVariant::Int: { - instr.type = QDeclarativeInstruction::StoreInteger; + instr.setType(QDeclarativeInstruction::StoreInteger); instr.storeInteger.propertyIndex = prop.propertyIndex(); instr.storeInteger.value = int(v->value.asNumber()); } break; case QMetaType::Float: { - instr.type = QDeclarativeInstruction::StoreFloat; + instr.setType(QDeclarativeInstruction::StoreFloat); instr.storeFloat.propertyIndex = prop.propertyIndex(); instr.storeFloat.value = float(v->value.asNumber()); } break; case QVariant::Double: { - instr.type = QDeclarativeInstruction::StoreDouble; + instr.setType(QDeclarativeInstruction::StoreDouble); instr.storeDouble.propertyIndex = prop.propertyIndex(); instr.storeDouble.value = v->value.asNumber(); } @@ -424,7 +424,7 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, case QVariant::Color: { QColor c = QDeclarativeStringConverters::colorFromString(string); - instr.type = QDeclarativeInstruction::StoreColor; + instr.setType(QDeclarativeInstruction::StoreColor); instr.storeColor.propertyIndex = prop.propertyIndex(); instr.storeColor.value = c.rgba(); } @@ -433,7 +433,7 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, case QVariant::Date: { QDate d = QDeclarativeStringConverters::dateFromString(string); - instr.type = QDeclarativeInstruction::StoreDate; + instr.setType(QDeclarativeInstruction::StoreDate); instr.storeDate.propertyIndex = prop.propertyIndex(); instr.storeDate.value = d.toJulianDay(); } @@ -444,7 +444,7 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, int data[] = { time.hour(), time.minute(), time.second(), time.msec() }; int index = output->indexForInt(data, 4); - instr.type = QDeclarativeInstruction::StoreTime; + instr.setType(QDeclarativeInstruction::StoreTime); instr.storeTime.propertyIndex = prop.propertyIndex(); instr.storeTime.valueIndex = index; } @@ -458,7 +458,7 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, dateTime.time().second(), dateTime.time().msec() }; int index = output->indexForInt(data, 5); - instr.type = QDeclarativeInstruction::StoreDateTime; + instr.setType(QDeclarativeInstruction::StoreDateTime); instr.storeDateTime.propertyIndex = prop.propertyIndex(); instr.storeDateTime.valueIndex = index; } @@ -473,9 +473,9 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, float data[] = { float(point.x()), float(point.y()) }; int index = output->indexForFloat(data, 2); if (type == QVariant::PointF) - instr.type = QDeclarativeInstruction::StorePointF; + instr.setType(QDeclarativeInstruction::StorePointF); else - instr.type = QDeclarativeInstruction::StorePoint; + instr.setType(QDeclarativeInstruction::StorePoint); instr.storeRealPair.propertyIndex = prop.propertyIndex(); instr.storeRealPair.valueIndex = index; } @@ -488,9 +488,9 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, float data[] = { float(size.width()), float(size.height()) }; int index = output->indexForFloat(data, 2); if (type == QVariant::SizeF) - instr.type = QDeclarativeInstruction::StoreSizeF; + instr.setType(QDeclarativeInstruction::StoreSizeF); else - instr.type = QDeclarativeInstruction::StoreSize; + instr.setType(QDeclarativeInstruction::StoreSize); instr.storeRealPair.propertyIndex = prop.propertyIndex(); instr.storeRealPair.valueIndex = index; } @@ -504,9 +504,9 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, float(rect.width()), float(rect.height()) }; int index = output->indexForFloat(data, 4); if (type == QVariant::RectF) - instr.type = QDeclarativeInstruction::StoreRectF; + instr.setType(QDeclarativeInstruction::StoreRectF); else - instr.type = QDeclarativeInstruction::StoreRect; + instr.setType(QDeclarativeInstruction::StoreRect); instr.storeRect.propertyIndex = prop.propertyIndex(); instr.storeRect.valueIndex = index; } @@ -514,7 +514,7 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, case QVariant::Bool: { bool b = v->value.asBoolean(); - instr.type = QDeclarativeInstruction::StoreBool; + instr.setType(QDeclarativeInstruction::StoreBool); instr.storeBool.propertyIndex = prop.propertyIndex(); instr.storeBool.value = b; } @@ -526,7 +526,7 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, QDeclarativeStringConverters::vector3DFromString(string, &ok); float data[] = { float(vector.x()), float(vector.y()), float(vector.z()) }; int index = output->indexForFloat(data, 3); - instr.type = QDeclarativeInstruction::StoreVector3D; + instr.setType(QDeclarativeInstruction::StoreVector3D); instr.storeRealPair.propertyIndex = prop.propertyIndex(); instr.storeRealPair.valueIndex = index; } @@ -535,7 +535,7 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, { int t = prop.userType(); int index = output->customTypeData.count(); - instr.type = QDeclarativeInstruction::AssignCustomType; + instr.setType(QDeclarativeInstruction::AssignCustomType); instr.assignCustomType.propertyIndex = prop.propertyIndex(); instr.assignCustomType.valueIndex = index; instr.assignCustomType.line = v->location.start.line; @@ -547,7 +547,7 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, } break; } - output->bytecode << instr; + output->addInstruction(instr); } /*! @@ -664,13 +664,13 @@ void QDeclarativeCompiler::compileTree(QDeclarativeParser::Object *tree) importedScriptIndexes.append(script.qualifier); QDeclarativeInstruction import; - import.type = QDeclarativeInstruction::StoreImportedScript; + import.setType(QDeclarativeInstruction::StoreImportedScript); import.storeScript.value = output->scripts.count(); QDeclarativeScriptData *scriptData = script.script->scriptData(); scriptData->addref(); output->scripts << scriptData; - output->bytecode << import; + output->addInstruction(import); } // We generate the importCache before we build the tree so that @@ -685,7 +685,7 @@ void QDeclarativeCompiler::compileTree(QDeclarativeParser::Object *tree) return; QDeclarativeInstruction init; - init.type = QDeclarativeInstruction::Init; + init.setType(QDeclarativeInstruction::Init); init.init.bindingsSize = compileState.bindings.count(); init.init.parserStatusSize = compileState.parserStatusCount; init.init.contextCache = genContextCache(); @@ -693,13 +693,17 @@ void QDeclarativeCompiler::compileTree(QDeclarativeParser::Object *tree) init.init.compiledBinding = -1; else init.init.compiledBinding = output->indexForByteArray(compileState.compiledBindingData); - output->bytecode << init; + output->addInstruction(init); genObject(tree); QDeclarativeInstruction def; - def.type = QDeclarativeInstruction::SetDefault; - output->bytecode << def; + def.setType(QDeclarativeInstruction::SetDefault); + output->addInstruction(def); + + QDeclarativeInstruction done; + done.setType(QDeclarativeInstruction::Done); + output->addInstruction(done); Q_ASSERT(tree->metatype); @@ -907,18 +911,18 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) !output->types.at(obj->type).type->isExtendedType() && obj != compileState.root) { QDeclarativeInstruction create; - create.type = QDeclarativeInstruction::CreateSimpleObject; + create.setType(QDeclarativeInstruction::CreateSimpleObject); create.createSimple.create = output->types.at(obj->type).type->createFunction(); create.createSimple.typeSize = output->types.at(obj->type).type->createSize(); create.createSimple.type = obj->type; create.createSimple.line = obj->location.start.line; create.createSimple.column = obj->location.start.column; - output->bytecode << create; + output->addInstruction(create); } else { QDeclarativeInstruction create; - create.type = QDeclarativeInstruction::CreateObject; + create.setType(QDeclarativeInstruction::CreateObject); create.create.line = obj->location.start.line; create.create.column = obj->location.start.column; create.create.data = -1; @@ -933,14 +937,14 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) } else { create.create.bindingBits = -1; } - output->bytecode << create; + output->addInstruction(create); } // Setup the synthesized meta object if necessary if (!obj->metadata.isEmpty()) { QDeclarativeInstruction meta; - meta.type = QDeclarativeInstruction::StoreMetaObject; + meta.setType(QDeclarativeInstruction::StoreMetaObject); meta.storeMeta.data = output->indexForByteArray(obj->metadata); meta.storeMeta.aliasData = output->indexForByteArray(obj->synthdata); meta.storeMeta.propertyCache = output->propertyCaches.count(); @@ -965,7 +969,7 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) } output->propertyCaches << propertyCache; - output->bytecode << meta; + output->addInstruction(meta); } else if (obj == unitRoot) { output->rootPropertyCache = tr.createPropertyCache(engine); output->rootPropertyCache->addref(); @@ -974,18 +978,18 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) // Set the object id if (!obj->id.isEmpty()) { QDeclarativeInstruction id; - id.type = QDeclarativeInstruction::SetId; + id.setType(QDeclarativeInstruction::SetId); id.setId.value = output->indexForString(obj->id); id.setId.index = obj->idIndex; - output->bytecode << id; + output->addInstruction(id); } // Begin the class if (tr.type && obj->parserStatusCast != -1) { QDeclarativeInstruction begin; - begin.type = QDeclarativeInstruction::BeginObject; + begin.setType(QDeclarativeInstruction::BeginObject); begin.begin.castValue = obj->parserStatusCast; - output->bytecode << begin; + output->addInstruction(begin); } genObjectBody(obj); @@ -996,12 +1000,12 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) typedef QPair PropPair; foreach(const PropPair &prop, obj->scriptStringProperties) { QDeclarativeInstruction ss; - ss.type = QDeclarativeInstruction::StoreScriptString; + ss.setType(QDeclarativeInstruction::StoreScriptString); ss.storeScriptString.propertyIndex = prop.first->index; ss.storeScriptString.value = output->indexForString(prop.first->values.at(0)->value.asScript()); ss.storeScriptString.scope = prop.second; - output->bytecode << ss; + output->addInstruction(ss); } bool seenDefer = false; @@ -1015,18 +1019,18 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) } if (seenDefer) { QDeclarativeInstruction defer; - defer.type = QDeclarativeInstruction::Defer; + defer.setType(QDeclarativeInstruction::Defer); defer.defer.deferCount = 0; - int deferIdx = output->bytecode.count(); - output->bytecode << defer; + int deferIdx = output->addInstruction(defer); + int nextInstructionIndex = output->nextInstructionIndex(); QDeclarativeInstruction init; - init.type = QDeclarativeInstruction::Init; + init.setType(QDeclarativeInstruction::Init); init.init.bindingsSize = compileState.bindings.count(); // XXX - bigger than necessary init.init.parserStatusSize = compileState.parserStatusCount; // XXX - bigger than necessary init.init.contextCache = -1; init.init.compiledBinding = -1; - output->bytecode << init; + output->addInstruction(init); foreach(Property *prop, obj->valueProperties) { if (!prop->isDeferred) @@ -1034,8 +1038,11 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) genValueProperty(prop, obj); } - output->bytecode[deferIdx].defer.deferCount = - output->bytecode.count() - deferIdx - 1; + QDeclarativeInstruction done; + done.setType(QDeclarativeInstruction::Done); + output->addInstruction(done); + + output->instruction(deferIdx)->defer.deferCount = output->nextInstructionIndex() - nextInstructionIndex; } foreach(Property *prop, obj->signalProperties) { @@ -1047,25 +1054,25 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) genObject(v->object); QDeclarativeInstruction assign; - assign.type = QDeclarativeInstruction::AssignSignalObject; + assign.setType(QDeclarativeInstruction::AssignSignalObject); assign.assignSignalObject.line = v->location.start.line; assign.assignSignalObject.signal = output->indexForByteArray(prop->name); - output->bytecode << assign; + output->addInstruction(assign); } else if (v->type == Value::SignalExpression) { BindingContext ctxt = compileState.signalExpressions.value(v); QDeclarativeInstruction store; - store.type = QDeclarativeInstruction::StoreSignal; + store.setType(QDeclarativeInstruction::StoreSignal); store.storeSignal.signalIndex = prop->index; store.storeSignal.value = output->indexForString(v->value.asScript().trimmed()); store.storeSignal.context = ctxt.stack; store.storeSignal.name = output->indexForByteArray(prop->name); store.storeSignal.line = v->location.start.line; - output->bytecode << store; + output->addInstruction(store); } @@ -1073,39 +1080,39 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) foreach(Property *prop, obj->attachedProperties) { QDeclarativeInstruction fetch; - fetch.type = QDeclarativeInstruction::FetchAttached; + fetch.setType(QDeclarativeInstruction::FetchAttached); fetch.fetchAttached.id = prop->index; fetch.fetchAttached.line = prop->location.start.line; - output->bytecode << fetch; + output->addInstruction(fetch); genObjectBody(prop->value); QDeclarativeInstruction pop; - pop.type = QDeclarativeInstruction::PopFetchedObject; - output->bytecode << pop; + pop.setType(QDeclarativeInstruction::PopFetchedObject); + output->addInstruction(pop); } foreach(Property *prop, obj->groupedProperties) { QDeclarativeInstruction fetch; - fetch.type = QDeclarativeInstruction::FetchObject; + fetch.setType(QDeclarativeInstruction::FetchObject); fetch.fetch.property = prop->index; fetch.fetch.line = prop->location.start.line; - output->bytecode << fetch; + output->addInstruction(fetch); if (!prop->value->metadata.isEmpty()) { QDeclarativeInstruction meta; - meta.type = QDeclarativeInstruction::StoreMetaObject; + meta.setType(QDeclarativeInstruction::StoreMetaObject); meta.storeMeta.data = output->indexForByteArray(prop->value->metadata); meta.storeMeta.aliasData = output->indexForByteArray(prop->value->synthdata); meta.storeMeta.propertyCache = -1; - output->bytecode << meta; + output->addInstruction(meta); } genObjectBody(prop->value); QDeclarativeInstruction pop; - pop.type = QDeclarativeInstruction::PopFetchedObject; - output->bytecode << pop; + pop.setType(QDeclarativeInstruction::PopFetchedObject); + output->addInstruction(pop); } foreach(Property *prop, obj->valueTypeProperties) { @@ -1129,7 +1136,7 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) void QDeclarativeCompiler::genValueTypeProperty(QDeclarativeParser::Object *obj,QDeclarativeParser::Property *prop) { QDeclarativeInstruction fetch; - fetch.type = QDeclarativeInstruction::FetchValueType; + fetch.setType(QDeclarativeInstruction::FetchValueType); fetch.fetchValue.property = prop->index; fetch.fetchValue.type = prop->type; fetch.fetchValue.bindingSkipList = 0; @@ -1145,18 +1152,18 @@ void QDeclarativeCompiler::genValueTypeProperty(QDeclarativeParser::Object *obj, } } - output->bytecode << fetch; + output->addInstruction(fetch); foreach(Property *vprop, prop->value->valueProperties) { genPropertyAssignment(vprop, prop->value, prop); } QDeclarativeInstruction pop; - pop.type = QDeclarativeInstruction::PopValueType; + pop.setType(QDeclarativeInstruction::PopValueType); pop.fetchValue.property = prop->index; pop.fetchValue.type = prop->type; pop.fetchValue.bindingSkipList = 0; - output->bytecode << pop; + output->addInstruction(pop); } void QDeclarativeCompiler::genComponent(QDeclarativeParser::Object *obj) @@ -1165,18 +1172,18 @@ void QDeclarativeCompiler::genComponent(QDeclarativeParser::Object *obj) Q_ASSERT(root); QDeclarativeInstruction create; - create.type = QDeclarativeInstruction::CreateComponent; + create.setType(QDeclarativeInstruction::CreateComponent); create.createComponent.line = root->location.start.line; create.createComponent.column = root->location.start.column; create.createComponent.endLine = root->location.end.line; - output->bytecode << create; - int count = output->bytecode.count(); + int createInstruction = output->addInstruction(create); + int nextInstructionIndex = output->nextInstructionIndex(); ComponentCompileState oldCompileState = compileState; compileState = componentState(root); QDeclarativeInstruction init; - init.type = QDeclarativeInstruction::Init; + init.setType(QDeclarativeInstruction::Init); init.init.bindingsSize = compileState.bindings.count(); init.init.parserStatusSize = compileState.parserStatusCount; init.init.contextCache = genContextCache(); @@ -1184,25 +1191,29 @@ void QDeclarativeCompiler::genComponent(QDeclarativeParser::Object *obj) init.init.compiledBinding = -1; else init.init.compiledBinding = output->indexForByteArray(compileState.compiledBindingData); - output->bytecode << init; + output->addInstruction(init); genObject(root); QDeclarativeInstruction def; - def.type = QDeclarativeInstruction::SetDefault; - output->bytecode << def; + def.setType(QDeclarativeInstruction::SetDefault); + output->addInstruction(def); + + QDeclarativeInstruction done; + done.setType(QDeclarativeInstruction::Done); + output->addInstruction(done); - output->bytecode[count - 1].createComponent.count = - output->bytecode.count() - count; + output->instruction(createInstruction)->createComponent.count = + output->nextInstructionIndex() - nextInstructionIndex; compileState = oldCompileState; if (!obj->id.isEmpty()) { QDeclarativeInstruction id; - id.type = QDeclarativeInstruction::SetId; + id.setType(QDeclarativeInstruction::SetId); id.setId.value = output->indexForString(obj->id); id.setId.index = obj->idIndex; - output->bytecode << id; + output->addInstruction(id); } } @@ -1592,11 +1603,11 @@ void QDeclarativeCompiler::genListProperty(QDeclarativeParser::Property *prop, int listType = enginePrivate->listType(prop->type); QDeclarativeInstruction fetch; - fetch.type = QDeclarativeInstruction::FetchQList; + fetch.setType(QDeclarativeInstruction::FetchQList); fetch.fetchQmlList.property = prop->index; bool listTypeIsInterface = QDeclarativeMetaType::isInterface(listType); fetch.fetchQmlList.type = listType; - output->bytecode << fetch; + output->addInstruction(fetch); for (int ii = 0; ii < prop->values.count(); ++ii) { QDeclarativeParser::Value *v = prop->values.at(ii); @@ -1606,13 +1617,13 @@ void QDeclarativeCompiler::genListProperty(QDeclarativeParser::Property *prop, genObject(v->object); if (listTypeIsInterface) { QDeclarativeInstruction assign; - assign.type = QDeclarativeInstruction::AssignObjectList; + assign.setType(QDeclarativeInstruction::AssignObjectList); assign.assignObjectList.line = prop->location.start.line; - output->bytecode << assign; + output->addInstruction(assign); } else { QDeclarativeInstruction store; - store.type = QDeclarativeInstruction::StoreObjectQList; - output->bytecode << store; + store.setType(QDeclarativeInstruction::StoreObjectQList); + output->addInstruction(store); } } else if (v->type == Value::PropertyBinding) { @@ -1624,8 +1635,8 @@ void QDeclarativeCompiler::genListProperty(QDeclarativeParser::Property *prop, } QDeclarativeInstruction pop; - pop.type = QDeclarativeInstruction::PopQList; - output->bytecode << pop; + pop.setType(QDeclarativeInstruction::PopQList); + output->addInstruction(pop); } void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *prop, @@ -1646,26 +1657,26 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p if (QDeclarativeMetaType::isInterface(prop->type)) { QDeclarativeInstruction store; - store.type = QDeclarativeInstruction::StoreInterface; + store.setType(QDeclarativeInstruction::StoreInterface); store.storeObject.line = v->object->location.start.line; store.storeObject.propertyIndex = prop->index; - output->bytecode << store; + output->addInstruction(store); } else if (prop->type == -1) { QDeclarativeInstruction store; - store.type = QDeclarativeInstruction::StoreVariantObject; + store.setType(QDeclarativeInstruction::StoreVariantObject); store.storeObject.line = v->object->location.start.line; store.storeObject.propertyIndex = prop->index; - output->bytecode << store; + output->addInstruction(store); } else { QDeclarativeInstruction store; - store.type = QDeclarativeInstruction::StoreObject; + store.setType(QDeclarativeInstruction::StoreObject); store.storeObject.line = v->object->location.start.line; store.storeObject.propertyIndex = prop->index; - output->bytecode << store; + output->addInstruction(store); } } else if (v->type == Value::PropertyBinding) { @@ -1692,7 +1703,7 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p genObject(v->object); QDeclarativeInstruction store; - store.type = QDeclarativeInstruction::StoreValueSource; + store.setType(QDeclarativeInstruction::StoreValueSource); if (valueTypeProperty) { store.assignValueSource.property = genValueTypeData(prop, valueTypeProperty); store.assignValueSource.owner = 1; @@ -1702,13 +1713,13 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p } QDeclarativeType *valueType = toQmlType(v->object); store.assignValueSource.castValue = valueType->propertyValueSourceCast(); - output->bytecode << store; + output->addInstruction(store); } else if (v->type == Value::ValueInterceptor) { genObject(v->object); QDeclarativeInstruction store; - store.type = QDeclarativeInstruction::StoreValueInterceptor; + store.setType(QDeclarativeInstruction::StoreValueInterceptor); if (valueTypeProperty) { store.assignValueInterceptor.property = genValueTypeData(prop, valueTypeProperty); store.assignValueInterceptor.owner = 1; @@ -1718,7 +1729,7 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p } QDeclarativeType *valueType = toQmlType(v->object); store.assignValueInterceptor.castValue = valueType->propertyValueInterceptorCast(); - output->bytecode << store; + output->addInstruction(store); } } @@ -2805,7 +2816,7 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeParser::Value *bindi const BindingReference &ref = compileState.bindings.value(binding); if (ref.dataType == BindingReference::Experimental) { QDeclarativeInstruction store; - store.type = QDeclarativeInstruction::StoreCompiledBinding; + store.setType(QDeclarativeInstruction::StoreCompiledBinding); store.assignBinding.value = ref.compiledIndex; store.assignBinding.context = ref.bindingContext.stack; store.assignBinding.owner = ref.bindingContext.owner; @@ -2816,15 +2827,15 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeParser::Value *bindi else store.assignBinding.property = prop->index; store.assignBinding.line = binding->location.start.line; - output->bytecode << store; + output->addInstruction(store); return; } QDeclarativeInstruction store; if (!prop->isAlias) - store.type = QDeclarativeInstruction::StoreBinding; + store.setType(QDeclarativeInstruction::StoreBinding); else - store.type = QDeclarativeInstruction::StoreBindingOnAlias; + store.setType(QDeclarativeInstruction::StoreBindingOnAlias); store.assignBinding.value = output->indexForByteArray(ref.compiledData); store.assignBinding.context = ref.bindingContext.stack; store.assignBinding.owner = ref.bindingContext.owner; @@ -2838,7 +2849,7 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeParser::Value *bindi store.assignBinding.property = genPropertyData(prop); } - output->bytecode << store; + output->addInstruction(store); } int QDeclarativeCompiler::genContextCache() diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h index 49bab759be..3697d3ace2 100644 --- a/src/declarative/qml/qdeclarativecompiler_p.h +++ b/src/declarative/qml/qdeclarativecompiler_p.h @@ -117,7 +117,7 @@ public: QList customTypeData; QList datas; QList locations; - QList bytecode; + QByteArray bytecode; QList cachedPrograms; QList cachedClosures; QList propertyCaches; @@ -127,6 +127,10 @@ public: void dumpInstructions(); + int addInstruction(const QDeclarativeInstruction &instr); + int nextInstructionIndex(); + QDeclarativeInstruction *instruction(int index); + protected: virtual void clear(); // From QDeclarativeCleanup diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index aa1bbd156f..7126746078 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -455,7 +455,7 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, const Q /*! \internal */ -QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, QDeclarativeCompiledData *cc, int start, int count, QObject *parent) +QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, QDeclarativeCompiledData *cc, int start, QObject *parent) : QObject(*(new QDeclarativeComponentPrivate), parent) { Q_D(QDeclarativeComponent); @@ -463,7 +463,6 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeEngine *engine, QDeclar d->cc = cc; cc->addref(); d->start = start; - d->count = count; d->url = cc->url; d->progress = 1.0; } @@ -833,7 +832,7 @@ QDeclarativeComponentPrivate::beginCreate(QDeclarativeContextData *context, cons return 0; } - return begin(context, creationContext, cc, start, count, &state, 0, bindings); + return begin(context, creationContext, cc, start, &state, 0, bindings); } /* @@ -866,7 +865,7 @@ static inline QString buildTypeNameForDebug(const QMetaObject *metaObject) QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentContext, QDeclarativeContextData *componentCreationContext, - QDeclarativeCompiledData *component, int start, int count, + QDeclarativeCompiledData *component, int start, ConstructionState *state, QList *errors, const QBitField &bindings) { @@ -895,7 +894,7 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentCon QDeclarativeVME vme; enginePriv->referenceScarceResources(); // "hold" scarce resources in memory during evaluation. - QObject *rv = vme.run(ctxt, component, start, count, bindings); + QObject *rv = vme.run(ctxt, component, start, bindings); enginePriv->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete. if (vme.isError()) { diff --git a/src/declarative/qml/qdeclarativecomponent.h b/src/declarative/qml/qdeclarativecomponent.h index f46ffdf2cf..72e77dab85 100644 --- a/src/declarative/qml/qdeclarativecomponent.h +++ b/src/declarative/qml/qdeclarativecomponent.h @@ -113,7 +113,7 @@ protected: Q_INVOKABLE Q_REVISION(1) QScriptValue createObject(QObject* parent, const QScriptValue& valuemap); //XXX Versioning private: - QDeclarativeComponent(QDeclarativeEngine *, QDeclarativeCompiledData *, int, int, QObject *parent); + QDeclarativeComponent(QDeclarativeEngine *, QDeclarativeCompiledData *, int, QObject *parent); Q_DISABLE_COPY(QDeclarativeComponent) friend class QDeclarativeVME; diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h index f8bec2b475..9bfbba94e2 100644 --- a/src/declarative/qml/qdeclarativecomponent_p.h +++ b/src/declarative/qml/qdeclarativecomponent_p.h @@ -79,7 +79,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeComponentPrivate : public QObjectPrivate, pu Q_DECLARE_PUBLIC(QDeclarativeComponent) public: - QDeclarativeComponentPrivate() : typeData(0), progress(0.), start(-1), count(-1), cc(0), engine(0), creationContext(0) {} + QDeclarativeComponentPrivate() : typeData(0), progress(0.), start(-1), cc(0), engine(0), creationContext(0) {} QObject *beginCreate(QDeclarativeContextData *, const QBitField &); void completeCreate(); @@ -94,7 +94,6 @@ public: qreal progress; int start; - int count; QDeclarativeCompiledData *cc; struct ConstructionState { @@ -109,7 +108,7 @@ public: ConstructionState state; static QObject *begin(QDeclarativeContextData *parentContext, QDeclarativeContextData *componentCreationContext, - QDeclarativeCompiledData *component, int start, int count, + QDeclarativeCompiledData *component, int start, ConstructionState *state, QList *errors, const QBitField &bindings = QBitField()); static void beginDeferred(QDeclarativeEnginePrivate *enginePriv, QObject *object, diff --git a/src/declarative/qml/qdeclarativeinstruction.cpp b/src/declarative/qml/qdeclarativeinstruction.cpp index 237cfa2a16..202e6461e4 100644 --- a/src/declarative/qml/qdeclarativeinstruction.cpp +++ b/src/declarative/qml/qdeclarativeinstruction.cpp @@ -53,10 +53,13 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx) Q_UNUSED(instr) Q_UNUSED(idx) #else - switch(instr->type) { + switch(instr->type()) { case QDeclarativeInstruction::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 QDeclarativeInstruction::Done: + qWarning().nospace() << idx << "\t\t" << "DONE"; + break; case QDeclarativeInstruction::CreateObject: qWarning().nospace() << idx << "\t\t" << "CREATE\t\t\t" << instr->create.type << "\t" << instr->create.bindingBits << "\t\t" << types.at(instr->create.type).className; break; @@ -214,10 +217,20 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx) qWarning().nospace() << idx << "\t\t" << "DEFER" << "\t\t\t" << instr->defer.deferCount; break; default: - qWarning().nospace() << idx << "\t\t" << "XXX UNKNOWN INSTRUCTION" << "\t" << instr->type; + qWarning().nospace() << idx << "\t\t" << "XXX UNKNOWN INSTRUCTION" << "\t" << instr->type(); break; } #endif // QT_NO_DEBUG_STREAM } +int QDeclarativeInstruction::size() const +{ +#define QML_RETURN_INSTR_SIZE(I, FMT) case I: return QDeclarativeInstructionMeta<(int)I>::Size; + switch (common.instructionType) { + FOR_EACH_QML_INSTR(QML_RETURN_INSTR_SIZE) + default: return 0; + } +#undef QML_RETURN_INSTR_SIZE +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h index 3032964a33..b436ce531f 100644 --- a/src/declarative/qml/qdeclarativeinstruction_p.h +++ b/src/declarative/qml/qdeclarativeinstruction_p.h @@ -57,322 +57,339 @@ QT_BEGIN_NAMESPACE -class QDeclarativeCompiledData; -class Q_AUTOTEST_EXPORT QDeclarativeInstruction -{ -public: - enum Type { - // - // Object Creation - // - // CreateObject - Create a new object instance and push it on the - // object stack - // SetId - Set the id of the object on the top of the object stack - // SetDefault - Sets the instance on the top of the object stack to - // be the context's default object. - // StoreMetaObject - Assign the dynamic metaobject to object on the - // top of the stack. - Init, /* init */ - CreateObject, /* create */ - CreateSimpleObject, /* createSimple */ - SetId, /* setId */ - SetDefault, - CreateComponent, /* createComponent */ - StoreMetaObject, /* storeMeta */ - - // - // Precomputed single assignment - // - // StoreFloat - Store a float in a core property - // StoreDouble - Store a double in a core property - // StoreInteger - Store a int or uint in a core property - // StoreBool - Store a bool in a core property - // StoreString - Store a QString in a core property - // StoreByteArray - Store a QByteArray in a core property - // StoreUrl - Store a QUrl in a core property - // StoreColor - Store a QColor in a core property - // StoreDate - Store a QDate in a core property - // StoreTime - Store a QTime in a core property - // StoreDateTime - Store a QDateTime in a core property - // StoreVariant - Store a QVariant in a core property - // StoreObject - Pop the object on the top of the object stack and - // store it in a core property - StoreFloat, /* storeFloat */ - StoreDouble, /* storeDouble */ - StoreInteger, /* storeInteger */ - StoreBool, /* storeBool */ - StoreString, /* storeString */ - StoreByteArray, /* storeByteArray */ - StoreUrl, /* storeUrl */ - StoreColor, /* storeColor */ - StoreDate, /* storeDate */ - StoreTime, /* storeTime */ - StoreDateTime, /* storeDateTime */ - StorePoint, /* storeRealPair */ - StorePointF, /* storeRealPair */ - StoreSize, /* storeRealPair */ - StoreSizeF, /* storeRealPair */ - StoreRect, /* storeRect */ - StoreRectF, /* storeRect */ - StoreVector3D, /* storeVector3D */ - StoreVariant, /* storeString */ - StoreVariantInteger, /* storeInteger */ - StoreVariantDouble, /* storeDouble */ - StoreVariantBool, /* storeBool */ - StoreObject, /* storeObject */ - StoreVariantObject, /* storeObject */ - StoreInterface, /* storeObject */ - - StoreSignal, /* storeSignal */ - StoreImportedScript, /* storeScript */ - StoreScriptString, /* storeScriptString */ - - // - // Unresolved single assignment - // - AssignSignalObject, /* assignSignalObject */ - AssignCustomType, /* assignCustomType */ - - StoreBinding, /* assignBinding */ - StoreBindingOnAlias, /* assignBinding */ - StoreCompiledBinding, /* assignBinding */ - StoreValueSource, /* assignValueSource */ - StoreValueInterceptor, /* assignValueInterceptor */ - - BeginObject, /* begin */ - - StoreObjectQList, /* NA */ - AssignObjectList, /* assignObjectList */ +#define FOR_EACH_QML_INSTR(F) \ + F(Init, init) \ + F(Done, common) \ + F(CreateObject, create) \ + 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(StoreString, storeString) \ + F(StoreByteArray, storeByteArray) \ + F(StoreUrl, storeUrl) \ + F(StoreFloat, storeFloat) \ + F(StoreDouble, storeDouble) \ + F(StoreBool, storeBool) \ + F(StoreInteger, storeInteger) \ + F(StoreColor, storeColor) \ + F(StoreDate, storeDate) \ + F(StoreTime, storeTime) \ + F(StoreDateTime, storeDateTime) \ + F(StorePoint, storeRealPair) \ + F(StorePointF, storeRealPair) \ + F(StoreSize, storeRealPair) \ + F(StoreSizeF, storeRealPair) \ + F(StoreRect, storeRect) \ + F(StoreRectF, storeRect) \ + F(StoreVector3D, storeVector3D) \ + 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(StoreBindingOnAlias, assignBinding) \ + F(StoreCompiledBinding, assignBinding) \ + F(StoreValueSource, assignValueSource) \ + F(StoreValueInterceptor, assignValueInterceptor) \ + F(StoreObjectQList, common) \ + F(AssignObjectList, assignObjectList) \ + F(StoreVariantObject, 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) - FetchAttached, /* fetchAttached */ - FetchQList, /* fetch */ - FetchObject, /* fetch */ - FetchValueType, /* fetchValue */ +#ifdef Q_ALIGNOF +# define QML_INSTR_ALIGN_MASK (Q_ALIGNOF(QDeclarativeInstruction) - 1) +#else +# define QML_INSTR_ALIGN_MASK (sizeof(void *) - 1) +#endif - // - // Stack manipulation - // - // PopFetchedObject - Remove an object from the object stack - // PopQList - Remove a list from the list stack - PopFetchedObject, - PopQList, - PopValueType, /* fetchValue */ +#define QML_INSTR_HEADER quint8 instructionType; +#define QML_INSTR_ENUM(I, FMT) I, +#define QML_INSTR_SIZE(I, FMT) ((sizeof(QDeclarativeInstruction::instr_##FMT) + QML_INSTR_ALIGN_MASK) & ~QML_INSTR_ALIGN_MASK) - // - // Deferred creation - // - Defer /* defer */ +class QDeclarativeCompiledData; +union QDeclarativeInstruction +{ + enum Type { + FOR_EACH_QML_INSTR(QML_INSTR_ENUM) }; - QDeclarativeInstruction() {} - Type type; + inline void setType(Type type) { common.instructionType = type; } + inline Type type() const { return (Type)common.instructionType; } - struct InitInstruction { + struct instr_common { + QML_INSTR_HEADER + }; + struct instr_init { + QML_INSTR_HEADER int bindingsSize; int parserStatusSize; int contextCache; int compiledBinding; }; - struct CreateInstruction { + struct instr_create { + QML_INSTR_HEADER int type; int data; int bindingBits; ushort column; ushort line; }; - struct CreateSimpleInstruction { + struct instr_createSimple { + QML_INSTR_HEADER void (*create)(void *); int typeSize; int type; ushort column; ushort line; }; - struct StoreMetaInstruction { + struct instr_storeMeta { + QML_INSTR_HEADER int data; int aliasData; int propertyCache; }; - struct SetIdInstruction { + struct instr_setId { + QML_INSTR_HEADER int value; int index; }; - struct AssignValueSourceInstruction { + struct instr_assignValueSource { + QML_INSTR_HEADER int property; int owner; int castValue; }; - struct AssignValueInterceptorInstruction { + struct instr_assignValueInterceptor { + QML_INSTR_HEADER int property; int owner; int castValue; }; - struct AssignBindingInstruction { + struct instr_assignBinding { + QML_INSTR_HEADER unsigned int property; int value; short context; short owner; ushort line; }; - struct FetchInstruction { + struct instr_fetch { + QML_INSTR_HEADER int property; ushort line; }; - struct FetchValueInstruction { + struct instr_fetchValue { + QML_INSTR_HEADER int property; int type; quint32 bindingSkipList; }; - struct FetchQmlListInstruction { + struct instr_fetchQmlList { + QML_INSTR_HEADER int property; int type; }; - struct BeginInstruction { + struct instr_begin { + QML_INSTR_HEADER int castValue; }; - struct StoreFloatInstruction { + struct instr_storeFloat { + QML_INSTR_HEADER int propertyIndex; float value; }; - struct StoreDoubleInstruction { + struct instr_storeDouble { + QML_INSTR_HEADER int propertyIndex; double value; }; - struct StoreIntegerInstruction { + struct instr_storeInteger { + QML_INSTR_HEADER int propertyIndex; int value; }; - struct StoreBoolInstruction { + struct instr_storeBool { + QML_INSTR_HEADER int propertyIndex; bool value; }; - struct StoreStringInstruction { + struct instr_storeString { + QML_INSTR_HEADER int propertyIndex; int value; }; - struct StoreByteArrayInstruction { + struct instr_storeByteArray { + QML_INSTR_HEADER int propertyIndex; int value; }; - struct StoreScriptStringInstruction { + struct instr_storeScriptString { + QML_INSTR_HEADER int propertyIndex; int value; int scope; }; - struct StoreScriptInstruction { + struct instr_storeScript { + QML_INSTR_HEADER int value; }; - struct StoreUrlInstruction { + struct instr_storeUrl { + QML_INSTR_HEADER int propertyIndex; int value; }; - struct StoreColorInstruction { + struct instr_storeColor { + QML_INSTR_HEADER int propertyIndex; unsigned int value; }; - struct StoreDateInstruction { + struct instr_storeDate { + QML_INSTR_HEADER int propertyIndex; int value; }; - struct StoreTimeInstruction { + struct instr_storeTime { + QML_INSTR_HEADER int propertyIndex; int valueIndex; }; - struct StoreDateTimeInstruction { + struct instr_storeDateTime { + QML_INSTR_HEADER int propertyIndex; int valueIndex; }; - struct StoreRealPairInstruction { + struct instr_storeRealPair { + QML_INSTR_HEADER int propertyIndex; int valueIndex; }; - struct StoreRectInstruction { + struct instr_storeRect { + QML_INSTR_HEADER int propertyIndex; int valueIndex; }; - struct StoreVector3DInstruction { + struct instr_storeVector3D { + QML_INSTR_HEADER int propertyIndex; int valueIndex; }; - struct StoreObjectInstruction { + struct instr_storeObject { + QML_INSTR_HEADER int propertyIndex; ushort line; }; - struct AssignCustomTypeInstruction { + struct instr_assignCustomType { + QML_INSTR_HEADER int propertyIndex; int valueIndex; ushort line; }; - struct StoreSignalInstruction { + struct instr_storeSignal { + QML_INSTR_HEADER int signalIndex; int value; short context; int name; ushort line; }; - struct AssignSignalObjectInstruction { + struct instr_assignSignalObject { + QML_INSTR_HEADER int signal; ushort line; }; - struct CreateComponentInstruction { + struct instr_createComponent { + QML_INSTR_HEADER int count; int endLine; int metaObject; ushort column; ushort line; }; - struct FetchAttachedInstruction { + struct instr_fetchAttached { + QML_INSTR_HEADER int id; ushort line; }; - struct DeferInstruction { + struct instr_defer { + QML_INSTR_HEADER int deferCount; }; - struct AssignObjectListInstruction { + struct instr_assignObjectList { + QML_INSTR_HEADER ushort line; }; - union { - InitInstruction init; - CreateInstruction create; - CreateSimpleInstruction createSimple; - StoreMetaInstruction storeMeta; - SetIdInstruction setId; - AssignValueSourceInstruction assignValueSource; - AssignValueInterceptorInstruction assignValueInterceptor; - AssignBindingInstruction assignBinding; - FetchInstruction fetch; - FetchValueInstruction fetchValue; - FetchQmlListInstruction fetchQmlList; - BeginInstruction begin; - StoreFloatInstruction storeFloat; - StoreDoubleInstruction storeDouble; - StoreIntegerInstruction storeInteger; - StoreBoolInstruction storeBool; - StoreStringInstruction storeString; - StoreByteArrayInstruction storeByteArray; - StoreScriptStringInstruction storeScriptString; - StoreScriptInstruction storeScript; - StoreUrlInstruction storeUrl; - StoreColorInstruction storeColor; - StoreDateInstruction storeDate; - StoreTimeInstruction storeTime; - StoreDateTimeInstruction storeDateTime; - StoreRealPairInstruction storeRealPair; - StoreRectInstruction storeRect; - StoreVector3DInstruction storeVector3D; - StoreObjectInstruction storeObject; - AssignCustomTypeInstruction assignCustomType; - StoreSignalInstruction storeSignal; - AssignSignalObjectInstruction assignSignalObject; - CreateComponentInstruction createComponent; - FetchAttachedInstruction fetchAttached; - DeferInstruction defer; - AssignObjectListInstruction assignObjectList; - }; + instr_common common; + instr_init init; + instr_create create; + 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_storeByteArray storeByteArray; + instr_storeScriptString storeScriptString; + instr_storeScript storeScript; + instr_storeUrl storeUrl; + instr_storeColor storeColor; + instr_storeDate storeDate; + instr_storeTime storeTime; + instr_storeDateTime storeDateTime; + instr_storeRealPair storeRealPair; + instr_storeRect storeRect; + instr_storeVector3D storeVector3D; + instr_storeObject storeObject; + instr_assignCustomType assignCustomType; + instr_storeSignal storeSignal; + instr_assignSignalObject assignSignalObject; + instr_createComponent createComponent; + instr_fetchAttached fetchAttached; + instr_defer defer; + instr_assignObjectList assignObjectList; - void dump(QDeclarativeCompiledData *); + int size() const; }; +template +struct QDeclarativeInstructionMeta { +}; + +#define QML_INSTR_META_TEMPLATE(I, FMT) \ + template<> struct QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I> { \ + enum { Size = QML_INSTR_SIZE(I, FMT) }; \ + typedef QDeclarativeInstruction::instr_##FMT DataType; \ + static const DataType &data(const QDeclarativeInstruction &instr) { return instr.FMT; } \ + }; +FOR_EACH_QML_INSTR(QML_INSTR_META_TEMPLATE); +#undef QML_INSTR_META_TEMPLATE + QT_END_NAMESPACE #endif // QDECLARATIVEINSTRUCTION_P_H diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index af29991858..03abae73a7 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -102,14 +102,13 @@ struct ListInstance }; QObject *QDeclarativeVME::run(QDeclarativeContextData *ctxt, QDeclarativeCompiledData *comp, - int start, int count, const QBitField &bindingSkipList) + int start, const QBitField &bindingSkipList) { QDeclarativeVMEStack stack; if (start == -1) start = 0; - if (count == -1) count = comp->bytecode.count(); - return run(stack, ctxt, comp, start, count, bindingSkipList); + return run(stack, ctxt, comp, start, bindingSkipList); } void QDeclarativeVME::runDeferred(QObject *object) @@ -121,12 +120,11 @@ void QDeclarativeVME::runDeferred(QObject *object) QDeclarativeContextData *ctxt = data->context; QDeclarativeCompiledData *comp = data->deferredComponent; - int start = data->deferredIdx + 1; - int count = data->deferredComponent->bytecode.at(data->deferredIdx).defer.deferCount; + int start = data->deferredIdx; QDeclarativeVMEStack stack; stack.push(object); - run(stack, ctxt, comp, start, count, QBitField()); + run(stack, ctxt, comp, start, QBitField()); } inline bool fastHasBinding(QObject *o, int index) @@ -143,13 +141,20 @@ static void removeBindingOnProperty(QObject *o, int index) if (binding) binding->destroy(); } +#define QML_BEGIN_INSTR(I) \ + case QDeclarativeInstruction::I: { \ + const QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::DataType &instr = QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::data(genericInstr); \ + instructionStream += QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::Size; \ + Q_UNUSED(instr); + +#define QML_END_INSTR(I) } break; + #define CLEAN_PROPERTY(o, index) if (fastHasBinding(o, index)) removeBindingOnProperty(o, index) QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QDeclarativeContextData *ctxt, QDeclarativeCompiledData *comp, - int start, int count, - const QBitField &bindingSkipList) + int start, const QBitField &bindingSkipList) { Q_ASSERT(comp); Q_ASSERT(ctxt); @@ -175,830 +180,746 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite; - for (int ii = start; !isError() && ii < (start + count); ++ii) { - const QDeclarativeInstruction &instr = comp->bytecode.at(ii); - - switch(instr.type) { - case QDeclarativeInstruction::Init: - { - if (instr.init.bindingsSize) - bindValues = QDeclarativeEnginePrivate::SimpleList(instr.init.bindingsSize); - if (instr.init.parserStatusSize) - parserStatus = QDeclarativeEnginePrivate::SimpleList(instr.init.parserStatusSize); - if (instr.init.contextCache != -1) - ctxt->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache)); - if (instr.init.compiledBinding != -1) - ctxt->optimizedBindings = new QDeclarativeV4Bindings(datas.at(instr.init.compiledBinding).constData(), ctxt); - } - break; - - case QDeclarativeInstruction::CreateObject: - { - QBitField bindings; - if (instr.create.bindingBits != -1) { - const QByteArray &bits = datas.at(instr.create.bindingBits); - bindings = QBitField((const quint32*)bits.constData(), - bits.size() * 8); - } - if (stack.isEmpty()) - bindings = bindings.united(bindingSkipList); - - QObject *o = - types.at(instr.create.type).createInstance(ctxt, bindings, &vmeErrors); - - if (!o) { - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.create.type).className)), instr.create.line); - } - - QDeclarativeData *ddata = QDeclarativeData::get(o); - Q_ASSERT(ddata); - - if (stack.isEmpty()) { - if (ddata->context) { - Q_ASSERT(ddata->context != ctxt); - Q_ASSERT(ddata->outerContext); - Q_ASSERT(ddata->outerContext != ctxt); - QDeclarativeContextData *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.create.line; - ddata->columnNumber = instr.create.column; - - if (instr.create.data != -1) { - QDeclarativeCustomParser *customParser = - types.at(instr.create.type).type->customParser(); - customParser->setCustomData(o, datas.at(instr.create.data)); - } - if (!stack.isEmpty()) { - QObject *parent = stack.top(); - if (o->isWidgetType()) { - QWidget *widget = static_cast(o); - if (parent->isWidgetType()) { - QWidget *parentWidget = static_cast(parent); - widget->setParent(parentWidget); - } else { - // TODO: parent might be a layout - } - } else { - QDeclarative_setParent_noEvent(o, parent); - } - } - stack.push(o); - } - break; - - case QDeclarativeInstruction::CreateSimpleObject: - { - QObject *o = (QObject *)operator new(instr.createSimple.typeSize + - sizeof(QDeclarativeData)); - ::memset(o, 0, instr.createSimple.typeSize + sizeof(QDeclarativeData)); - instr.createSimple.create(o); - - QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.createSimple.typeSize); - const QDeclarativeCompiledData::TypeReference &ref = types.at(instr.createSimple.type); - if (!ddata->propertyCache && ref.typePropertyCache) { - ddata->propertyCache = ref.typePropertyCache; - ddata->propertyCache->addref(); - } - ddata->lineNumber = instr.createSimple.line; - ddata->columnNumber = instr.createSimple.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 = stack.top(); - QDeclarative_setParent_noEvent(o, parent); - - stack.push(o); - } - break; - - case QDeclarativeInstruction::SetId: - { - QObject *target = stack.top(); - ctxt->setIdProperty(instr.setId.index, target); + const char *instructionStream = comp->bytecode.constData() + start; + + bool done = false; + while (!isError() && !done) { + const QDeclarativeInstruction &genericInstr = *((QDeclarativeInstruction *)instructionStream); + + switch(genericInstr.type()) { + QML_BEGIN_INSTR(Init) + if (instr.bindingsSize) + bindValues = QDeclarativeEnginePrivate::SimpleList(instr.bindingsSize); + if (instr.parserStatusSize) + parserStatus = QDeclarativeEnginePrivate::SimpleList(instr.parserStatusSize); + if (instr.contextCache != -1) + ctxt->setIdPropertyData(comp->contextCaches.at(instr.contextCache)); + if (instr.compiledBinding != -1) + ctxt->optimizedBindings = new QDeclarativeV4Bindings(datas.at(instr.compiledBinding).constData(), ctxt); + QML_END_INSTR(Init) + + QML_BEGIN_INSTR(Done) + done = true; + QML_END_INSTR(Done) + + QML_BEGIN_INSTR(CreateObject) + QBitField bindings; + if (instr.bindingBits != -1) { + const QByteArray &bits = datas.at(instr.bindingBits); + bindings = QBitField((const quint32*)bits.constData(), + bits.size() * 8); } - break; + if (stack.isEmpty()) + bindings = bindings.united(bindingSkipList); + QObject *o = + types.at(instr.type).createInstance(ctxt, bindings, &vmeErrors); - case QDeclarativeInstruction::SetDefault: - { - ctxt->contextObject = stack.top(); + if (!o) { + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.type).className)), instr.line); } - break; - - case QDeclarativeInstruction::CreateComponent: - { - QDeclarativeComponent *qcomp = - new QDeclarativeComponent(ctxt->engine, comp, ii + 1, instr.createComponent.count, - stack.isEmpty() ? 0 : stack.top()); - - QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true); - Q_ASSERT(ddata); - - ctxt->addObject(qcomp); - - if (stack.isEmpty()) - ddata->ownContext = true; - - ddata->setImplicitDestructible(); - ddata->outerContext = ctxt; - ddata->lineNumber = instr.createComponent.line; - ddata->columnNumber = instr.createComponent.column; - - QDeclarativeComponentPrivate::get(qcomp)->creationContext = ctxt; - - stack.push(qcomp); - ii += instr.createComponent.count; - } - break; - - case QDeclarativeInstruction::StoreMetaObject: - { - QObject *target = stack.top(); - - QMetaObject mo; - const QByteArray &metadata = datas.at(instr.storeMeta.data); - QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata); - const QDeclarativeVMEMetaData *data = - (const QDeclarativeVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData(); - - (void)new QDeclarativeVMEMetaObject(target, &mo, data, comp); - - if (instr.storeMeta.propertyCache != -1) { - QDeclarativeData *ddata = QDeclarativeData::get(target, true); - if (ddata->propertyCache) ddata->propertyCache->release(); - ddata->propertyCache = propertyCaches.at(instr.storeMeta.propertyCache); - ddata->propertyCache->addref(); + QDeclarativeData *ddata = QDeclarativeData::get(o); + Q_ASSERT(ddata); + + if (stack.isEmpty()) { + if (ddata->context) { + Q_ASSERT(ddata->context != ctxt); + Q_ASSERT(ddata->outerContext); + Q_ASSERT(ddata->outerContext != ctxt); + QDeclarativeContextData *c = ddata->context; + while (c->linkedContext) c = c->linkedContext; + c->linkedContext = ctxt; + } else { + ctxt->addObject(o); } - } - break; - - case QDeclarativeInstruction::StoreVariant: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeString.propertyIndex); - - // XXX - can be more efficient - QVariant v = QDeclarativeStringConverters::variantFromString(primitives.at(instr.storeString.value)); - void *a[] = { &v, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeString.propertyIndex, a); - } - break; - - case QDeclarativeInstruction::StoreVariantInteger: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeString.propertyIndex); - - QVariant v(instr.storeInteger.value); - void *a[] = { &v, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeString.propertyIndex, a); - } - break; - - case QDeclarativeInstruction::StoreVariantDouble: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeString.propertyIndex); - - QVariant v(instr.storeDouble.value); - void *a[] = { &v, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeString.propertyIndex, a); - } - break; - - case QDeclarativeInstruction::StoreVariantBool: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeString.propertyIndex); - - QVariant v(instr.storeBool.value); - void *a[] = { &v, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeString.propertyIndex, a); - } - break; - - case QDeclarativeInstruction::StoreString: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeString.propertyIndex); - - void *a[] = { (void *)&primitives.at(instr.storeString.value), 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeString.propertyIndex, a); - } - break; - - case QDeclarativeInstruction::StoreByteArray: - { - QObject *target = stack.top(); - void *a[] = { (void *)&datas.at(instr.storeByteArray.value), 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeByteArray.propertyIndex, a); - } - break; - - case QDeclarativeInstruction::StoreUrl: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeUrl.propertyIndex); - - void *a[] = { (void *)&urls.at(instr.storeUrl.value), 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeUrl.propertyIndex, a); - } - break; - - case QDeclarativeInstruction::StoreFloat: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeFloat.propertyIndex); - - float f = instr.storeFloat.value; - void *a[] = { &f, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeFloat.propertyIndex, a); - } - break; - - case QDeclarativeInstruction::StoreDouble: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeDouble.propertyIndex); - - double d = instr.storeDouble.value; - void *a[] = { &d, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeDouble.propertyIndex, a); - } - break; - - case QDeclarativeInstruction::StoreBool: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeBool.propertyIndex); - - void *a[] = { (void *)&instr.storeBool.value, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeBool.propertyIndex, a); - } - break; - - case QDeclarativeInstruction::StoreInteger: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeInteger.propertyIndex); - - void *a[] = { (void *)&instr.storeInteger.value, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeInteger.propertyIndex, a); - } - break; - - case QDeclarativeInstruction::StoreColor: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeColor.propertyIndex); - - QColor c = QColor::fromRgba(instr.storeColor.value); - void *a[] = { &c, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeColor.propertyIndex, a); - } - break; - - case QDeclarativeInstruction::StoreDate: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeDate.propertyIndex); - - QDate d = QDate::fromJulianDay(instr.storeDate.value); - void *a[] = { &d, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeDate.propertyIndex, a); - } - break; - - case QDeclarativeInstruction::StoreTime: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeTime.propertyIndex); - - QTime t; - t.setHMS(intData.at(instr.storeTime.valueIndex), - intData.at(instr.storeTime.valueIndex+1), - intData.at(instr.storeTime.valueIndex+2), - intData.at(instr.storeTime.valueIndex+3)); - void *a[] = { &t, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeTime.propertyIndex, a); - } - break; - case QDeclarativeInstruction::StoreDateTime: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeDateTime.propertyIndex); - - QTime t; - t.setHMS(intData.at(instr.storeDateTime.valueIndex+1), - intData.at(instr.storeDateTime.valueIndex+2), - intData.at(instr.storeDateTime.valueIndex+3), - intData.at(instr.storeDateTime.valueIndex+4)); - QDateTime dt(QDate::fromJulianDay(intData.at(instr.storeDateTime.valueIndex)), t); - void *a[] = { &dt, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeDateTime.propertyIndex, a); - } - break; - - case QDeclarativeInstruction::StorePoint: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex); - - QPoint p = QPointF(floatData.at(instr.storeRealPair.valueIndex), - floatData.at(instr.storeRealPair.valueIndex+1)).toPoint(); - void *a[] = { &p, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeRealPair.propertyIndex, a); - } - break; - - case QDeclarativeInstruction::StorePointF: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex); - - QPointF p(floatData.at(instr.storeRealPair.valueIndex), - floatData.at(instr.storeRealPair.valueIndex+1)); - void *a[] = { &p, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeRealPair.propertyIndex, a); - } - break; - - case QDeclarativeInstruction::StoreSize: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex); - - QSize p = QSizeF(floatData.at(instr.storeRealPair.valueIndex), - floatData.at(instr.storeRealPair.valueIndex+1)).toSize(); - void *a[] = { &p, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeRealPair.propertyIndex, a); + ddata->ownContext = true; + } else if (!ddata->context) { + ctxt->addObject(o); } - break; - - case QDeclarativeInstruction::StoreSizeF: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex); - QSizeF s(floatData.at(instr.storeRealPair.valueIndex), - floatData.at(instr.storeRealPair.valueIndex+1)); - void *a[] = { &s, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeRealPair.propertyIndex, a); - } - break; + ddata->setImplicitDestructible(); + ddata->outerContext = ctxt; + ddata->lineNumber = instr.line; + ddata->columnNumber = instr.column; - case QDeclarativeInstruction::StoreRect: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeRect.propertyIndex); - - QRect r = QRectF(floatData.at(instr.storeRect.valueIndex), - floatData.at(instr.storeRect.valueIndex+1), - floatData.at(instr.storeRect.valueIndex+2), - floatData.at(instr.storeRect.valueIndex+3)).toRect(); - void *a[] = { &r, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeRect.propertyIndex, a); + if (instr.data != -1) { + QDeclarativeCustomParser *customParser = + types.at(instr.type).type->customParser(); + customParser->setCustomData(o, datas.at(instr.data)); } - break; - - case QDeclarativeInstruction::StoreRectF: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeRect.propertyIndex); - - QRectF r(floatData.at(instr.storeRect.valueIndex), - floatData.at(instr.storeRect.valueIndex+1), - floatData.at(instr.storeRect.valueIndex+2), - floatData.at(instr.storeRect.valueIndex+3)); - void *a[] = { &r, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeRect.propertyIndex, a); + if (!stack.isEmpty()) { + QObject *parent = stack.top(); + if (o->isWidgetType()) { + QWidget *widget = static_cast(o); + if (parent->isWidgetType()) { + QWidget *parentWidget = static_cast(parent); + widget->setParent(parentWidget); + } else { + // TODO: parent might be a layout + } + } else { + QDeclarative_setParent_noEvent(o, parent); + } } - break; - - case QDeclarativeInstruction::StoreVector3D: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeVector3D.propertyIndex); - - QVector3D p(floatData.at(instr.storeVector3D.valueIndex), - floatData.at(instr.storeVector3D.valueIndex+1), - floatData.at(instr.storeVector3D.valueIndex+2)); - void *a[] = { &p, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeVector3D.propertyIndex, a); + stack.push(o); + QML_END_INSTR(CreateObject) + + QML_BEGIN_INSTR(CreateSimpleObject) + QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QDeclarativeData)); + ::memset(o, 0, instr.typeSize + sizeof(QDeclarativeData)); + instr.create(o); + + QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.typeSize); + const QDeclarativeCompiledData::TypeReference &ref = types.at(instr.type); + if (!ddata->propertyCache && ref.typePropertyCache) { + ddata->propertyCache = ref.typePropertyCache; + ddata->propertyCache->addref(); } - break; + ddata->lineNumber = instr.line; + ddata->columnNumber = instr.column; - case QDeclarativeInstruction::StoreObject: - { - QObject *assignObj = stack.pop(); - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeObject.propertyIndex); + 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; - void *a[] = { (void *)&assignObj, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeObject.propertyIndex, a); - } - break; + QObject *parent = stack.top(); + QDeclarative_setParent_noEvent(o, parent); + stack.push(o); + QML_END_INSTR(CreateSimpleObject) - case QDeclarativeInstruction::AssignCustomType: - { - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.assignCustomType.propertyIndex); - - QDeclarativeCompiledData::CustomTypeData data = customTypeData.at(instr.assignCustomType.valueIndex); - const QString &primitive = primitives.at(data.index); - QDeclarativeMetaType::StringConverter converter = - QDeclarativeMetaType::customStringConverter(data.type); - QVariant v = (*converter)(primitive); - - QMetaProperty prop = - target->metaObject()->property(instr.assignCustomType.propertyIndex); - if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type)) - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.assignCustomType.line); - - void *a[] = { (void *)v.data(), 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.assignCustomType.propertyIndex, a); - } - break; + QML_BEGIN_INSTR(SetId) + QObject *target = stack.top(); + ctxt->setIdProperty(instr.index, target); + QML_END_INSTR(SetId) - case QDeclarativeInstruction::AssignSignalObject: - { - // XXX optimize + QML_BEGIN_INSTR(SetDefault) + ctxt->contextObject = stack.top(); + QML_END_INSTR(SetDefault) - QObject *assign = stack.pop(); - QObject *target = stack.top(); - int sigIdx = instr.assignSignalObject.signal; - const QByteArray &pr = datas.at(sigIdx); + QML_BEGIN_INSTR(CreateComponent) + QDeclarativeComponent *qcomp = + new QDeclarativeComponent(ctxt->engine, comp, instructionStream - comp->bytecode.constData(), + stack.isEmpty() ? 0 : stack.top()); - QDeclarativeProperty prop(target, QString::fromUtf8(pr)); - if (prop.type() & QDeclarativeProperty::SignalProperty) { + QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true); + Q_ASSERT(ddata); - QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign); - if (method.signature() == 0) - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())), instr.assignSignalObject.line); + ctxt->addObject(qcomp); - if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature())) - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature())), instr.assignSignalObject.line); + if (stack.isEmpty()) + ddata->ownContext = true; - QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex()); + ddata->setImplicitDestructible(); + ddata->outerContext = ctxt; + ddata->lineNumber = instr.line; + ddata->columnNumber = instr.column; - } else { - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr)), instr.assignSignalObject.line); - } + QDeclarativeComponentPrivate::get(qcomp)->creationContext = ctxt; + stack.push(qcomp); + instructionStream += instr.count; + QML_END_INSTR(CreateComponent) - } - break; - - case QDeclarativeInstruction::StoreSignal: - { - QObject *target = stack.top(); - QObject *context = stack.at(stack.count() - 1 - instr.storeSignal.context); + QML_BEGIN_INSTR(StoreMetaObject) + QObject *target = stack.top(); - QMetaMethod signal = target->metaObject()->method(instr.storeSignal.signalIndex); + QMetaObject mo; + const QByteArray &metadata = datas.at(instr.data); + QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata); - QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target); - QDeclarativeExpression *expr = - new QDeclarativeExpression(ctxt, context, primitives.at(instr.storeSignal.value)); - expr->setSourceLocation(comp->name, instr.storeSignal.line); - static_cast(QObjectPrivate::get(expr))->name = datas.at(instr.storeSignal.name); - bs->setExpression(expr); - } - break; + const QDeclarativeVMEMetaData *data = + (const QDeclarativeVMEMetaData *)datas.at(instr.aliasData).constData(); - case QDeclarativeInstruction::StoreImportedScript: - { - ctxt->importedScripts << run(ctxt, scripts.at(instr.storeScript.value)); - } - break; + (void)new QDeclarativeVMEMetaObject(target, &mo, data, comp); - case QDeclarativeInstruction::StoreScriptString: - { - QObject *target = stack.top(); - QObject *scope = stack.at(stack.count() - 1 - instr.storeScriptString.scope); - QDeclarativeScriptString ss; - ss.setContext(ctxt->asQDeclarativeContext()); - ss.setScopeObject(scope); - ss.setScript(primitives.at(instr.storeScriptString.value)); - - void *a[] = { &ss, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeScriptString.propertyIndex, a); + if (instr.propertyCache != -1) { + QDeclarativeData *ddata = QDeclarativeData::get(target, true); + if (ddata->propertyCache) ddata->propertyCache->release(); + ddata->propertyCache = propertyCaches.at(instr.propertyCache); + ddata->propertyCache->addref(); } - break; - - case QDeclarativeInstruction::BeginObject: - { - QObject *target = stack.top(); - QDeclarativeParserStatus *status = reinterpret_cast(reinterpret_cast(target) + instr.begin.castValue); - parserStatus.append(status); - status->d = &parserStatus.values[parserStatus.count - 1]; - - status->classBegin(); + QML_END_INSTR(StoreMetaObject) + + QML_BEGIN_INSTR(StoreVariant) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + // XXX - can be more efficient + QVariant v = QDeclarativeStringConverters::variantFromString(primitives.at(instr.value)); + void *a[] = { &v, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreVariant) + + QML_BEGIN_INSTR(StoreVariantInteger) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + QVariant v(instr.value); + void *a[] = { &v, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreVariantInteger) + + QML_BEGIN_INSTR(StoreVariantDouble) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + QVariant v(instr.value); + void *a[] = { &v, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreVariantDouble) + + QML_BEGIN_INSTR(StoreVariantBool) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + QVariant v(instr.value); + void *a[] = { &v, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreVariantBool) + + QML_BEGIN_INSTR(StoreString) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + void *a[] = { (void *)&primitives.at(instr.value), 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreString) + + QML_BEGIN_INSTR(StoreByteArray) + QObject *target = stack.top(); + void *a[] = { (void *)&datas.at(instr.value), 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreByteArray) + + QML_BEGIN_INSTR(StoreUrl) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + void *a[] = { (void *)&urls.at(instr.value), 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreUrl) + + QML_BEGIN_INSTR(StoreFloat) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + float f = instr.value; + void *a[] = { &f, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreFloat) + + QML_BEGIN_INSTR(StoreDouble) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + double d = instr.value; + void *a[] = { &d, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreDouble) + + QML_BEGIN_INSTR(StoreBool) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + void *a[] = { (void *)&instr.value, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreBool) + + QML_BEGIN_INSTR(StoreInteger) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + void *a[] = { (void *)&instr.value, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreInteger) + + QML_BEGIN_INSTR(StoreColor) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + QColor c = QColor::fromRgba(instr.value); + void *a[] = { &c, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreColor) + + QML_BEGIN_INSTR(StoreDate) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + QDate d = QDate::fromJulianDay(instr.value); + void *a[] = { &d, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreDate) + + QML_BEGIN_INSTR(StoreTime) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + QTime t; + t.setHMS(intData.at(instr.valueIndex), + intData.at(instr.valueIndex+1), + intData.at(instr.valueIndex+2), + intData.at(instr.valueIndex+3)); + void *a[] = { &t, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreTime) + + QML_BEGIN_INSTR(StoreDateTime) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + QTime t; + t.setHMS(intData.at(instr.valueIndex+1), + intData.at(instr.valueIndex+2), + intData.at(instr.valueIndex+3), + intData.at(instr.valueIndex+4)); + QDateTime dt(QDate::fromJulianDay(intData.at(instr.valueIndex)), t); + void *a[] = { &dt, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreDateTime) + + QML_BEGIN_INSTR(StorePoint) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + QPoint p = QPointF(floatData.at(instr.valueIndex), + floatData.at(instr.valueIndex+1)).toPoint(); + void *a[] = { &p, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StorePoint) + + QML_BEGIN_INSTR(StorePointF) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + QPointF p(floatData.at(instr.valueIndex), + floatData.at(instr.valueIndex+1)); + void *a[] = { &p, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StorePointF) + + QML_BEGIN_INSTR(StoreSize) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + QSize p = QSizeF(floatData.at(instr.valueIndex), + floatData.at(instr.valueIndex+1)).toSize(); + void *a[] = { &p, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreSize) + + QML_BEGIN_INSTR(StoreSizeF) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + QSizeF s(floatData.at(instr.valueIndex), + floatData.at(instr.valueIndex+1)); + void *a[] = { &s, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreSizeF) + + QML_BEGIN_INSTR(StoreRect) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + QRect r = QRectF(floatData.at(instr.valueIndex), + floatData.at(instr.valueIndex+1), + floatData.at(instr.valueIndex+2), + floatData.at(instr.valueIndex+3)).toRect(); + void *a[] = { &r, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreRect) + + QML_BEGIN_INSTR(StoreRectF) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + QRectF r(floatData.at(instr.valueIndex), + floatData.at(instr.valueIndex+1), + floatData.at(instr.valueIndex+2), + floatData.at(instr.valueIndex+3)); + void *a[] = { &r, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreRectF) + + QML_BEGIN_INSTR(StoreVector3D) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + QVector3D p(floatData.at(instr.valueIndex), + floatData.at(instr.valueIndex+1), + floatData.at(instr.valueIndex+2)); + void *a[] = { &p, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreVector3D) + + QML_BEGIN_INSTR(StoreObject) + QObject *assignObj = stack.pop(); + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + void *a[] = { (void *)&assignObj, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreObject) + + QML_BEGIN_INSTR(AssignCustomType) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + QDeclarativeCompiledData::CustomTypeData data = customTypeData.at(instr.valueIndex); + const QString &primitive = primitives.at(data.index); + QDeclarativeMetaType::StringConverter converter = + QDeclarativeMetaType::customStringConverter(data.type); + QVariant v = (*converter)(primitive); + + QMetaProperty prop = + target->metaObject()->property(instr.propertyIndex); + if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type)) + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","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 = stack.pop(); + QObject *target = stack.top(); + int sigIdx = instr.signal; + const QByteArray &pr = datas.at(sigIdx); + + QDeclarativeProperty prop(target, QString::fromUtf8(pr)); + if (prop.type() & QDeclarativeProperty::SignalProperty) { + + QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign); + if (method.signature() == 0) + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())), instr.line); + + if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature())) + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature())), instr.line); + + QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex()); + + } else { + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr)), instr.line); } - break; - - case QDeclarativeInstruction::StoreBinding: - case QDeclarativeInstruction::StoreBindingOnAlias: - { - QObject *target = - stack.at(stack.count() - 1 - instr.assignBinding.owner); - QObject *context = - stack.at(stack.count() - 1 - instr.assignBinding.context); - - QDeclarativeProperty mp = - QDeclarativePropertyPrivate::restore(datas.at(instr.assignBinding.property), target, ctxt); - int coreIndex = mp.index(); - if ((stack.count() - instr.assignBinding.owner) == 1 && bindingSkipList.testBit(coreIndex)) - break; - - QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, comp->name, instr.assignBinding.line, 0); - bindValues.append(bind); - bind->m_mePtr = &bindValues.values[bindValues.count - 1]; - bind->setTarget(mp); - - if (instr.type == QDeclarativeInstruction::StoreBindingOnAlias) { - QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind); - if (old) { old->destroy(); } - } else { - bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp)); + QML_END_INSTR(AssignSignalObject) + + QML_BEGIN_INSTR(StoreSignal) + QObject *target = stack.top(); + QObject *context = stack.at(stack.count() - 1 - instr.context); + + QMetaMethod signal = target->metaObject()->method(instr.signalIndex); + + QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target); + QDeclarativeExpression *expr = + new QDeclarativeExpression(ctxt, context, primitives.at(instr.value)); + expr->setSourceLocation(comp->name, instr.line); + static_cast(QObjectPrivate::get(expr))->name = datas.at(instr.name); + bs->setExpression(expr); + QML_END_INSTR(StoreSignal) + + QML_BEGIN_INSTR(StoreImportedScript) + ctxt->importedScripts << run(ctxt, scripts.at(instr.value)); + QML_END_INSTR(StoreImportedScript) + + QML_BEGIN_INSTR(StoreScriptString) + QObject *target = stack.top(); + QObject *scope = stack.at(stack.count() - 1 - instr.scope); + QDeclarativeScriptString ss; + ss.setContext(ctxt->asQDeclarativeContext()); + ss.setScopeObject(scope); + ss.setScript(primitives.at(instr.value)); + + void *a[] = { &ss, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreScriptString) + + QML_BEGIN_INSTR(BeginObject) + QObject *target = stack.top(); + QDeclarativeParserStatus *status = reinterpret_cast(reinterpret_cast(target) + instr.castValue); + parserStatus.append(status); + status->d = &parserStatus.values[parserStatus.count - 1]; + + status->classBegin(); + QML_END_INSTR(BeginObject) + + QML_BEGIN_INSTR(StoreBinding) + QObject *target = + stack.at(stack.count() - 1 - instr.owner); + QObject *context = + stack.at(stack.count() - 1 - instr.context); + + QDeclarativeProperty mp = + QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt); + + int coreIndex = mp.index(); + + if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex)) + break; + + QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.value).constData(), comp, context, ctxt, comp->name, instr.line, 0); + bindValues.append(bind); + bind->m_mePtr = &bindValues.values[bindValues.count - 1]; + bind->setTarget(mp); + + bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp)); + QML_END_INSTR(StoreBinding) + + QML_BEGIN_INSTR(StoreBindingOnAlias) + QObject *target = + stack.at(stack.count() - 1 - instr.owner); + QObject *context = + stack.at(stack.count() - 1 - instr.context); + + QDeclarativeProperty mp = + QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt); + + int coreIndex = mp.index(); + + if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex)) + break; + + QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.value).constData(), comp, context, ctxt, comp->name, instr.line, 0); + bindValues.append(bind); + bind->m_mePtr = &bindValues.values[bindValues.count - 1]; + bind->setTarget(mp); + + QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind); + if (old) { old->destroy(); } + QML_END_INSTR(StoreBindingOnAlias) + + QML_BEGIN_INSTR(StoreCompiledBinding) + QObject *target = + stack.at(stack.count() - 1 - instr.owner); + QObject *scope = + stack.at(stack.count() - 1 - instr.context); + + int property = instr.property; + if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF)) + break; + + QDeclarativeAbstractBinding *binding = + ctxt->optimizedBindings->configBinding(instr.value, target, scope, property); + bindValues.append(binding); + binding->m_mePtr = &bindValues.values[bindValues.count - 1]; + binding->addToObject(target, property); + QML_END_INSTR(StoreCompiledBinding) + + QML_BEGIN_INSTR(StoreValueSource) + QObject *obj = stack.pop(); + QDeclarativePropertyValueSource *vs = reinterpret_cast(reinterpret_cast(obj) + instr.castValue); + QObject *target = stack.at(stack.count() - 1 - instr.owner); + + QDeclarativeProperty prop = + QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt); + obj->setParent(target); + vs->setTarget(prop); + QML_END_INSTR(StoreValueSource) + + QML_BEGIN_INSTR(StoreValueInterceptor) + QObject *obj = stack.pop(); + QDeclarativePropertyValueInterceptor *vi = reinterpret_cast(reinterpret_cast(obj) + instr.castValue); + QObject *target = stack.at(stack.count() - 1 - instr.owner); + QDeclarativeProperty prop = + QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt); + obj->setParent(target); + vi->setTarget(prop); + QDeclarativeVMEMetaObject *mo = static_cast((QMetaObject*)target->metaObject()); + mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi); + QML_END_INSTR(StoreValueInterceptor) + + QML_BEGIN_INSTR(StoreObjectQList) + QObject *assign = stack.pop(); + + const ListInstance &list = qliststack.top(); + list.qListProperty.append((QDeclarativeListProperty*)&list.qListProperty, assign); + QML_END_INSTR(StoreObjectQList) + + QML_BEGIN_INSTR(AssignObjectList) + // This is only used for assigning interfaces + QObject *assign = stack.pop(); + const ListInstance &list = qliststack.top(); + + int type = list.type; + + void *ptr = 0; + + const char *iid = QDeclarativeMetaType::interfaceIId(type); + if (iid) + ptr = assign->qt_metacast(iid); + if (!ptr) + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list"), instr.line); + + + list.qListProperty.append((QDeclarativeListProperty*)&list.qListProperty, ptr); + QML_END_INSTR(AssignObjectList) + + QML_BEGIN_INSTR(StoreVariantObject) + QObject *assign = stack.pop(); + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + QVariant v = QVariant::fromValue(assign); + void *a[] = { &v, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreVariantObject) + + QML_BEGIN_INSTR(StoreInterface) + QObject *assign = stack.pop(); + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + int coreIdx = instr.propertyIndex; + QMetaProperty prop = target->metaObject()->property(coreIdx); + int t = prop.userType(); + const char *iid = QDeclarativeMetaType::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; } - } - break; + } - case QDeclarativeInstruction::StoreCompiledBinding: - { - QObject *target = - stack.at(stack.count() - 1 - instr.assignBinding.owner); - QObject *scope = - stack.at(stack.count() - 1 - instr.assignBinding.context); - - int property = instr.assignBinding.property; - if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF)) - break; - - QDeclarativeAbstractBinding *binding = - ctxt->optimizedBindings->configBinding(instr.assignBinding.value, target, scope, property); - bindValues.append(binding); - binding->m_mePtr = &bindValues.values[bindValues.count - 1]; - binding->addToObject(target, property); - } - break; + if (!ok) + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property"), instr.line); + QML_END_INSTR(StoreInterface) + + QML_BEGIN_INSTR(FetchAttached) + QObject *target = stack.top(); - case QDeclarativeInstruction::StoreValueSource: - { - QObject *obj = stack.pop(); - QDeclarativePropertyValueSource *vs = reinterpret_cast(reinterpret_cast(obj) + instr.assignValueSource.castValue); - QObject *target = stack.at(stack.count() - 1 - instr.assignValueSource.owner); + QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.id, target); - QDeclarativeProperty prop = - QDeclarativePropertyPrivate::restore(datas.at(instr.assignValueSource.property), target, ctxt); - obj->setParent(target); - vs->setTarget(prop); - } - break; + if (!qmlObject) + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object"), instr.line); - case QDeclarativeInstruction::StoreValueInterceptor: - { - QObject *obj = stack.pop(); - QDeclarativePropertyValueInterceptor *vi = reinterpret_cast(reinterpret_cast(obj) + instr.assignValueInterceptor.castValue); - QObject *target = stack.at(stack.count() - 1 - instr.assignValueInterceptor.owner); - QDeclarativeProperty prop = - QDeclarativePropertyPrivate::restore(datas.at(instr.assignValueInterceptor.property), target, ctxt); - obj->setParent(target); - vi->setTarget(prop); - QDeclarativeVMEMetaObject *mo = static_cast((QMetaObject*)target->metaObject()); - mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi); - } - break; + stack.push(qmlObject); + QML_END_INSTR(FetchAttached) - case QDeclarativeInstruction::StoreObjectQList: - { - QObject *assign = stack.pop(); + QML_BEGIN_INSTR(FetchQList) + QObject *target = stack.top(); - const ListInstance &list = qliststack.top(); - list.qListProperty.append((QDeclarativeListProperty*)&list.qListProperty, assign); - } - break; + qliststack.push(ListInstance(instr.type)); - case QDeclarativeInstruction::AssignObjectList: - { - // This is only used for assigning interfaces - QObject *assign = stack.pop(); - const ListInstance &list = qliststack.top(); + void *a[1]; + a[0] = (void *)&(qliststack.top().qListProperty); + QMetaObject::metacall(target, QMetaObject::ReadProperty, + instr.property, a); + QML_END_INSTR(FetchQList) - int type = list.type; + QML_BEGIN_INSTR(FetchObject) + QObject *target = stack.top(); - void *ptr = 0; + 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); - const char *iid = QDeclarativeMetaType::interfaceIId(type); - if (iid) - ptr = assign->qt_metacast(iid); - if (!ptr) - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list"), instr.assignObjectList.line); + if (!obj) + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.property).name())), instr.line); + stack.push(obj); + QML_END_INSTR(FetchObject) - list.qListProperty.append((QDeclarativeListProperty*)&list.qListProperty, ptr); - } - break; + QML_BEGIN_INSTR(PopQList) + qliststack.pop(); + QML_END_INSTR(PopQList) - case QDeclarativeInstruction::StoreVariantObject: - { - QObject *assign = stack.pop(); + QML_BEGIN_INSTR(Defer) + if (instr.deferCount) { QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeObject.propertyIndex); - - QVariant v = QVariant::fromValue(assign); - void *a[] = { &v, 0, &status, &flags }; - QMetaObject::metacall(target, QMetaObject::WriteProperty, - instr.storeObject.propertyIndex, a); + QDeclarativeData *data = + QDeclarativeData::get(target, true); + comp->addref(); + data->deferredComponent = comp; + data->deferredIdx = instructionStream - comp->bytecode.constData(); + instructionStream += instr.deferCount; } - break; - - case QDeclarativeInstruction::StoreInterface: - { - QObject *assign = stack.pop(); - QObject *target = stack.top(); - CLEAN_PROPERTY(target, instr.storeObject.propertyIndex); - - int coreIdx = instr.storeObject.propertyIndex; - QMetaProperty prop = target->metaObject()->property(coreIdx); - int t = prop.userType(); - const char *iid = QDeclarativeMetaType::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; + QML_END_INSTR(Defer) + + QML_BEGIN_INSTR(PopFetchedObject) + stack.pop(); + QML_END_INSTR(PopFetchedObject) + + QML_BEGIN_INSTR(FetchValueType) + QObject *target = stack.top(); + + if (instr.bindingSkipList != 0) { + // Possibly need to clear bindings + QDeclarativeData *targetData = QDeclarativeData::get(target); + if (targetData) { + QDeclarativeAbstractBinding *binding = + QDeclarativePropertyPrivate::binding(target, instr.property, -1); + + if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) { + QDeclarativePropertyPrivate::setBinding(target, instr.property, -1, 0); + binding->destroy(); + } else if (binding) { + QDeclarativeValueTypeProxyBinding *proxy = + static_cast(binding); + proxy->removeBindings(instr.bindingSkipList); } - } - - if (!ok) - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property"), instr.storeObject.line); - } - break; - - case QDeclarativeInstruction::FetchAttached: - { - QObject *target = stack.top(); - - QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.fetchAttached.id, target); - - if (!qmlObject) - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object"), instr.fetchAttached.line); - - stack.push(qmlObject); - } - break; - - case QDeclarativeInstruction::FetchQList: - { - QObject *target = stack.top(); - - qliststack.push(ListInstance(instr.fetchQmlList.type)); - - void *a[1]; - a[0] = (void *)&(qliststack.top().qListProperty); - QMetaObject::metacall(target, QMetaObject::ReadProperty, - instr.fetchQmlList.property, a); - } - break; - - case QDeclarativeInstruction::FetchObject: - { - QObject *target = stack.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.fetch.property, a); - - if (!obj) - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.fetch.property).name())), instr.fetch.line); - - stack.push(obj); - } - break; - - case QDeclarativeInstruction::PopQList: - { - qliststack.pop(); - } - break; - - case QDeclarativeInstruction::Defer: - { - if (instr.defer.deferCount) { - QObject *target = stack.top(); - QDeclarativeData *data = - QDeclarativeData::get(target, true); - comp->addref(); - data->deferredComponent = comp; - data->deferredIdx = ii; - ii += instr.defer.deferCount; } } - break; - - case QDeclarativeInstruction::PopFetchedObject: - { - stack.pop(); - } - break; - - case QDeclarativeInstruction::FetchValueType: - { - QObject *target = stack.top(); - - if (instr.fetchValue.bindingSkipList != 0) { - // Possibly need to clear bindings - QDeclarativeData *targetData = QDeclarativeData::get(target); - if (targetData) { - QDeclarativeAbstractBinding *binding = - QDeclarativePropertyPrivate::binding(target, instr.fetchValue.property, -1); - - if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) { - QDeclarativePropertyPrivate::setBinding(target, instr.fetchValue.property, -1, 0); - binding->destroy(); - } else if (binding) { - QDeclarativeValueTypeProxyBinding *proxy = - static_cast(binding); - proxy->removeBindings(instr.fetchValue.bindingSkipList); - } - } - } - QDeclarativeValueType *valueHandler = ep->valueTypes[instr.fetchValue.type]; - valueHandler->read(target, instr.fetchValue.property); - stack.push(valueHandler); - } - break; + QDeclarativeValueType *valueHandler = ep->valueTypes[instr.type]; + valueHandler->read(target, instr.property); + stack.push(valueHandler); + QML_END_INSTR(FetchValueType) - case QDeclarativeInstruction::PopValueType: - { - QDeclarativeValueType *valueHandler = - static_cast(stack.pop()); - QObject *target = stack.top(); - valueHandler->write(target, instr.fetchValue.property, - QDeclarativePropertyPrivate::BypassInterceptor); - } - break; + QML_BEGIN_INSTR(PopValueType) + QDeclarativeValueType *valueHandler = + static_cast(stack.pop()); + QObject *target = stack.top(); + valueHandler->write(target, instr.property, QDeclarativePropertyPrivate::BypassInterceptor); + QML_END_INSTR(PopValueType) default: - qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", instr.type); + qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", genericInstr.type()); break; } } @@ -1061,7 +982,7 @@ QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData return rv; } else { Q_ASSERT(component); - return QDeclarativeComponentPrivate::begin(ctxt, 0, component, -1, -1, 0, errors, bindings); + return QDeclarativeComponentPrivate::begin(ctxt, 0, component, -1, 0, errors, bindings); } } diff --git a/src/declarative/qml/qdeclarativevme_p.h b/src/declarative/qml/qdeclarativevme_p.h index 4c010f19d8..40343b2f19 100644 --- a/src/declarative/qml/qdeclarativevme_p.h +++ b/src/declarative/qml/qdeclarativevme_p.h @@ -64,7 +64,6 @@ QT_BEGIN_NAMESPACE class QObject; class QScriptValue; class QDeclarativeScriptData; -class QDeclarativeInstruction; class QDeclarativeCompiledData; class QDeclarativeCompiledData; class QDeclarativeContextData; @@ -103,8 +102,7 @@ public: QDeclarativeVME(); QObject *run(QDeclarativeContextData *, QDeclarativeCompiledData *, - int start = -1, int count = -1, - const QBitField & = QBitField()); + int start = -1, const QBitField & = QBitField()); QScriptValue run(QDeclarativeContextData *, QDeclarativeScriptData *); void runDeferred(QObject *); @@ -115,8 +113,7 @@ public: private: QObject *run(QDeclarativeVMEStack &, QDeclarativeContextData *, QDeclarativeCompiledData *, - int start, int count, - const QBitField &); + int start, const QBitField &); QList vmeErrors; }; diff --git a/src/declarative/qml/v4/qdeclarativev4bindings.cpp b/src/declarative/qml/v4/qdeclarativev4bindings.cpp index 80c7a68697..5ef293de89 100644 --- a/src/declarative/qml/v4/qdeclarativev4bindings.cpp +++ b/src/declarative/qml/v4/qdeclarativev4bindings.cpp @@ -774,7 +774,7 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, #ifdef QML_THREADED_INTERPRETER if (table) { static void *decode_instr[] = { - FOR_EACH_QML_INSTR(QML_INSTR_ADDR) + FOR_EACH_V4_INSTR(QML_V4_INSTR_ADDR) }; *table = decode_instr; @@ -792,7 +792,7 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(context->engine); const char *code = program->instructions(); - code += instrIndex * QML_INSTR_SIZE(Jump, jump); + code += instrIndex * QML_V4_INSTR_SIZE(Jump, jump); const Instr *instr = (const Instr *) code; const char *data = program->data(); @@ -809,28 +809,28 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, switch (instr->common.type) { #endif - QML_BEGIN_INSTR(Noop, common) - QML_END_INSTR(Noop, common) + QML_V4_BEGIN_INSTR(Noop, common) + QML_V4_END_INSTR(Noop, common) - QML_BEGIN_INSTR(BindingId, id) + QML_V4_BEGIN_INSTR(BindingId, id) bindingLine = instr->id.line; bindingColumn = instr->id.column; - QML_END_INSTR(BindingId, id) + QML_V4_END_INSTR(BindingId, id) - QML_BEGIN_INSTR(SubscribeId, subscribeop) + QML_V4_BEGIN_INSTR(SubscribeId, subscribeop) subscribeId(context, instr->subscribeop.index, instr->subscribeop.offset); - QML_END_INSTR(SubscribeId, subscribeop) + QML_V4_END_INSTR(SubscribeId, subscribeop) - QML_BEGIN_INSTR(Subscribe, subscribeop) + QML_V4_BEGIN_INSTR(Subscribe, subscribeop) { QObject *o = 0; const Register &object = registers[instr->subscribeop.reg]; if (!object.isUndefined()) o = object.getQObject(); subscribe(o, instr->subscribeop.index, instr->subscribeop.offset); } - QML_END_INSTR(Subscribe, subscribeop) + QML_V4_END_INSTR(Subscribe, subscribeop) - QML_BEGIN_INSTR(FetchAndSubscribe, fetchAndSubscribe) + QML_V4_BEGIN_INSTR(FetchAndSubscribe, fetchAndSubscribe) { Register ® = registers[instr->fetchAndSubscribe.reg]; @@ -854,21 +854,21 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, QDeclarativeV4Compiler::fastPropertyAccessor()->accessor(instr->fetchAndSubscribe.function)(object, reg.typeDataPtr(), sub); } } - QML_END_INSTR(FetchAndSubscribe, fetchAndSubscribe) + QML_V4_END_INSTR(FetchAndSubscribe, fetchAndSubscribe) - QML_BEGIN_INSTR(LoadId, load) + QML_V4_BEGIN_INSTR(LoadId, load) registers[instr->load.reg].setQObject(context->idValues[instr->load.index].data()); - QML_END_INSTR(LoadId, load) + QML_V4_END_INSTR(LoadId, load) - QML_BEGIN_INSTR(LoadScope, load) + QML_V4_BEGIN_INSTR(LoadScope, load) registers[instr->load.reg].setQObject(scope); - QML_END_INSTR(LoadScope, load) + QML_V4_END_INSTR(LoadScope, load) - QML_BEGIN_INSTR(LoadRoot, load) + QML_V4_BEGIN_INSTR(LoadRoot, load) registers[instr->load.reg].setQObject(context->contextObject); - QML_END_INSTR(LoadRoot, load) + QML_V4_END_INSTR(LoadRoot, load) - QML_BEGIN_INSTR(LoadAttached, attached) + QML_V4_BEGIN_INSTR(LoadAttached, attached) { const Register &input = registers[instr->attached.reg]; Register &output = registers[instr->attached.output]; @@ -884,57 +884,57 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, output.setQObject(attached); } } - QML_END_INSTR(LoadAttached, attached) + QML_V4_END_INSTR(LoadAttached, attached) - QML_BEGIN_INSTR(UnaryNot, unaryop) + QML_V4_BEGIN_INSTR(UnaryNot, unaryop) { registers[instr->unaryop.output].setbool(!registers[instr->unaryop.src].getbool()); } - QML_END_INSTR(UnaryNot, unaryop) + QML_V4_END_INSTR(UnaryNot, unaryop) - QML_BEGIN_INSTR(UnaryMinusReal, unaryop) + QML_V4_BEGIN_INSTR(UnaryMinusReal, unaryop) { registers[instr->unaryop.output].setqreal(-registers[instr->unaryop.src].getqreal()); } - QML_END_INSTR(UnaryMinusReal, unaryop) + QML_V4_END_INSTR(UnaryMinusReal, unaryop) - QML_BEGIN_INSTR(UnaryMinusInt, unaryop) + QML_V4_BEGIN_INSTR(UnaryMinusInt, unaryop) { registers[instr->unaryop.output].setint(-registers[instr->unaryop.src].getint()); } - QML_END_INSTR(UnaryMinusInt, unaryop) + QML_V4_END_INSTR(UnaryMinusInt, unaryop) - QML_BEGIN_INSTR(UnaryPlusReal, unaryop) + QML_V4_BEGIN_INSTR(UnaryPlusReal, unaryop) { registers[instr->unaryop.output].setqreal(+registers[instr->unaryop.src].getqreal()); } - QML_END_INSTR(UnaryPlusReal, unaryop) + QML_V4_END_INSTR(UnaryPlusReal, unaryop) - QML_BEGIN_INSTR(UnaryPlusInt, unaryop) + QML_V4_BEGIN_INSTR(UnaryPlusInt, unaryop) { registers[instr->unaryop.output].setint(+registers[instr->unaryop.src].getint()); } - QML_END_INSTR(UnaryPlusInt, unaryop) + QML_V4_END_INSTR(UnaryPlusInt, unaryop) - QML_BEGIN_INSTR(ConvertBoolToInt, unaryop) + QML_V4_BEGIN_INSTR(ConvertBoolToInt, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; if (src.isUndefined()) output.setUndefined(); else output.setint(src.getbool()); } - QML_END_INSTR(ConvertBoolToInt, unaryop) + QML_V4_END_INSTR(ConvertBoolToInt, unaryop) - QML_BEGIN_INSTR(ConvertBoolToReal, unaryop) + QML_V4_BEGIN_INSTR(ConvertBoolToReal, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; if (src.isUndefined()) output.setUndefined(); else output.setqreal(src.getbool()); } - QML_END_INSTR(ConvertBoolToReal, unaryop) + QML_V4_END_INSTR(ConvertBoolToReal, unaryop) - QML_BEGIN_INSTR(ConvertBoolToString, unaryop) + QML_V4_BEGIN_INSTR(ConvertBoolToString, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; @@ -945,27 +945,27 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, STRING_REGISTER(instr->unaryop.output); } } - QML_END_INSTR(ConvertBoolToString, unaryop) + QML_V4_END_INSTR(ConvertBoolToString, unaryop) - QML_BEGIN_INSTR(ConvertIntToBool, unaryop) + QML_V4_BEGIN_INSTR(ConvertIntToBool, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; if (src.isUndefined()) output.setUndefined(); else output.setbool(src.getint()); } - QML_END_INSTR(ConvertIntToBool, unaryop) + QML_V4_END_INSTR(ConvertIntToBool, unaryop) - QML_BEGIN_INSTR(ConvertIntToReal, unaryop) + QML_V4_BEGIN_INSTR(ConvertIntToReal, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; if (src.isUndefined()) output.setUndefined(); else output.setqreal(qreal(src.getint())); } - QML_END_INSTR(ConvertIntToReal, unaryop) + QML_V4_END_INSTR(ConvertIntToReal, unaryop) - QML_BEGIN_INSTR(ConvertIntToString, unaryop) + QML_V4_BEGIN_INSTR(ConvertIntToString, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; @@ -976,27 +976,27 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, STRING_REGISTER(instr->unaryop.output); } } - QML_END_INSTR(ConvertIntToString, unaryop) + QML_V4_END_INSTR(ConvertIntToString, unaryop) - QML_BEGIN_INSTR(ConvertRealToBool, unaryop) + QML_V4_BEGIN_INSTR(ConvertRealToBool, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; if (src.isUndefined()) output.setUndefined(); else output.setbool(src.getqreal() != 0); } - QML_END_INSTR(ConvertRealToBool, unaryop) + QML_V4_END_INSTR(ConvertRealToBool, unaryop) - QML_BEGIN_INSTR(ConvertRealToInt, unaryop) + QML_V4_BEGIN_INSTR(ConvertRealToInt, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; if (src.isUndefined()) output.setUndefined(); else output.setint(toInt32(src.getqreal())); } - QML_END_INSTR(ConvertRealToInt, unaryop) + QML_V4_END_INSTR(ConvertRealToInt, unaryop) - QML_BEGIN_INSTR(ConvertRealToString, unaryop) + QML_V4_BEGIN_INSTR(ConvertRealToString, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; @@ -1008,9 +1008,9 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, STRING_REGISTER(instr->unaryop.output); } } - QML_END_INSTR(ConvertRealToString, unaryop) + QML_V4_END_INSTR(ConvertRealToString, unaryop) - QML_BEGIN_INSTR(ConvertStringToBool, unaryop) + QML_V4_BEGIN_INSTR(ConvertStringToBool, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; @@ -1028,9 +1028,9 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, output.setbool(tmp.toBool()); } } - QML_END_INSTR(ConvertStringToBool, unaryop) + QML_V4_END_INSTR(ConvertStringToBool, unaryop) - QML_BEGIN_INSTR(ConvertStringToInt, unaryop) + QML_V4_BEGIN_INSTR(ConvertStringToInt, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; @@ -1048,9 +1048,9 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, output.setint(tmp.toInt32()); } } - QML_END_INSTR(ConvertStringToInt, unaryop) + QML_V4_END_INSTR(ConvertStringToInt, unaryop) - QML_BEGIN_INSTR(ConvertStringToReal, unaryop) + QML_V4_BEGIN_INSTR(ConvertStringToReal, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; @@ -1068,109 +1068,109 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, output.setqreal(tmp.toNumber()); } } - QML_END_INSTR(ConvertStringToReal, unaryop) + QML_V4_END_INSTR(ConvertStringToReal, unaryop) - QML_BEGIN_INSTR(MathSinReal, unaryop) + QML_V4_BEGIN_INSTR(MathSinReal, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; if (src.isUndefined()) output.setUndefined(); else output.setqreal(qSin(src.getqreal())); } - QML_END_INSTR(MathSinReal, unaryop) + QML_V4_END_INSTR(MathSinReal, unaryop) - QML_BEGIN_INSTR(MathCosReal, unaryop) + QML_V4_BEGIN_INSTR(MathCosReal, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; if (src.isUndefined()) output.setUndefined(); else output.setqreal(qCos(src.getqreal())); } - QML_END_INSTR(MathCosReal, unaryop) + QML_V4_END_INSTR(MathCosReal, unaryop) - QML_BEGIN_INSTR(MathRoundReal, unaryop) + QML_V4_BEGIN_INSTR(MathRoundReal, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; if (src.isUndefined()) output.setUndefined(); else output.setint(qRound(src.getqreal())); } - QML_END_INSTR(MathRoundReal, unaryop) + QML_V4_END_INSTR(MathRoundReal, unaryop) - QML_BEGIN_INSTR(MathFloorReal, unaryop) + QML_V4_BEGIN_INSTR(MathFloorReal, unaryop) { const Register &src = registers[instr->unaryop.src]; Register &output = registers[instr->unaryop.output]; if (src.isUndefined()) output.setUndefined(); else output.setint(qFloor(src.getqreal())); } - QML_END_INSTR(MathFloorReal, unaryop) + QML_V4_END_INSTR(MathFloorReal, unaryop) - QML_BEGIN_INSTR(MathPIReal, unaryop) + QML_V4_BEGIN_INSTR(MathPIReal, unaryop) { static const qsreal qmlPI = 2.0 * qAsin(1.0); Register &output = registers[instr->unaryop.output]; output.setqreal(qmlPI); } - QML_END_INSTR(MathPIReal, unaryop) + QML_V4_END_INSTR(MathPIReal, unaryop) - QML_BEGIN_INSTR(Real, real_value) + QML_V4_BEGIN_INSTR(Real, real_value) registers[instr->real_value.reg].setqreal(instr->real_value.value); - QML_END_INSTR(Real, real_value) + QML_V4_END_INSTR(Real, real_value) - QML_BEGIN_INSTR(Int, int_value) + QML_V4_BEGIN_INSTR(Int, int_value) registers[instr->int_value.reg].setint(instr->int_value.value); - QML_END_INSTR(Int, int_value) + QML_V4_END_INSTR(Int, int_value) - QML_BEGIN_INSTR(Bool, bool_value) + QML_V4_BEGIN_INSTR(Bool, bool_value) registers[instr->bool_value.reg].setbool(instr->bool_value.value); - QML_END_INSTR(Bool, bool_value) + QML_V4_END_INSTR(Bool, bool_value) - QML_BEGIN_INSTR(String, string_value) + QML_V4_BEGIN_INSTR(String, string_value) { Register &output = registers[instr->string_value.reg]; QChar *string = (QChar *)(data + instr->string_value.offset); new (output.getstringptr()) QString(string, instr->string_value.length); STRING_REGISTER(instr->string_value.reg); } - QML_END_INSTR(String, string_value) + QML_V4_END_INSTR(String, string_value) - QML_BEGIN_INSTR(EnableV4Test, string_value) + QML_V4_BEGIN_INSTR(EnableV4Test, string_value) { testBindingSource = new QString((QChar *)(data + instr->string_value.offset), instr->string_value.length); testBinding = true; } - QML_END_INSTR(String, string_value) + QML_V4_END_INSTR(String, string_value) - QML_BEGIN_INSTR(BitAndInt, binaryop) + QML_V4_BEGIN_INSTR(BitAndInt, binaryop) { registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() & registers[instr->binaryop.right].getint()); } - QML_END_INSTR(BitAndInt, binaryop) + QML_V4_END_INSTR(BitAndInt, binaryop) - QML_BEGIN_INSTR(BitOrInt, binaryop) + QML_V4_BEGIN_INSTR(BitOrInt, binaryop) { registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() | registers[instr->binaryop.right].getint()); } - QML_END_INSTR(BitAndInt, binaryop) + QML_V4_END_INSTR(BitAndInt, binaryop) - QML_BEGIN_INSTR(BitXorInt, binaryop) + QML_V4_BEGIN_INSTR(BitXorInt, binaryop) { registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() ^ registers[instr->binaryop.right].getint()); } - QML_END_INSTR(BitXorInt, binaryop) + QML_V4_END_INSTR(BitXorInt, binaryop) - QML_BEGIN_INSTR(AddReal, binaryop) + QML_V4_BEGIN_INSTR(AddReal, binaryop) { registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() + registers[instr->binaryop.right].getqreal()); } - QML_END_INSTR(AddReal, binaryop) + QML_V4_END_INSTR(AddReal, binaryop) - QML_BEGIN_INSTR(AddString, binaryop) + QML_V4_BEGIN_INSTR(AddString, binaryop) { QString &string = *registers[instr->binaryop.output].getstringptr(); if (instr->binaryop.output == instr->binaryop.left) { @@ -1180,30 +1180,30 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, *registers[instr->binaryop.right].getstringptr(); } } - QML_END_INSTR(AddString, binaryop) + QML_V4_END_INSTR(AddString, binaryop) - QML_BEGIN_INSTR(SubReal, binaryop) + QML_V4_BEGIN_INSTR(SubReal, binaryop) { registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() - registers[instr->binaryop.right].getqreal()); } - QML_END_INSTR(SubReal, binaryop) + QML_V4_END_INSTR(SubReal, binaryop) - QML_BEGIN_INSTR(MulReal, binaryop) + QML_V4_BEGIN_INSTR(MulReal, binaryop) { registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() * registers[instr->binaryop.right].getqreal()); } - QML_END_INSTR(MulReal, binaryop) + QML_V4_END_INSTR(MulReal, binaryop) - QML_BEGIN_INSTR(DivReal, binaryop) + QML_V4_BEGIN_INSTR(DivReal, binaryop) { registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() / registers[instr->binaryop.right].getqreal()); } - QML_END_INSTR(DivReal, binaryop) + QML_V4_END_INSTR(DivReal, binaryop) - QML_BEGIN_INSTR(ModReal, binaryop) + QML_V4_BEGIN_INSTR(ModReal, binaryop) { Register &target = registers[instr->binaryop.output]; const Register &left = registers[instr->binaryop.left]; @@ -1213,86 +1213,86 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, else target.setqreal(::fmod(left.getqreal(), right.getqreal())); } - QML_END_INSTR(ModInt, binaryop) + QML_V4_END_INSTR(ModInt, binaryop) - QML_BEGIN_INSTR(LShiftInt, binaryop) + QML_V4_BEGIN_INSTR(LShiftInt, binaryop) { registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() << registers[instr->binaryop.right].getint()); } - QML_END_INSTR(LShiftInt, binaryop) + QML_V4_END_INSTR(LShiftInt, binaryop) - QML_BEGIN_INSTR(RShiftInt, binaryop) + QML_V4_BEGIN_INSTR(RShiftInt, binaryop) { registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() >> registers[instr->binaryop.right].getint()); } - QML_END_INSTR(RShiftInt, binaryop) + QML_V4_END_INSTR(RShiftInt, binaryop) - QML_BEGIN_INSTR(URShiftInt, binaryop) + QML_V4_BEGIN_INSTR(URShiftInt, binaryop) { registers[instr->binaryop.output].setint((unsigned)registers[instr->binaryop.left].getint() >> registers[instr->binaryop.right].getint()); } - QML_END_INSTR(URShiftInt, binaryop) + QML_V4_END_INSTR(URShiftInt, binaryop) - QML_BEGIN_INSTR(GtReal, binaryop) + QML_V4_BEGIN_INSTR(GtReal, binaryop) { registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() > registers[instr->binaryop.right].getqreal()); } - QML_END_INSTR(GtReal, binaryop) + QML_V4_END_INSTR(GtReal, binaryop) - QML_BEGIN_INSTR(LtReal, binaryop) + QML_V4_BEGIN_INSTR(LtReal, binaryop) { registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() < registers[instr->binaryop.right].getqreal()); } - QML_END_INSTR(LtReal, binaryop) + QML_V4_END_INSTR(LtReal, binaryop) - QML_BEGIN_INSTR(GeReal, binaryop) + QML_V4_BEGIN_INSTR(GeReal, binaryop) { registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() >= registers[instr->binaryop.right].getqreal()); } - QML_END_INSTR(GeReal, binaryop) + QML_V4_END_INSTR(GeReal, binaryop) - QML_BEGIN_INSTR(LeReal, binaryop) + QML_V4_BEGIN_INSTR(LeReal, binaryop) { registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() <= registers[instr->binaryop.right].getqreal()); } - QML_END_INSTR(LeReal, binaryop) + QML_V4_END_INSTR(LeReal, binaryop) - QML_BEGIN_INSTR(EqualReal, binaryop) + QML_V4_BEGIN_INSTR(EqualReal, binaryop) { registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() == registers[instr->binaryop.right].getqreal()); } - QML_END_INSTR(EqualReal, binaryop) + QML_V4_END_INSTR(EqualReal, binaryop) - QML_BEGIN_INSTR(NotEqualReal, binaryop) + QML_V4_BEGIN_INSTR(NotEqualReal, binaryop) { registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() != registers[instr->binaryop.right].getqreal()); } - QML_END_INSTR(NotEqualReal, binaryop) + QML_V4_END_INSTR(NotEqualReal, binaryop) - QML_BEGIN_INSTR(StrictEqualReal, binaryop) + QML_V4_BEGIN_INSTR(StrictEqualReal, binaryop) { registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() == registers[instr->binaryop.right].getqreal()); } - QML_END_INSTR(StrictEqualReal, binaryop) + QML_V4_END_INSTR(StrictEqualReal, binaryop) - QML_BEGIN_INSTR(StrictNotEqualReal, binaryop) + QML_V4_BEGIN_INSTR(StrictNotEqualReal, binaryop) { registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() != registers[instr->binaryop.right].getqreal()); } - QML_END_INSTR(StrictNotEqualReal, binaryop) + QML_V4_END_INSTR(StrictNotEqualReal, binaryop) - QML_BEGIN_INSTR(GtString, binaryop) + QML_V4_BEGIN_INSTR(GtString, binaryop) { const QString &a = *registers[instr->binaryop.left].getstringptr(); const QString &b = *registers[instr->binaryop.right].getstringptr(); @@ -1303,9 +1303,9 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, } registers[instr->binaryop.output].setbool(result); } - QML_END_INSTR(GtString, binaryop) + QML_V4_END_INSTR(GtString, binaryop) - QML_BEGIN_INSTR(LtString, binaryop) + QML_V4_BEGIN_INSTR(LtString, binaryop) { const QString &a = *registers[instr->binaryop.left].getstringptr(); const QString &b = *registers[instr->binaryop.right].getstringptr(); @@ -1316,9 +1316,9 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, } registers[instr->binaryop.output].setbool(result); } - QML_END_INSTR(LtString, binaryop) + QML_V4_END_INSTR(LtString, binaryop) - QML_BEGIN_INSTR(GeString, binaryop) + QML_V4_BEGIN_INSTR(GeString, binaryop) { const QString &a = *registers[instr->binaryop.left].getstringptr(); const QString &b = *registers[instr->binaryop.right].getstringptr(); @@ -1329,9 +1329,9 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, } registers[instr->binaryop.output].setbool(result); } - QML_END_INSTR(GeString, binaryop) + QML_V4_END_INSTR(GeString, binaryop) - QML_BEGIN_INSTR(LeString, binaryop) + QML_V4_BEGIN_INSTR(LeString, binaryop) { const QString &a = *registers[instr->binaryop.left].getstringptr(); const QString &b = *registers[instr->binaryop.right].getstringptr(); @@ -1342,9 +1342,9 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, } registers[instr->binaryop.output].setbool(result); } - QML_END_INSTR(LeString, binaryop) + QML_V4_END_INSTR(LeString, binaryop) - QML_BEGIN_INSTR(EqualString, binaryop) + QML_V4_BEGIN_INSTR(EqualString, binaryop) { const QString &a = *registers[instr->binaryop.left].getstringptr(); const QString &b = *registers[instr->binaryop.right].getstringptr(); @@ -1355,9 +1355,9 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, } registers[instr->binaryop.output].setbool(result); } - QML_END_INSTR(EqualString, binaryop) + QML_V4_END_INSTR(EqualString, binaryop) - QML_BEGIN_INSTR(NotEqualString, binaryop) + QML_V4_BEGIN_INSTR(NotEqualString, binaryop) { const QString &a = *registers[instr->binaryop.left].getstringptr(); const QString &b = *registers[instr->binaryop.right].getstringptr(); @@ -1368,9 +1368,9 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, } registers[instr->binaryop.output].setbool(result); } - QML_END_INSTR(NotEqualString, binaryop) + QML_V4_END_INSTR(NotEqualString, binaryop) - QML_BEGIN_INSTR(StrictEqualString, binaryop) + QML_V4_BEGIN_INSTR(StrictEqualString, binaryop) { const QString &a = *registers[instr->binaryop.left].getstringptr(); const QString &b = *registers[instr->binaryop.right].getstringptr(); @@ -1381,9 +1381,9 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, } registers[instr->binaryop.output].setbool(result); } - QML_END_INSTR(StrictEqualString, binaryop) + QML_V4_END_INSTR(StrictEqualString, binaryop) - QML_BEGIN_INSTR(StrictNotEqualString, binaryop) + QML_V4_BEGIN_INSTR(StrictNotEqualString, binaryop) { const QString &a = *registers[instr->binaryop.left].getstringptr(); const QString &b = *registers[instr->binaryop.right].getstringptr(); @@ -1394,25 +1394,25 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, } registers[instr->binaryop.output].setbool(result); } - QML_END_INSTR(StrictNotEqualString, binaryop) + QML_V4_END_INSTR(StrictNotEqualString, binaryop) - QML_BEGIN_INSTR(NewString, construct) + QML_V4_BEGIN_INSTR(NewString, construct) { Register &output = registers[instr->construct.reg]; new (output.getstringptr()) QString; STRING_REGISTER(instr->construct.reg); } - QML_END_INSTR(NewString, construct) + QML_V4_END_INSTR(NewString, construct) - QML_BEGIN_INSTR(NewUrl, construct) + QML_V4_BEGIN_INSTR(NewUrl, construct) { Register &output = registers[instr->construct.reg]; new (output.geturlptr()) QUrl; URL_REGISTER(instr->construct.reg); } - QML_END_INSTR(NewUrl, construct) + QML_V4_END_INSTR(NewUrl, construct) - QML_BEGIN_INSTR(Fetch, fetch) + QML_V4_BEGIN_INSTR(Fetch, fetch) { Register ® = registers[instr->fetch.reg]; @@ -1430,17 +1430,17 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, QMetaObject::metacall(object, QMetaObject::ReadProperty, instr->fetch.index, argv); } } - QML_END_INSTR(Fetch, fetch) + QML_V4_END_INSTR(Fetch, fetch) - QML_BEGIN_INSTR(TestV4Store, storetest) + QML_V4_BEGIN_INSTR(TestV4Store, storetest) { Register &data = registers[instr->storetest.reg]; testBindingResult(*testBindingSource, bindingLine, bindingColumn, context, scope, data, instr->storetest.regType); } - QML_END_INSTR(TestV4Store, storetest) + QML_V4_END_INSTR(TestV4Store, storetest) - QML_BEGIN_INSTR(Store, store) + QML_V4_BEGIN_INSTR(Store, store) { Register &data = registers[instr->store.reg]; @@ -1454,38 +1454,38 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, goto programExit; } - QML_END_INSTR(Store, store) + QML_V4_END_INSTR(Store, store) - QML_BEGIN_INSTR(Copy, copy) + QML_V4_BEGIN_INSTR(Copy, copy) registers[instr->copy.reg].copy(registers[instr->copy.src]); if (registers[instr->copy.reg].gettype() >= FirstCleanupType) MARK_REGISTER(instr->copy.reg); - QML_END_INSTR(Copy, copy) + QML_V4_END_INSTR(Copy, copy) - QML_BEGIN_INSTR(Jump, jump) + QML_V4_BEGIN_INSTR(Jump, jump) if (instr->jump.reg == -1 || !registers[instr->jump.reg].getbool()) code += instr->jump.count; - QML_END_INSTR(Jump, jump) + QML_V4_END_INSTR(Jump, jump) - QML_BEGIN_INSTR(BranchTrue, branchop) + QML_V4_BEGIN_INSTR(BranchTrue, branchop) if (registers[instr->branchop.reg].getbool()) code += instr->branchop.offset; - QML_END_INSTR(BranchTrue, branchop) + QML_V4_END_INSTR(BranchTrue, branchop) - QML_BEGIN_INSTR(BranchFalse, branchop) + QML_V4_BEGIN_INSTR(BranchFalse, branchop) if (! registers[instr->branchop.reg].getbool()) code += instr->branchop.offset; - QML_END_INSTR(BranchFalse, branchop) + QML_V4_END_INSTR(BranchFalse, branchop) - QML_BEGIN_INSTR(Branch, branchop) + QML_V4_BEGIN_INSTR(Branch, branchop) code += instr->branchop.offset; - QML_END_INSTR(Branch, branchop) + QML_V4_END_INSTR(Branch, branchop) - QML_BEGIN_INSTR(Block, blockop) + QML_V4_BEGIN_INSTR(Block, blockop) executedBlocks |= instr->blockop.block; - QML_END_INSTR(Block, blockop) + QML_V4_END_INSTR(Block, blockop) - QML_BEGIN_INSTR(InitString, initstring) + QML_V4_BEGIN_INSTR(InitString, initstring) if (!identifiers[instr->initstring.offset].identifier) { quint32 len = *(quint32 *)(data + instr->initstring.dataIdx); QChar *strdata = (QChar *)(data + instr->initstring.dataIdx + sizeof(quint32)); @@ -1494,11 +1494,11 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks, identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str); } - QML_END_INSTR(InitString, initstring) + QML_V4_END_INSTR(InitString, initstring) - QML_BEGIN_INSTR(CleanupRegister, cleanup) + QML_V4_BEGIN_INSTR(CleanupRegister, cleanup) registers[instr->cleanup.reg].cleanup(); - QML_END_INSTR(CleanupRegister, cleanup) + QML_V4_END_INSTR(CleanupRegister, cleanup) #ifdef QML_THREADED_INTERPRETER // nothing to do diff --git a/src/declarative/qml/v4/qdeclarativev4instruction.cpp b/src/declarative/qml/v4/qdeclarativev4instruction.cpp index 1f24f30c25..9c3bf914e0 100644 --- a/src/declarative/qml/v4/qdeclarativev4instruction.cpp +++ b/src/declarative/qml/v4/qdeclarativev4instruction.cpp @@ -60,18 +60,18 @@ namespace QDeclarativeJS { static struct DumpInstrAtStartup { DumpInstrAtStartup() { #define DUMP_INSTR_AT_STARTUP(Type, FMT) { Instr i; i.common.type = Instr::Type; i.dump(0); } - FOR_EACH_QML_INSTR(DUMP_INSTR_AT_STARTUP); + FOR_EACH_V4_INSTR(DUMP_INSTR_AT_STARTUP); } } dump_instr_at_startup; #endif int Instr::size() const { -#define QML_RETURN_INSTR_SIZE(I, FMT) case I: return QML_INSTR_SIZE(I, FMT); +#define V4_RETURN_INSTR_SIZE(I, FMT) case I: return QML_V4_INSTR_SIZE(I, FMT); switch (common.type) { - FOR_EACH_QML_INSTR(QML_RETURN_INSTR_SIZE) + FOR_EACH_V4_INSTR(V4_RETURN_INSTR_SIZE) } -#undef QML_RETURN_INSTR_SIZE +#undef V4_RETURN_INSTR_SIZE return 0; } diff --git a/src/declarative/qml/v4/qdeclarativev4instruction_p.h b/src/declarative/qml/v4/qdeclarativev4instruction_p.h index f6e0bc734a..67b152adea 100644 --- a/src/declarative/qml/v4/qdeclarativev4instruction_p.h +++ b/src/declarative/qml/v4/qdeclarativev4instruction_p.h @@ -61,7 +61,7 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -#define FOR_EACH_QML_INSTR(F) \ +#define FOR_EACH_V4_INSTR(F) \ F(Noop, common) \ F(BindingId, id) \ F(Subscribe, subscribeop) \ @@ -146,23 +146,23 @@ QT_BEGIN_NAMESPACE #endif #ifdef Q_ALIGNOF -# define QML_INSTR_ALIGN_MASK (Q_ALIGNOF(Instr) - 1) +# define QML_V4_INSTR_ALIGN_MASK (Q_ALIGNOF(Instr) - 1) #else -# define QML_INSTR_ALIGN_MASK (sizeof(void *) - 1) +# define QML_V4_INSTR_ALIGN_MASK (sizeof(void *) - 1) #endif -#define QML_INSTR_ENUM(I, FMT) I, -#define QML_INSTR_ADDR(I, FMT) &&op_##I, -#define QML_INSTR_SIZE(I, FMT) ((sizeof(Instr::instr_##FMT) + QML_INSTR_ALIGN_MASK) & ~QML_INSTR_ALIGN_MASK) +#define QML_V4_INSTR_ENUM(I, FMT) I, +#define QML_V4_INSTR_ADDR(I, FMT) &&op_##I, +#define QML_V4_INSTR_SIZE(I, FMT) ((sizeof(Instr::instr_##FMT) + QML_V4_INSTR_ALIGN_MASK) & ~QML_V4_INSTR_ALIGN_MASK) #ifdef QML_THREADED_INTERPRETER -# define QML_BEGIN_INSTR(I,FMT) op_##I: -# define QML_END_INSTR(I,FMT) code += QML_INSTR_SIZE(I, FMT); instr = (const Instr *) code; goto *instr->common.code; -# define QML_INSTR_HEADER void *code; +# define QML_V4_BEGIN_INSTR(I,FMT) op_##I: +# define QML_V4_END_INSTR(I,FMT) code += QML_V4_INSTR_SIZE(I, FMT); instr = (const Instr *) code; goto *instr->common.code; +# define QML_V4_INSTR_HEADER void *code; #else -# define QML_BEGIN_INSTR(I,FMT) case Instr::I: -# define QML_END_INSTR(I,FMT) code += QML_INSTR_SIZE(I, FMT); instr = (const Instr *) code; break; -# define QML_INSTR_HEADER +# define QML_V4_BEGIN_INSTR(I,FMT) case Instr::I: +# define QML_V4_END_INSTR(I,FMT) code += QML_V4_INSTR_SIZE(I, FMT); instr = (const Instr *) code; break; +# define QML_V4_INSTR_HEADER #endif namespace QDeclarativeJS { @@ -200,30 +200,30 @@ union Instr { void block(quint32 mask); enum { - FOR_EACH_QML_INSTR(QML_INSTR_ENUM) + FOR_EACH_V4_INSTR(QML_V4_INSTR_ENUM) }; struct instr_common { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; }; struct instr_id { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; quint16 column; quint32 line; }; struct instr_init { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; quint16 subscriptions; quint16 identifiers; }; struct instr_subscribeop { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 reg; quint16 offset; @@ -231,14 +231,14 @@ union Instr { }; struct instr_load { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 reg; quint32 index; }; struct instr_attached { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 output; qint8 reg; @@ -247,7 +247,7 @@ union Instr { }; struct instr_store { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 output; qint8 reg; @@ -256,14 +256,14 @@ union Instr { }; struct instr_storetest { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 reg; qint32 regType; }; struct instr_fetchAndSubscribe { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 reg; quint8 exceptionId; @@ -273,7 +273,7 @@ union Instr { }; struct instr_fetch{ - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 reg; quint8 exceptionId; @@ -282,41 +282,41 @@ union Instr { }; struct instr_copy { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 reg; qint8 src; }; struct instr_construct { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 reg; }; struct instr_real_value { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 reg; qreal value; // XXX Makes the instruction 12 bytes }; struct instr_int_value { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 reg; int value; }; struct instr_bool_value { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 reg; bool value; }; struct instr_string_value { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 reg; quint16 length; @@ -324,7 +324,7 @@ union Instr { }; struct instr_binaryop { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 output; qint8 left; @@ -332,21 +332,21 @@ union Instr { }; struct instr_unaryop { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 output; qint8 src; }; struct instr_jump { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 reg; quint32 count; }; struct instr_find { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 reg; qint8 src; @@ -356,27 +356,27 @@ union Instr { }; struct instr_cleanup { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; qint8 reg; }; struct instr_initstring { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; quint16 offset; quint32 dataIdx; }; struct instr_branchop { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; quint8 reg; qint16 offset; }; struct instr_blockop { - QML_INSTR_HEADER + QML_V4_INSTR_HEADER quint8 type; quint32 block; }; -- cgit v1.2.3 From 21521c2d28e7c00e859fd2a28263b716d550c0fc Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 5 May 2011 14:16:27 +1000 Subject: Inline static data for basic types into the QML instruction The following types are now entirely inline: QPoint, QPointF QSize, QSizeF QRect, QRectF QVector3D, QTime, QDateTime CustomTypeData Reviewed-by: Martin Jones Change-Id: I7024d136c77f8fb23ef6a6abb23ddfe0f9f8a1ca --- src/declarative/qml/qdeclarativecompileddata.cpp | 64 ------------- src/declarative/qml/qdeclarativecompiler.cpp | 110 +++++++++++------------ src/declarative/qml/qdeclarativecompiler_p.h | 13 --- src/declarative/qml/qdeclarativeinstruction.cpp | 20 ++--- src/declarative/qml/qdeclarativeinstruction_p.h | 103 +++++++++++++++++---- src/declarative/qml/qdeclarativevme.cpp | 68 +++++--------- 6 files changed, 173 insertions(+), 205 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativecompileddata.cpp b/src/declarative/qml/qdeclarativecompileddata.cpp index 1f5d11141d..4c7f270048 100644 --- a/src/declarative/qml/qdeclarativecompileddata.cpp +++ b/src/declarative/qml/qdeclarativecompileddata.cpp @@ -97,70 +97,6 @@ int QDeclarativeCompiledData::indexForUrl(const QUrl &data) return idx; } -int QDeclarativeCompiledData::indexForFloat(float *data, int count) -{ - Q_ASSERT(count > 0); - - for (int ii = 0; ii <= floatData.count() - count; ++ii) { - bool found = true; - for (int jj = 0; jj < count; ++jj) { - if (floatData.at(ii + jj) != data[jj]) { - found = false; - break; - } - } - - if (found) - return ii; - } - - int idx = floatData.count(); - for (int ii = 0; ii < count; ++ii) - floatData << data[ii]; - - return idx; -} - -int QDeclarativeCompiledData::indexForInt(int *data, int count) -{ - Q_ASSERT(count > 0); - - for (int ii = 0; ii <= intData.count() - count; ++ii) { - bool found = true; - for (int jj = 0; jj < count; ++jj) { - if (intData.at(ii + jj) != data[jj]) { - found = false; - break; - } - } - - if (found) - return ii; - } - - int idx = intData.count(); - for (int ii = 0; ii < count; ++ii) - intData << data[ii]; - - return idx; -} - -int QDeclarativeCompiledData::indexForLocation(const QDeclarativeParser::Location &l) -{ - // ### FIXME - int rv = locations.count(); - locations << l; - return rv; -} - -int QDeclarativeCompiledData::indexForLocation(const QDeclarativeParser::LocationSpan &l) -{ - // ### FIXME - int rv = locations.count(); - locations << l.start << l.end; - return rv; -} - QDeclarativeCompiledData::QDeclarativeCompiledData(QDeclarativeEngine *engine) : QDeclarativeCleanup(engine), importCache(0), root(0), rootPropertyCache(0) { diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index d8aa938943..31a9f668ef 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -441,74 +441,84 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, case QVariant::Time: { QTime time = QDeclarativeStringConverters::timeFromString(string); - int data[] = { time.hour(), time.minute(), - time.second(), time.msec() }; - int index = output->indexForInt(data, 4); instr.setType(QDeclarativeInstruction::StoreTime); instr.storeTime.propertyIndex = prop.propertyIndex(); - instr.storeTime.valueIndex = index; + instr.storeTime.time = *(QDeclarativeInstruction::instr_storeTime::QTime *)&time; } break; case QVariant::DateTime: { QDateTime dateTime = QDeclarativeStringConverters::dateTimeFromString(string); - int data[] = { dateTime.date().toJulianDay(), - dateTime.time().hour(), - dateTime.time().minute(), - dateTime.time().second(), - dateTime.time().msec() }; - int index = output->indexForInt(data, 5); + QTime time = dateTime.time(); instr.setType(QDeclarativeInstruction::StoreDateTime); instr.storeDateTime.propertyIndex = prop.propertyIndex(); - instr.storeDateTime.valueIndex = index; + instr.storeDateTime.date = dateTime.date().toJulianDay(); + instr.storeDateTime.time = *(QDeclarativeInstruction::instr_storeTime::QTime *)&time; } break; #endif // QT_NO_DATESTRING case QVariant::Point: + { + bool ok; + QPoint point = QDeclarativeStringConverters::pointFFromString(string, &ok).toPoint(); + instr.setType(QDeclarativeInstruction::StorePoint); + instr.storePoint.propertyIndex = prop.propertyIndex(); + instr.storePoint.point.xp = point.x(); + instr.storePoint.point.yp = point.y(); + } + break; case QVariant::PointF: { bool ok; - QPointF point = - QDeclarativeStringConverters::pointFFromString(string, &ok); - float data[] = { float(point.x()), float(point.y()) }; - int index = output->indexForFloat(data, 2); - if (type == QVariant::PointF) - instr.setType(QDeclarativeInstruction::StorePointF); - else - instr.setType(QDeclarativeInstruction::StorePoint); - instr.storeRealPair.propertyIndex = prop.propertyIndex(); - instr.storeRealPair.valueIndex = index; + QPointF point = QDeclarativeStringConverters::pointFFromString(string, &ok); + instr.setType(QDeclarativeInstruction::StorePointF); + instr.storePointF.propertyIndex = prop.propertyIndex(); + instr.storePointF.point.xp = point.x(); + instr.storePointF.point.yp = point.y(); } break; case QVariant::Size: + { + bool ok; + QSize size = QDeclarativeStringConverters::sizeFFromString(string, &ok).toSize(); + instr.setType(QDeclarativeInstruction::StoreSize); + instr.storeSize.propertyIndex = prop.propertyIndex(); + instr.storeSize.size.wd = size.width(); + instr.storeSize.size.ht = size.height(); + } + break; case QVariant::SizeF: { bool ok; QSizeF size = QDeclarativeStringConverters::sizeFFromString(string, &ok); - float data[] = { float(size.width()), float(size.height()) }; - int index = output->indexForFloat(data, 2); - if (type == QVariant::SizeF) - instr.setType(QDeclarativeInstruction::StoreSizeF); - else - instr.setType(QDeclarativeInstruction::StoreSize); - instr.storeRealPair.propertyIndex = prop.propertyIndex(); - instr.storeRealPair.valueIndex = index; + instr.setType(QDeclarativeInstruction::StoreSizeF); + instr.storeSizeF.propertyIndex = prop.propertyIndex(); + instr.storeSizeF.size.wd = size.width(); + instr.storeSizeF.size.ht = size.height(); } break; case QVariant::Rect: + { + bool ok; + QRect rect = QDeclarativeStringConverters::rectFFromString(string, &ok).toRect(); + instr.setType(QDeclarativeInstruction::StoreRect); + instr.storeRect.propertyIndex = prop.propertyIndex(); + instr.storeRect.rect.x1 = rect.left(); + instr.storeRect.rect.y1 = rect.top(); + instr.storeRect.rect.x2 = rect.right(); + instr.storeRect.rect.y2 = rect.bottom(); + } + break; case QVariant::RectF: { bool ok; QRectF rect = QDeclarativeStringConverters::rectFFromString(string, &ok); - float data[] = { float(rect.x()), float(rect.y()), - float(rect.width()), float(rect.height()) }; - int index = output->indexForFloat(data, 4); - if (type == QVariant::RectF) - instr.setType(QDeclarativeInstruction::StoreRectF); - else - instr.setType(QDeclarativeInstruction::StoreRect); - instr.storeRect.propertyIndex = prop.propertyIndex(); - instr.storeRect.valueIndex = index; + instr.setType(QDeclarativeInstruction::StoreRectF); + instr.storeRectF.propertyIndex = prop.propertyIndex(); + instr.storeRectF.rect.xp = rect.left(); + instr.storeRectF.rect.yp = rect.top(); + instr.storeRectF.rect.w = rect.width(); + instr.storeRectF.rect.h = rect.height(); } break; case QVariant::Bool: @@ -522,28 +532,21 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, case QVariant::Vector3D: { bool ok; - QVector3D vector = - QDeclarativeStringConverters::vector3DFromString(string, &ok); - float data[] = { float(vector.x()), float(vector.y()), float(vector.z()) }; - int index = output->indexForFloat(data, 3); + QVector3D vector = QDeclarativeStringConverters::vector3DFromString(string, &ok); instr.setType(QDeclarativeInstruction::StoreVector3D); - instr.storeRealPair.propertyIndex = prop.propertyIndex(); - instr.storeRealPair.valueIndex = index; + instr.storeVector3D.propertyIndex = prop.propertyIndex(); + instr.storeVector3D.vector.xp = vector.x(); + instr.storeVector3D.vector.yp = vector.y(); + instr.storeVector3D.vector.zp = vector.z(); } break; default: { int t = prop.userType(); - int index = output->customTypeData.count(); instr.setType(QDeclarativeInstruction::AssignCustomType); instr.assignCustomType.propertyIndex = prop.propertyIndex(); - instr.assignCustomType.valueIndex = index; - instr.assignCustomType.line = v->location.start.line; - - QDeclarativeCompiledData::CustomTypeData data; - data.index = output->indexForString(string); - data.type = t; - output->customTypeData << data; + instr.assignCustomType.primitive = output->indexForString(string); + instr.assignCustomType.type = t; } break; } @@ -557,9 +560,6 @@ void QDeclarativeCompiler::reset(QDeclarativeCompiledData *data) { data->types.clear(); data->primitives.clear(); - data->floatData.clear(); - data->intData.clear(); - data->customTypeData.clear(); data->datas.clear(); data->bytecode.clear(); } diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h index 3697d3ace2..417a1fafb1 100644 --- a/src/declarative/qml/qdeclarativecompiler_p.h +++ b/src/declarative/qml/qdeclarativecompiler_p.h @@ -102,21 +102,12 @@ public: QDeclarativePropertyCache *createPropertyCache(QDeclarativeEngine *); }; QList types; - struct CustomTypeData - { - int index; - int type; - }; const QMetaObject *root; QAbstractDynamicMetaObject rootData; QDeclarativePropertyCache *rootPropertyCache; QList primitives; - QList floatData; - QList intData; - QList customTypeData; QList datas; - QList locations; QByteArray bytecode; QList cachedPrograms; QList cachedClosures; @@ -144,10 +135,6 @@ private: int indexForString(const QString &); int indexForByteArray(const QByteArray &); - int indexForFloat(float *, int); - int indexForInt(int *, int); - int indexForLocation(const QDeclarativeParser::Location &); - int indexForLocation(const QDeclarativeParser::LocationSpan &); int indexForUrl(const QUrl &); }; diff --git a/src/declarative/qml/qdeclarativeinstruction.cpp b/src/declarative/qml/qdeclarativeinstruction.cpp index 202e6461e4..f664913693 100644 --- a/src/declarative/qml/qdeclarativeinstruction.cpp +++ b/src/declarative/qml/qdeclarativeinstruction.cpp @@ -106,31 +106,31 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx) qWarning().nospace() << idx << "\t\t" << "STORE_DATE\t\t" << instr->storeDate.propertyIndex << "\t" << instr->storeDate.value; break; case QDeclarativeInstruction::StoreTime: - qWarning().nospace() << idx << "\t\t" << "STORE_TIME\t\t" << instr->storeTime.propertyIndex << "\t" << instr->storeTime.valueIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_TIME\t\t" << instr->storeTime.propertyIndex; break; case QDeclarativeInstruction::StoreDateTime: - qWarning().nospace() << idx << "\t\t" << "STORE_DATETIME\t\t" << instr->storeDateTime.propertyIndex << "\t" << instr->storeDateTime.valueIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_DATETIME\t\t" << instr->storeDateTime.propertyIndex; break; case QDeclarativeInstruction::StorePoint: - qWarning().nospace() << idx << "\t\t" << "STORE_POINT\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_POINT\t\t" << instr->storePoint.propertyIndex << "\t" << instr->storePoint.point.xp << "\t" << instr->storePoint.point.yp; break; case QDeclarativeInstruction::StorePointF: - qWarning().nospace() << idx << "\t\t" << "STORE_POINTF\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_POINTF\t\t" << instr->storePointF.propertyIndex << "\t" << instr->storePointF.point.xp << "\t" << instr->storePointF.point.yp; break; case QDeclarativeInstruction::StoreSize: - qWarning().nospace() << idx << "\t\t" << "STORE_SIZE\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_SIZE\t\t" << instr->storeSize.propertyIndex << "\t" << instr->storeSize.size.wd << "\t" << instr->storeSize.size.ht; break; case QDeclarativeInstruction::StoreSizeF: - qWarning().nospace() << idx << "\t\t" << "STORE_SIZEF\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex; + qWarning().nospace() << idx << "\t\t" << "STORE_SIZEF\t\t" << instr->storeSizeF.propertyIndex << "\t" << instr->storeSizeF.size.wd << "\t" << instr->storeSizeF.size.ht; break; case QDeclarativeInstruction::StoreRect: - qWarning().nospace() << idx << "\t\t" << "STORE_RECT\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.valueIndex; + 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 QDeclarativeInstruction::StoreRectF: - qWarning().nospace() << idx << "\t\t" << "STORE_RECTF\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.valueIndex; + 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 QDeclarativeInstruction::StoreVector3D: - qWarning().nospace() << idx << "\t\t" << "STORE_VECTOR3D\t\t" << instr->storeVector3D.propertyIndex << "\t" << instr->storeVector3D.valueIndex; + 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 QDeclarativeInstruction::StoreVariant: qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value); @@ -166,7 +166,7 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx) qWarning().nospace() << idx << "\t\t" << "ASSIGN_SIGNAL_OBJECT\t" << instr->assignSignalObject.signal << "\t\t\t" << datas.at(instr->assignSignalObject.signal); break; case QDeclarativeInstruction::AssignCustomType: - qWarning().nospace() << idx << "\t\t" << "ASSIGN_CUSTOMTYPE\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.valueIndex; + qWarning().nospace() << idx << "\t\t" << "ASSIGN_CUSTOMTYPE\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.primitive << "\t" << instr->assignCustomType.type; break; case QDeclarativeInstruction::StoreBinding: qWarning().nospace() << idx << "\t\t" << "STORE_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context; diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h index b436ce531f..cbf34a8baf 100644 --- a/src/declarative/qml/qdeclarativeinstruction_p.h +++ b/src/declarative/qml/qdeclarativeinstruction_p.h @@ -81,12 +81,12 @@ QT_BEGIN_NAMESPACE F(StoreDate, storeDate) \ F(StoreTime, storeTime) \ F(StoreDateTime, storeDateTime) \ - F(StorePoint, storeRealPair) \ - F(StorePointF, storeRealPair) \ - F(StoreSize, storeRealPair) \ - F(StoreSizeF, storeRealPair) \ + F(StorePoint, storePoint) \ + F(StorePointF, storePointF) \ + F(StoreSize, storeSize) \ + F(StoreSizeF, storeSizeF) \ F(StoreRect, storeRect) \ - F(StoreRectF, storeRect) \ + F(StoreRectF, storeRectF) \ F(StoreVector3D, storeVector3D) \ F(StoreObject, storeObject) \ F(AssignCustomType, assignCustomType) \ @@ -268,27 +268,45 @@ union QDeclarativeInstruction struct instr_storeTime { QML_INSTR_HEADER int propertyIndex; - int valueIndex; + struct QTime { + int mds; +#if defined(Q_OS_WINCE) + int startTick; +#endif + } time; }; struct instr_storeDateTime { QML_INSTR_HEADER int propertyIndex; - int valueIndex; - }; - struct instr_storeRealPair { - QML_INSTR_HEADER - int propertyIndex; - int valueIndex; + int date; + instr_storeTime::QTime time; }; struct instr_storeRect { QML_INSTR_HEADER int propertyIndex; - int valueIndex; + struct QRect { +#if defined(Q_OS_MAC) + int y1; + int x1; + int y2; + int x2; +#else + int x1; + int y1; + int x2; + int y2; +#endif + } rect; }; - struct instr_storeVector3D { + struct instr_storeRectF { QML_INSTR_HEADER int propertyIndex; - int valueIndex; + struct QRectF { + qreal xp; + qreal yp; + qreal w; + qreal h; + } rect; }; struct instr_storeObject { QML_INSTR_HEADER @@ -298,7 +316,8 @@ union QDeclarativeInstruction struct instr_assignCustomType { QML_INSTR_HEADER int propertyIndex; - int valueIndex; + int primitive; + int type; ushort line; }; struct instr_storeSignal { @@ -335,6 +354,52 @@ union QDeclarativeInstruction QML_INSTR_HEADER ushort line; }; + struct instr_storePoint { + QML_INSTR_HEADER + int propertyIndex; + struct QPoint { +#if defined(Q_OS_MAC) + int yp; + int xp; +#else + int xp; + int yp; +#endif + } 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; + }; instr_common common; instr_init init; @@ -362,8 +427,12 @@ union QDeclarativeInstruction instr_storeDate storeDate; instr_storeTime storeTime; instr_storeDateTime storeDateTime; - instr_storeRealPair storeRealPair; + instr_storePoint storePoint; + instr_storePointF storePointF; + instr_storeSize storeSize; + instr_storeSizeF storeSizeF; instr_storeRect storeRect; + instr_storeRectF storeRectF; instr_storeVector3D storeVector3D; instr_storeObject storeObject; instr_assignCustomType assignCustomType; diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index 03abae73a7..13539a0f1f 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -161,9 +161,6 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, const QList &types = comp->types; const QList &primitives = comp->primitives; const QList &datas = comp->datas; - const QList &customTypeData = comp->customTypeData; - const QList &intData = comp->intData; - const QList &floatData = comp->floatData; const QList &propertyCaches = comp->propertyCaches; const QList &scripts = comp->scripts; const QList &urls = comp->urls; @@ -475,12 +472,8 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.propertyIndex); - QTime t; - t.setHMS(intData.at(instr.valueIndex), - intData.at(instr.valueIndex+1), - intData.at(instr.valueIndex+2), - intData.at(instr.valueIndex+3)); - void *a[] = { &t, 0, &status, &flags }; + QTime *t = (QTime *)&instr.time; + void *a[] = { t, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); QML_END_INSTR(StoreTime) @@ -489,12 +482,8 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.propertyIndex); - QTime t; - t.setHMS(intData.at(instr.valueIndex+1), - intData.at(instr.valueIndex+2), - intData.at(instr.valueIndex+3), - intData.at(instr.valueIndex+4)); - QDateTime dt(QDate::fromJulianDay(intData.at(instr.valueIndex)), t); + QTime *t = (QTime *)&instr.time; + QDateTime dt(QDate::fromJulianDay(instr.date), *t); void *a[] = { &dt, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); @@ -504,9 +493,8 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.propertyIndex); - QPoint p = QPointF(floatData.at(instr.valueIndex), - floatData.at(instr.valueIndex+1)).toPoint(); - void *a[] = { &p, 0, &status, &flags }; + QPoint *p = (QPoint *)&instr.point; + void *a[] = { p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); QML_END_INSTR(StorePoint) @@ -515,9 +503,8 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.propertyIndex); - QPointF p(floatData.at(instr.valueIndex), - floatData.at(instr.valueIndex+1)); - void *a[] = { &p, 0, &status, &flags }; + QPointF *p = (QPointF *)&instr.point; + void *a[] = { p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); QML_END_INSTR(StorePointF) @@ -526,9 +513,8 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.propertyIndex); - QSize p = QSizeF(floatData.at(instr.valueIndex), - floatData.at(instr.valueIndex+1)).toSize(); - void *a[] = { &p, 0, &status, &flags }; + QSize *s = (QSize *)&instr.size; + void *a[] = { s, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); QML_END_INSTR(StoreSize) @@ -537,9 +523,8 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.propertyIndex); - QSizeF s(floatData.at(instr.valueIndex), - floatData.at(instr.valueIndex+1)); - void *a[] = { &s, 0, &status, &flags }; + QSizeF *s = (QSizeF *)&instr.size; + void *a[] = { s, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); QML_END_INSTR(StoreSizeF) @@ -548,11 +533,8 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.propertyIndex); - QRect r = QRectF(floatData.at(instr.valueIndex), - floatData.at(instr.valueIndex+1), - floatData.at(instr.valueIndex+2), - floatData.at(instr.valueIndex+3)).toRect(); - void *a[] = { &r, 0, &status, &flags }; + QRect *r = (QRect *)&instr.rect; + void *a[] = { r, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); QML_END_INSTR(StoreRect) @@ -561,11 +543,8 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.propertyIndex); - QRectF r(floatData.at(instr.valueIndex), - floatData.at(instr.valueIndex+1), - floatData.at(instr.valueIndex+2), - floatData.at(instr.valueIndex+3)); - void *a[] = { &r, 0, &status, &flags }; + QRectF *r = (QRectF *)&instr.rect; + void *a[] = { r, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); QML_END_INSTR(StoreRectF) @@ -574,10 +553,8 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.propertyIndex); - QVector3D p(floatData.at(instr.valueIndex), - floatData.at(instr.valueIndex+1), - floatData.at(instr.valueIndex+2)); - void *a[] = { &p, 0, &status, &flags }; + QVector3D *v = (QVector3D *)&instr.vector; + void *a[] = { v, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); QML_END_INSTR(StoreVector3D) @@ -596,15 +573,14 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.propertyIndex); - QDeclarativeCompiledData::CustomTypeData data = customTypeData.at(instr.valueIndex); - const QString &primitive = primitives.at(data.index); - QDeclarativeMetaType::StringConverter converter = - QDeclarativeMetaType::customStringConverter(data.type); + const QString &primitive = primitives.at(instr.primitive); + int type = instr.type; + QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(type); QVariant v = (*converter)(primitive); QMetaProperty prop = target->metaObject()->property(instr.propertyIndex); - if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type)) + if (v.isNull() || ((int)prop.type() != type && prop.userType() != type)) VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.line); void *a[] = { (void *)v.data(), 0, &status, &flags }; -- cgit v1.2.3 From 1332e9277cf68b0232abf666cd0c27c39b766ef1 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 5 May 2011 15:24:17 +1000 Subject: Compilation benchmark Change-Id: Iaa875817367d3a9600dd1ad685f996377af9f82d --- src/declarative/qml/parser/qdeclarativejsglobal_p.h | 2 +- src/declarative/qml/qdeclarativescriptparser_p.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/parser/qdeclarativejsglobal_p.h b/src/declarative/qml/parser/qdeclarativejsglobal_p.h index 776937cfdf..4fd8b84dcc 100644 --- a/src/declarative/qml/parser/qdeclarativejsglobal_p.h +++ b/src/declarative/qml/parser/qdeclarativejsglobal_p.h @@ -58,7 +58,7 @@ #else // !QT_CREATOR # define QT_QML_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE # define QT_QML_END_NAMESPACE QT_END_NAMESPACE -# define QML_PARSER_EXPORT +# define QML_PARSER_EXPORT Q_AUTOTEST_EXPORT #endif // QT_CREATOR #endif // QDECLARATIVEJSGLOBAL_P_H diff --git a/src/declarative/qml/qdeclarativescriptparser_p.h b/src/declarative/qml/qdeclarativescriptparser_p.h index fd89f757cc..f8cea76b11 100644 --- a/src/declarative/qml/qdeclarativescriptparser_p.h +++ b/src/declarative/qml/qdeclarativescriptparser_p.h @@ -67,7 +67,7 @@ QT_MODULE(Declarative) class QByteArray; class QDeclarativeScriptParserJsASTData; -class QDeclarativeScriptParser +class Q_AUTOTEST_EXPORT QDeclarativeScriptParser { public: class Import -- cgit v1.2.3 From e50b7c92998905efdd40314724480e3070bdbcb5 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Thu, 5 May 2011 17:19:01 +0200 Subject: Fix evaluation of boolean conditions Ensure that the operand of IR::OpIfTrue and IR::OpNot has boolean type. --- src/declarative/qml/v4/qdeclarativev4compiler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/v4/qdeclarativev4compiler.cpp b/src/declarative/qml/v4/qdeclarativev4compiler.cpp index a7eecce0c9..e67a3821d7 100644 --- a/src/declarative/qml/v4/qdeclarativev4compiler.cpp +++ b/src/declarative/qml/v4/qdeclarativev4compiler.cpp @@ -404,15 +404,15 @@ void QDeclarativeV4CompilerPrivate::visitUnop(IR::Unop *e) break; case IR::OpIfTrue: + convertToBool(e->expr, src); if (src != currentReg) { i.move_reg_reg(currentReg, src); gen(i); - } else { - // nothing to do } break; case IR::OpNot: + convertToBool(e->expr, src); i.unary_not(currentReg, src); gen(i); break; -- cgit v1.2.3 From 24bb6f90f828c0dbed06a56536a3f33b35d36506 Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Fri, 6 May 2011 13:18:19 +1000 Subject: Add unit test and documentation for module API Related to commit ae6c7a44394d4a5f943f1fc92f4de015ec7bcc96. Previously, only property access on module API was tested. This commit adds a test which calls a method on a module API. It also adds documentation for the qmlRegisterModuleApi functions. Task-number: QMLNG-33 Reviewed-by: Martin Jones --- src/declarative/qml/qdeclarative.h | 109 +++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarative.h b/src/declarative/qml/qdeclarative.h index 9227260b64..f3d91e80e9 100644 --- a/src/declarative/qml/qdeclarative.h +++ b/src/declarative/qml/qdeclarative.h @@ -410,6 +410,46 @@ QObject *qmlAttachedPropertiesObject(const QObject *obj, bool create = true) return qmlAttachedPropertiesObject(&idx, obj, &T::staticMetaObject, create); } +/*! + This function may be used to register a module API provider \a callback in a particular \a uri + with a version specified in \a versionMajor and \a versionMinor. + + Installing a module API into a uri allows developers to provide arbitrary functionality + (methods and properties) in a namespace that doesn't necessarily contain elements. + + A module API may be either a QObject or a QScriptValue. Only one module API provider + may be registered into any given namespace (combination of \a uri, \a majorVersion and \a minorVersion). + This function should be used to register a module API provider function which returns a QScriptValue as a module API. + + Usage: + \code + // first, define the module API provider function (callback). + static QScriptValue *example_qscriptvalue_module_api_provider(QDeclarativeEngine *engine, QScriptEngine *scriptEngine) + { + Q_UNUSED(engine) + + static int seedValue = 5; + QScriptValue example = scriptEngine->newObject(); + example.setProperty("someProperty", seedValue++); + return example; + } + + // second, register the module API provider with QML by calling this function in an initialization function. + ... + qmlRegisterModuleApi("Qt.example.qscriptvalueApi", 1, 0, example_qscriptvalue_module_api_provider); + ... + \endcode + + In order to use the registered module API in QML, you must import the module API. + \qml + import QtQuick 2.0 + import Qt.example.qscriptvalueApi 1.0 as ExampleApi + Item { + id: root + property int someValue: ExampleApi.someProperty + } + \endqml + */ inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMinor, QScriptValue (*callback)(QDeclarativeEngine *, QScriptEngine *)) { @@ -424,6 +464,75 @@ inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMi return QDeclarativePrivate::qmlregister(QDeclarativePrivate::ModuleApiRegistration, &api); } +/*! + This function may be used to register a module API provider \a callback in a particular \a uri + with a version specified in \a versionMajor and \a versionMinor. + + Installing a module API into a uri allows developers to provide arbitrary functionality + (methods and properties) in a namespace that doesn't necessarily contain elements. + + A module API may be either a QObject or a QScriptValue. Only one module API provider + may be registered into any given namespace (combination of \a uri, \a majorVersion and \a minorVersion). + This function should be used to register a module API provider function which returns a QObject as a module API. + + Usage: + \code + // first, define your QObject which provides the functionality. + class ModuleApiExample : public QObject + { + Q_OBJECT + Q_PROPERTY (int someProperty READ someProperty WRITE setSomeProperty NOTIFY somePropertyChanged) + + public: + ModuleApiExample(QObject* parent = 0) + : QObject(parent), m_someProperty(0) + { + } + + ~ModuleApiExample() {} + + Q_INVOKABLE int doSomething() { setSomeProperty(5); return m_someProperty; } + + int someProperty() const { return m_someProperty; } + void setSomeProperty(int val) { m_someProperty = val; emit somePropertyChanged(val); } + + signals: + void somePropertyChanged(int newValue); + + private: + int m_someProperty; + }; + + // second, define the module API provider function (callback). + static QObject *example_qobject_module_api_provider(QDeclarativeEngine *engine, QScriptEngine *scriptEngine) + { + Q_UNUSED(engine) + Q_UNUSED(scriptEngine) + + ModuleApiExample *example = new ModuleApiExample(); + return example; + } + + // third, register the module API provider with QML by calling this function in an initialization function. + ... + qmlRegisterModuleApi("Qt.example.qobjectApi", 1, 0, example_qobject_module_api_provider); + ... + \endcode + + In order to use the registered module API in QML, you must import the module API. + \qml + import QtQuick 2.0 + import Qt.example.qobjectApi 1.0 as ExampleApi + Item { + id: root + property int someValue: ExampleApi.someProperty + + Component.onCompleted: { + someValue = ExampleApi.doSomething() + } + } + \endqml + */ inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMinor, QObject *(*callback)(QDeclarativeEngine *, QScriptEngine *)) { -- cgit v1.2.3 From 56d4f0cc4552e11bee24cd977ada365df645889a Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 6 May 2011 10:08:27 +0200 Subject: Don't visit the sub tree of an AST::UiScriptBinding node. ProcessAST needs to look only at QML nodes and as we know it is impossible to find QML nodes inside JavaScript statements. --- src/declarative/qml/qdeclarativescriptparser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescriptparser.cpp index 352e341437..e9be923053 100644 --- a/src/declarative/qml/qdeclarativescriptparser.cpp +++ b/src/declarative/qml/qdeclarativescriptparser.cpp @@ -724,7 +724,7 @@ bool ProcessAST::visit(AST::UiScriptBinding *node) while (propertyCount--) _stateStack.pop(); - return true; + return false; } static QList collectCommas(AST::UiArrayMemberList *members) @@ -759,7 +759,7 @@ bool ProcessAST::visit(AST::UiArrayBinding *node) error.setLine(this->location(propertyName).start.line); error.setColumn(this->location(propertyName).start.column); _parser->_errors << error; - return 0; + return false; } accept(node->members); -- cgit v1.2.3 From 58ac6e8ee4a7eaa0eb3555a617f96843ec6ef34a Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Mon, 9 May 2011 12:48:21 +1000 Subject: Augment Documentation Task-number: QTBUG-19112 Reviewed-by: Martin Jones --- src/declarative/qml/qdeclarativeengine.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index ba0ddbbfaf..2ed10804b2 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -1350,6 +1350,8 @@ Example (where \c parentItem is the id of an existing QML item): In the case of an error, a QtScript Error object is thrown. This object has an additional property, \c qmlErrors, which is an array of the errors encountered. Each object in this array has the members \c lineNumber, \c columnNumber, \c fileName and \c message. +For example, if the above snippet had misspelled color as 'colro' then the array would contain an object like the following: +{ "lineNumber" : 1, "columnNumber" : 32, "fileName" : "dynamicSnippet1", "message" : "Cannot assign to non-existent property \"colro\""}. Note that this function returns immediately, and therefore may not work if the \a qml string loads new components (that is, external QML files that have not yet been loaded). -- cgit v1.2.3 From 7c31b7a96944409573dc85a8a1709e799f4aa446 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 9 May 2011 10:30:02 +0200 Subject: Fix wrong usages of #include directives in the QML/JS parser. Reviewed-by: Aaron Kennedy --- src/declarative/qml/parser/qdeclarativejs.g | 18 +++++++++--------- src/declarative/qml/parser/qdeclarativejsast.cpp | 4 ++-- src/declarative/qml/parser/qdeclarativejsast_p.h | 4 ++-- src/declarative/qml/parser/qdeclarativejsastfwd_p.h | 2 +- .../qml/parser/qdeclarativejsastvisitor.cpp | 2 +- .../qml/parser/qdeclarativejsastvisitor_p.h | 4 ++-- src/declarative/qml/parser/qdeclarativejsengine_p.cpp | 6 +++--- src/declarative/qml/parser/qdeclarativejsengine_p.h | 4 ++-- src/declarative/qml/parser/qdeclarativejslexer.cpp | 8 ++++---- src/declarative/qml/parser/qdeclarativejslexer_p.h | 2 +- .../qml/parser/qdeclarativejsmemorypool_p.h | 2 +- src/declarative/qml/parser/qdeclarativejsnodepool_p.h | 4 ++-- src/declarative/qml/parser/qdeclarativejsparser.cpp | 10 +++++----- src/declarative/qml/parser/qdeclarativejsparser_p.h | 8 ++++---- 14 files changed, 39 insertions(+), 39 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/parser/qdeclarativejs.g b/src/declarative/qml/parser/qdeclarativejs.g index 0e7454e42b..ac46fd725f 100644 --- a/src/declarative/qml/parser/qdeclarativejs.g +++ b/src/declarative/qml/parser/qdeclarativejs.g @@ -127,10 +127,10 @@ #include -#include "private/qdeclarativejsengine_p.h" -#include "private/qdeclarativejslexer_p.h" -#include "private/qdeclarativejsast_p.h" -#include "private/qdeclarativejsnodepool_p.h" +#include "qdeclarativejsengine_p.h" +#include "qdeclarativejslexer_p.h" +#include "qdeclarativejsast_p.h" +#include "qdeclarativejsnodepool_p.h" ./ @@ -195,10 +195,10 @@ #ifndef QDECLARATIVEJSPARSER_P_H #define QDECLARATIVEJSPARSER_P_H -#include "private/qdeclarativejsglobal_p.h" -#include "private/qdeclarativejsgrammar_p.h" -#include "private/qdeclarativejsast_p.h" -#include "private/qdeclarativejsengine_p.h" +#include "qdeclarativejsglobal_p.h" +#include "qdeclarativejsgrammar_p.h" +#include "qdeclarativejsast_p.h" +#include "qdeclarativejsengine_p.h" #include #include @@ -375,7 +375,7 @@ protected: /. -#include "private/qdeclarativejsparser_p.h" +#include "qdeclarativejsparser_p.h" #include // diff --git a/src/declarative/qml/parser/qdeclarativejsast.cpp b/src/declarative/qml/parser/qdeclarativejsast.cpp index afb399abf0..e59ffd753c 100644 --- a/src/declarative/qml/parser/qdeclarativejsast.cpp +++ b/src/declarative/qml/parser/qdeclarativejsast.cpp @@ -39,9 +39,9 @@ ** ****************************************************************************/ -#include "private/qdeclarativejsast_p.h" +#include "qdeclarativejsast_p.h" -#include "private/qdeclarativejsastvisitor_p.h" +#include "qdeclarativejsastvisitor_p.h" QT_QML_BEGIN_NAMESPACE diff --git a/src/declarative/qml/parser/qdeclarativejsast_p.h b/src/declarative/qml/parser/qdeclarativejsast_p.h index 956d6e7545..cd4118720b 100644 --- a/src/declarative/qml/parser/qdeclarativejsast_p.h +++ b/src/declarative/qml/parser/qdeclarativejsast_p.h @@ -53,8 +53,8 @@ // We mean it. // -#include "private/qdeclarativejsastvisitor_p.h" -#include "private/qdeclarativejsglobal_p.h" +#include "qdeclarativejsastvisitor_p.h" +#include "qdeclarativejsglobal_p.h" #include diff --git a/src/declarative/qml/parser/qdeclarativejsastfwd_p.h b/src/declarative/qml/parser/qdeclarativejsastfwd_p.h index 8a20ab25c4..8344d5476b 100644 --- a/src/declarative/qml/parser/qdeclarativejsastfwd_p.h +++ b/src/declarative/qml/parser/qdeclarativejsastfwd_p.h @@ -42,7 +42,7 @@ #ifndef QDECLARATIVEJSAST_FWD_P_H #define QDECLARATIVEJSAST_FWD_P_H -#include "private/qdeclarativejsglobal_p.h" +#include "qdeclarativejsglobal_p.h" #include diff --git a/src/declarative/qml/parser/qdeclarativejsastvisitor.cpp b/src/declarative/qml/parser/qdeclarativejsastvisitor.cpp index 8df755a062..b4eecc18ad 100644 --- a/src/declarative/qml/parser/qdeclarativejsastvisitor.cpp +++ b/src/declarative/qml/parser/qdeclarativejsastvisitor.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "private/qdeclarativejsastvisitor_p.h" +#include "qdeclarativejsastvisitor_p.h" QT_QML_BEGIN_NAMESPACE diff --git a/src/declarative/qml/parser/qdeclarativejsastvisitor_p.h b/src/declarative/qml/parser/qdeclarativejsastvisitor_p.h index 519b8c8880..6ef7c81a28 100644 --- a/src/declarative/qml/parser/qdeclarativejsastvisitor_p.h +++ b/src/declarative/qml/parser/qdeclarativejsastvisitor_p.h @@ -53,8 +53,8 @@ // We mean it. // -#include "private/qdeclarativejsastfwd_p.h" -#include "private/qdeclarativejsglobal_p.h" +#include "qdeclarativejsastfwd_p.h" +#include "qdeclarativejsglobal_p.h" QT_QML_BEGIN_NAMESPACE diff --git a/src/declarative/qml/parser/qdeclarativejsengine_p.cpp b/src/declarative/qml/parser/qdeclarativejsengine_p.cpp index ec9271a0de..4d135c2c54 100644 --- a/src/declarative/qml/parser/qdeclarativejsengine_p.cpp +++ b/src/declarative/qml/parser/qdeclarativejsengine_p.cpp @@ -39,10 +39,10 @@ ** ****************************************************************************/ -#include "private/qdeclarativejsengine_p.h" +#include "qdeclarativejsengine_p.h" -#include "private/qdeclarativejsglobal_p.h" -#include "private/qdeclarativejsnodepool_p.h" +#include "qdeclarativejsglobal_p.h" +#include "qdeclarativejsnodepool_p.h" #include #include diff --git a/src/declarative/qml/parser/qdeclarativejsengine_p.h b/src/declarative/qml/parser/qdeclarativejsengine_p.h index cacc9612fa..42db3e2188 100644 --- a/src/declarative/qml/parser/qdeclarativejsengine_p.h +++ b/src/declarative/qml/parser/qdeclarativejsengine_p.h @@ -53,8 +53,8 @@ // We mean it. // -#include "private/qdeclarativejsglobal_p.h" -#include "private/qdeclarativejsastfwd_p.h" +#include "qdeclarativejsglobal_p.h" +#include "qdeclarativejsastfwd_p.h" #include #include diff --git a/src/declarative/qml/parser/qdeclarativejslexer.cpp b/src/declarative/qml/parser/qdeclarativejslexer.cpp index 4dfef45ed5..f5fb791405 100644 --- a/src/declarative/qml/parser/qdeclarativejslexer.cpp +++ b/src/declarative/qml/parser/qdeclarativejslexer.cpp @@ -43,11 +43,11 @@ #include #endif -#include "private/qdeclarativejslexer_p.h" +#include "qdeclarativejslexer_p.h" -#include "private/qdeclarativejsglobal_p.h" -#include "private/qdeclarativejsengine_p.h" -#include "private/qdeclarativejsgrammar_p.h" +#include "qdeclarativejsglobal_p.h" +#include "qdeclarativejsengine_p.h" +#include "qdeclarativejsgrammar_p.h" #include diff --git a/src/declarative/qml/parser/qdeclarativejslexer_p.h b/src/declarative/qml/parser/qdeclarativejslexer_p.h index e41337dd8b..8febb54a86 100644 --- a/src/declarative/qml/parser/qdeclarativejslexer_p.h +++ b/src/declarative/qml/parser/qdeclarativejslexer_p.h @@ -53,7 +53,7 @@ // We mean it. // -#include "private/qdeclarativejsglobal_p.h" +#include "qdeclarativejsglobal_p.h" #include diff --git a/src/declarative/qml/parser/qdeclarativejsmemorypool_p.h b/src/declarative/qml/parser/qdeclarativejsmemorypool_p.h index 7eea9750a3..ebf75d1711 100644 --- a/src/declarative/qml/parser/qdeclarativejsmemorypool_p.h +++ b/src/declarative/qml/parser/qdeclarativejsmemorypool_p.h @@ -53,7 +53,7 @@ // We mean it. // -#include "private/qdeclarativejsglobal_p.h" +#include "qdeclarativejsglobal_p.h" #include #include diff --git a/src/declarative/qml/parser/qdeclarativejsnodepool_p.h b/src/declarative/qml/parser/qdeclarativejsnodepool_p.h index fde4897873..ca3841c642 100644 --- a/src/declarative/qml/parser/qdeclarativejsnodepool_p.h +++ b/src/declarative/qml/parser/qdeclarativejsnodepool_p.h @@ -53,8 +53,8 @@ // We mean it. // -#include "private/qdeclarativejsglobal_p.h" -#include "private/qdeclarativejsmemorypool_p.h" +#include "qdeclarativejsglobal_p.h" +#include "qdeclarativejsmemorypool_p.h" #include #include diff --git a/src/declarative/qml/parser/qdeclarativejsparser.cpp b/src/declarative/qml/parser/qdeclarativejsparser.cpp index 9a93fa1b4c..118dcc6538 100644 --- a/src/declarative/qml/parser/qdeclarativejsparser.cpp +++ b/src/declarative/qml/parser/qdeclarativejsparser.cpp @@ -44,14 +44,14 @@ #include -#include "private/qdeclarativejsengine_p.h" -#include "private/qdeclarativejslexer_p.h" -#include "private/qdeclarativejsast_p.h" -#include "private/qdeclarativejsnodepool_p.h" +#include "qdeclarativejsengine_p.h" +#include "qdeclarativejslexer_p.h" +#include "qdeclarativejsast_p.h" +#include "qdeclarativejsnodepool_p.h" -#include "private/qdeclarativejsparser_p.h" +#include "qdeclarativejsparser_p.h" #include // diff --git a/src/declarative/qml/parser/qdeclarativejsparser_p.h b/src/declarative/qml/parser/qdeclarativejsparser_p.h index ad46bfff1d..5eec1a4850 100644 --- a/src/declarative/qml/parser/qdeclarativejsparser_p.h +++ b/src/declarative/qml/parser/qdeclarativejsparser_p.h @@ -59,10 +59,10 @@ #ifndef QDECLARATIVEJSPARSER_P_H #define QDECLARATIVEJSPARSER_P_H -#include "private/qdeclarativejsglobal_p.h" -#include "private/qdeclarativejsgrammar_p.h" -#include "private/qdeclarativejsast_p.h" -#include "private/qdeclarativejsengine_p.h" +#include "qdeclarativejsglobal_p.h" +#include "qdeclarativejsgrammar_p.h" +#include "qdeclarativejsast_p.h" +#include "qdeclarativejsengine_p.h" #include #include -- cgit v1.2.3 From 4ff72975b6501a0003329bb8183479d4df5eda4d Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Tue, 10 May 2011 12:10:06 +1000 Subject: Add user documentation for scarce resource properties Relates to commit 59ace5c5a666b1588560d2aeaa79a57da535e863. Task-number: QMLNG-18 Reviewed-by: Aaron Kennedy Change-Id: I216ced4c663ebab8003978999dc16ac809443a5f --- .../qml/qdeclarativescarceresourcescriptclass.cpp | 36 +++++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativescarceresourcescriptclass.cpp b/src/declarative/qml/qdeclarativescarceresourcescriptclass.cpp index 121d0a1a35..d94e2d9332 100644 --- a/src/declarative/qml/qdeclarativescarceresourcescriptclass.cpp +++ b/src/declarative/qml/qdeclarativescarceresourcescriptclass.cpp @@ -144,9 +144,22 @@ QDeclarativeScarceResourceScriptClass::property(Object *object, const Identifier } /* - The user explicitly wants to preserve the resource. - We remove the scarce resource from the engine's linked list - of resources to release after evaluation completes. + This method is called when the user explicitly calls the "preserve" method of a scarce resource in JavaScript + within the specified evaluation context \a context of the script engine \a engine. + Calling this function signifies that the user explicitly wants to preserve the resource rather than let it + be automatically released once evaluation of the expression is complete. + This function removes the internal scarce resource from the declarative engine's linked list of scarce resources + to release after evaluation of the expression completes. This means that the resource will only be truly + released when the JavaScript engine's garbage collector is run. + + Example: + \qml + function getIcon(model) { + var icon = model.avatar; // a pixmap property + icon.preserve(); // explicitly preserves the resource + return icon; // a valid variant will be returned + } + \endqml */ QScriptValue QDeclarativeScarceResourceScriptClass::preserve(QScriptContext *context, QScriptEngine *engine) { @@ -168,8 +181,21 @@ QScriptValue QDeclarativeScarceResourceScriptClass::preserve(QScriptContext *con } /* - The user explicitly wants to release the resource. - We set the internal scarce resource variant to the invalid variant. + This method is called when the user explicitly calls the "destroy" method of a scarce resource in JavaScript + within the specified evaluation context \a context of the script engine \a engine. + Calling this function signifies that the user explicitly wants to release the resource. + This function sets the internal scarce resource variant to the invalid variant, in order to release the original resource, + and then removes the resource from the declarative engine's linked-list of scarce resources to + to release after evaluation of the expression completes, as it has already been released. + + Example: + \qml + function getIcon(model) { + var icon = model.avatar; // a pixmap property + icon.destroy(); // explicitly releases the resource + return icon; // an invalid variant will be returned + } + \endqml */ QScriptValue QDeclarativeScarceResourceScriptClass::destroy(QScriptContext *context, QScriptEngine *engine) { -- cgit v1.2.3 From 6fe601e4bcff790a335de949a20e223380ce9408 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 12 May 2011 14:34:48 +1000 Subject: Improve error message for invalid image provider name. Also fix broken qdeclarativeimageprovider test. --- src/declarative/qml/qdeclarativeengine.cpp | 2 +- src/declarative/qml/qdeclarativeimageprovider.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 2ed10804b2..eb2974f46a 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -837,7 +837,7 @@ QDeclarativeImageProvider::ImageType QDeclarativeEnginePrivate::getImageProvider locker.unlock(); if (provider) return provider->imageType(); - return static_cast(-1); + return QDeclarativeImageProvider::Invalid; } QSGTexture *QDeclarativeEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size) diff --git a/src/declarative/qml/qdeclarativeimageprovider.h b/src/declarative/qml/qdeclarativeimageprovider.h index e5e80f227c..512724b947 100644 --- a/src/declarative/qml/qdeclarativeimageprovider.h +++ b/src/declarative/qml/qdeclarativeimageprovider.h @@ -60,7 +60,8 @@ public: enum ImageType { Image, Pixmap, - Texture + Texture, + Invalid }; QDeclarativeImageProvider(ImageType type); -- cgit v1.2.3 From f31d94f2d4438106558dede0de1a423cade960a9 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Thu, 12 May 2011 11:31:31 +0200 Subject: Fix the QML front-end to allow side effects in the initializer. Task-number: QTBUG-15117 --- src/declarative/qml/parser/qdeclarativejs.g | 35 +- src/declarative/qml/parser/qdeclarativejsast.cpp | 2 +- src/declarative/qml/parser/qdeclarativejsast_p.h | 8 +- .../qml/parser/qdeclarativejsgrammar.cpp | 1490 ++++++++++---------- .../qml/parser/qdeclarativejsgrammar_p.h | 14 +- .../qml/parser/qdeclarativejsparser.cpp | 424 +++--- .../qml/parser/qdeclarativejsparser_p.h | 4 +- src/declarative/qml/qdeclarativescriptparser.cpp | 25 +- 8 files changed, 1010 insertions(+), 992 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/parser/qdeclarativejs.g b/src/declarative/qml/parser/qdeclarativejs.g index ac46fd725f..fdb46d71ce 100644 --- a/src/declarative/qml/parser/qdeclarativejs.g +++ b/src/declarative/qml/parser/qdeclarativejs.g @@ -782,19 +782,14 @@ case $rule_number: { } break; ./ -UiObjectMember: UiQualifiedId T_COLON Block ; -/.case $rule_number:./ - -UiObjectMember: UiQualifiedId T_COLON EmptyStatement ; -/.case $rule_number:./ - -UiObjectMember: UiQualifiedId T_COLON ExpressionStatement ; -/.case $rule_number:./ - -UiObjectMember: UiQualifiedId T_COLON IfStatement ; --- ### do we really want if statement in a binding? -/.case $rule_number:./ +UiScriptStatement: Block ; +UiScriptStatement: EmptyStatement ; +UiScriptStatement: ExpressionStatement ; +UiScriptStatement: IfStatement ; --- ### do we really want if statement in a binding? +UiObjectMember: UiQualifiedId T_COLON UiScriptStatement ; /. +case $rule_number: { AST::UiScriptBinding *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId, sym(3).Statement); @@ -922,51 +917,45 @@ case $rule_number: { } break; ./ -UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_COLON Expression T_AUTOMATIC_SEMICOLON ; -UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_COLON Expression T_SEMICOLON ; +UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ; /. case $rule_number: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(3).sval, - sym(5).Expression); + sym(5).Statement); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); node->colonToken = loc(4); - node->semicolonToken = loc(6); sym(1).Node = node; } break; ./ -UiObjectMember: T_READONLY T_PROPERTY UiPropertyType JsIdentifier T_COLON Expression T_AUTOMATIC_SEMICOLON ; -UiObjectMember: T_READONLY T_PROPERTY UiPropertyType JsIdentifier T_COLON Expression T_SEMICOLON ; +UiObjectMember: T_READONLY T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ; /. case $rule_number: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(4).sval, - sym(6).Expression); + sym(6).Statement); node->isReadonlyMember = true; node->readonlyToken = loc(1); node->propertyToken = loc(2); node->typeToken = loc(3); node->identifierToken = loc(4); node->colonToken = loc(5); - node->semicolonToken = loc(7); sym(1).Node = node; } break; ./ -UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_COLON Expression T_AUTOMATIC_SEMICOLON ; -UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_COLON Expression T_SEMICOLON ; +UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ; /. case $rule_number: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(4).sval, - sym(6).Expression); + sym(6).Statement); node->isDefaultMember = true; node->defaultToken = loc(1); node->propertyToken = loc(2); node->typeToken = loc(3); node->identifierToken = loc(4); node->colonToken = loc(5); - node->semicolonToken = loc(7); sym(1).Node = node; } break; ./ diff --git a/src/declarative/qml/parser/qdeclarativejsast.cpp b/src/declarative/qml/parser/qdeclarativejsast.cpp index e59ffd753c..599f7bfd9e 100644 --- a/src/declarative/qml/parser/qdeclarativejsast.cpp +++ b/src/declarative/qml/parser/qdeclarativejsast.cpp @@ -836,7 +836,7 @@ void UiFormal::accept0(Visitor *visitor) void UiPublicMember::accept0(Visitor *visitor) { if (visitor->visit(this)) { - accept(expression, visitor); + accept(statement, visitor); accept(binding, visitor); } diff --git a/src/declarative/qml/parser/qdeclarativejsast_p.h b/src/declarative/qml/parser/qdeclarativejsast_p.h index cd4118720b..c82a8dbc1a 100644 --- a/src/declarative/qml/parser/qdeclarativejsast_p.h +++ b/src/declarative/qml/parser/qdeclarativejsast_p.h @@ -2342,13 +2342,13 @@ public: UiPublicMember(NameId *memberType, NameId *name) - : type(Property), typeModifier(0), memberType(memberType), name(name), expression(0), binding(0), isDefaultMember(false), isReadonlyMember(false), parameters(0) + : type(Property), typeModifier(0), memberType(memberType), name(name), statement(0), binding(0), isDefaultMember(false), isReadonlyMember(false), parameters(0) { kind = K; } UiPublicMember(NameId *memberType, NameId *name, - ExpressionNode *expression) - : type(Property), typeModifier(0), memberType(memberType), name(name), expression(expression), binding(0), isDefaultMember(false), isReadonlyMember(false), parameters(0) + Statement *statement) + : type(Property), typeModifier(0), memberType(memberType), name(name), statement(statement), binding(0), isDefaultMember(false), isReadonlyMember(false), parameters(0) { kind = K; } virtual SourceLocation firstSourceLocation() const @@ -2376,7 +2376,7 @@ public: NameId *typeModifier; NameId *memberType; NameId *name; - ExpressionNode *expression; // initialized with a JS expression + Statement *statement; // initialized with a JS expression UiObjectMember *binding; // initialized with a QML object or array. bool isDefaultMember; bool isReadonlyMember; diff --git a/src/declarative/qml/parser/qdeclarativejsgrammar.cpp b/src/declarative/qml/parser/qdeclarativejsgrammar.cpp index ea19e1ccd5..64b62347a7 100644 --- a/src/declarative/qml/parser/qdeclarativejsgrammar.cpp +++ b/src/declarative/qml/parser/qdeclarativejsgrammar.cpp @@ -61,462 +61,469 @@ const short QDeclarativeJSGrammar::lhs [] = { 101, 101, 101, 101, 101, 101, 102, 108, 108, 111, 111, 113, 112, 112, 112, 112, 112, 112, 112, 112, 115, 110, 109, 118, 118, 119, 119, 120, 120, 117, - 106, 106, 106, 106, 106, 106, 106, 106, 126, 126, - 126, 127, 127, 128, 128, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 122, 122, 122, 122, 106, 127, + 127, 127, 128, 128, 129, 129, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, - 106, 106, 106, 106, 106, 116, 116, 116, 116, 116, - 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, - 131, 131, 131, 131, 131, 131, 131, 131, 121, 133, - 133, 133, 133, 132, 132, 135, 135, 137, 137, 137, - 137, 137, 137, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 139, 139, 114, 114, 114, 114, - 114, 142, 142, 143, 143, 143, 143, 141, 141, 144, - 144, 145, 145, 146, 146, 146, 147, 147, 147, 147, - 147, 147, 147, 147, 147, 147, 148, 148, 148, 148, - 149, 149, 149, 150, 150, 150, 150, 151, 151, 151, - 151, 151, 151, 151, 152, 152, 152, 152, 152, 152, - 153, 153, 153, 153, 153, 154, 154, 154, 154, 154, - 155, 155, 156, 156, 157, 157, 158, 158, 159, 159, - 160, 160, 161, 161, 162, 162, 163, 163, 164, 164, - 165, 165, 166, 166, 136, 136, 167, 167, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 104, 104, 169, 169, 170, 170, 171, 171, 103, 103, + 106, 106, 106, 116, 116, 116, 116, 116, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 121, 134, 134, 134, + 134, 133, 133, 136, 136, 138, 138, 138, 138, 138, + 138, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 140, 140, 114, 114, 114, 114, 114, 143, + 143, 144, 144, 144, 144, 142, 142, 145, 145, 146, + 146, 147, 147, 147, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 149, 149, 149, 149, 150, 150, + 150, 151, 151, 151, 151, 152, 152, 152, 152, 152, + 152, 152, 153, 153, 153, 153, 153, 153, 154, 154, + 154, 154, 154, 155, 155, 155, 155, 155, 156, 156, + 157, 157, 158, 158, 159, 159, 160, 160, 161, 161, + 162, 162, 163, 163, 164, 164, 165, 165, 166, 166, + 167, 167, 137, 137, 168, 168, 169, 169, 169, 169, + 169, 169, 169, 169, 169, 169, 169, 169, 104, 104, + 170, 170, 171, 171, 172, 172, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, - 103, 103, 103, 122, 183, 183, 182, 182, 130, 130, - 184, 184, 185, 185, 187, 187, 186, 188, 191, 189, - 189, 192, 190, 190, 123, 124, 124, 125, 125, 172, - 172, 172, 172, 172, 172, 172, 173, 173, 173, 173, - 174, 174, 174, 174, 175, 175, 176, 178, 193, 193, - 196, 196, 194, 194, 197, 195, 177, 177, 177, 179, - 179, 180, 180, 180, 198, 199, 181, 181, 129, 140, - 203, 203, 200, 200, 201, 201, 204, 107, 205, 205, - 105, 105, 202, 202, 134, 134, 206}; + 103, 123, 184, 184, 183, 183, 131, 131, 185, 185, + 186, 186, 188, 188, 187, 189, 192, 190, 190, 193, + 191, 191, 124, 125, 125, 126, 126, 173, 173, 173, + 173, 173, 173, 173, 174, 174, 174, 174, 175, 175, + 175, 175, 176, 176, 177, 179, 194, 194, 197, 197, + 195, 195, 198, 196, 178, 178, 178, 180, 180, 181, + 181, 181, 199, 200, 182, 182, 130, 141, 204, 204, + 201, 201, 202, 202, 205, 107, 206, 206, 105, 105, + 203, 203, 135, 135, 207}; const short QDeclarativeJSGrammar::rhs [] = { 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 2, 2, 3, 3, 5, 5, 4, 4, 2, 0, 1, 1, 2, 1, 3, 2, 3, 2, - 1, 5, 4, 4, 3, 3, 3, 3, 1, 1, - 1, 0, 1, 2, 4, 6, 6, 3, 3, 7, - 7, 4, 4, 5, 5, 6, 6, 7, 7, 7, - 7, 10, 6, 1, 1, 1, 1, 1, 1, 1, + 1, 5, 4, 4, 1, 1, 1, 1, 3, 1, + 1, 1, 0, 1, 2, 4, 6, 6, 3, 3, + 7, 7, 4, 4, 5, 5, 5, 6, 6, 10, + 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 3, 4, 5, 3, 4, 3, 1, 1, 2, 3, + 4, 1, 2, 3, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 3, 3, 4, 5, 3, 4, 3, 1, 1, - 2, 3, 4, 1, 2, 3, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 4, 3, - 5, 1, 2, 4, 4, 4, 3, 0, 1, 1, - 3, 1, 1, 1, 2, 2, 1, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 3, 3, 3, - 1, 3, 3, 1, 3, 3, 3, 1, 3, 3, - 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, - 1, 3, 3, 3, 3, 1, 3, 3, 3, 3, - 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, + 1, 1, 1, 1, 1, 1, 4, 3, 5, 1, + 2, 4, 4, 4, 3, 0, 1, 1, 3, 1, + 1, 1, 2, 2, 1, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 1, 3, 3, 3, 1, 3, + 3, 1, 3, 3, 3, 1, 3, 3, 3, 3, + 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, + 3, 3, 3, 1, 3, 3, 3, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, - 1, 5, 1, 5, 1, 3, 1, 3, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3, 0, 1, 1, 3, 0, 1, 1, 1, + 1, 3, 1, 3, 1, 3, 1, 3, 1, 5, + 1, 5, 1, 3, 1, 3, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 3, 1, 2, 0, 1, 3, 3, - 1, 1, 1, 3, 1, 3, 2, 2, 2, 0, - 1, 2, 0, 1, 1, 2, 2, 7, 5, 7, - 7, 5, 9, 10, 7, 8, 2, 2, 3, 3, - 2, 2, 3, 3, 3, 3, 5, 5, 3, 5, - 1, 2, 0, 1, 4, 3, 3, 3, 3, 3, - 3, 3, 3, 4, 5, 2, 2, 2, 8, 8, - 1, 3, 0, 1, 0, 1, 1, 1, 1, 2, - 1, 1, 0, 1, 0, 1, 2}; + 1, 3, 1, 2, 0, 1, 3, 3, 1, 1, + 1, 3, 1, 3, 2, 2, 2, 0, 1, 2, + 0, 1, 1, 2, 2, 7, 5, 7, 7, 5, + 9, 10, 7, 8, 2, 2, 3, 3, 2, 2, + 3, 3, 3, 3, 5, 5, 3, 5, 1, 2, + 0, 1, 4, 3, 3, 3, 3, 3, 3, 3, + 3, 4, 5, 2, 2, 2, 8, 8, 1, 3, + 0, 1, 0, 1, 1, 1, 1, 2, 1, 1, + 0, 1, 0, 1, 2}; const short QDeclarativeJSGrammar::action_default [] = { - 0, 0, 0, 0, 0, 0, 22, 0, 174, 241, - 205, 213, 209, 153, 225, 201, 3, 138, 72, 154, - 217, 221, 142, 171, 152, 157, 137, 191, 178, 0, - 79, 80, 75, 343, 66, 345, 0, 0, 0, 0, - 77, 0, 0, 73, 76, 70, 0, 0, 67, 69, - 68, 78, 71, 0, 74, 0, 0, 167, 0, 0, - 154, 173, 156, 155, 0, 0, 0, 169, 170, 168, - 172, 0, 202, 0, 0, 0, 0, 192, 0, 0, - 0, 0, 0, 0, 182, 0, 0, 0, 176, 177, - 175, 180, 184, 183, 181, 179, 194, 193, 195, 0, - 210, 0, 206, 0, 0, 148, 135, 147, 136, 104, - 105, 106, 131, 107, 132, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 117, 118, 119, 120, 133, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 134, - 0, 0, 146, 242, 149, 0, 150, 0, 151, 145, - 0, 238, 231, 229, 236, 237, 235, 234, 240, 233, - 232, 230, 239, 226, 0, 214, 0, 0, 218, 0, - 0, 222, 0, 0, 148, 140, 0, 139, 0, 144, - 158, 0, 344, 333, 334, 0, 331, 0, 332, 0, - 335, 249, 256, 255, 263, 251, 0, 252, 336, 0, - 342, 253, 254, 259, 257, 339, 337, 341, 260, 0, - 271, 0, 0, 0, 0, 343, 66, 0, 345, 67, - 243, 285, 68, 0, 0, 0, 272, 0, 0, 261, - 262, 0, 250, 258, 286, 287, 330, 340, 0, 301, - 302, 303, 304, 0, 297, 298, 299, 300, 327, 328, - 0, 0, 0, 0, 0, 290, 291, 247, 245, 207, - 215, 211, 227, 203, 248, 0, 154, 219, 223, 196, - 185, 0, 0, 204, 0, 0, 0, 0, 197, 0, - 0, 0, 0, 0, 189, 187, 190, 188, 186, 199, - 198, 200, 0, 212, 0, 208, 0, 246, 154, 0, - 228, 243, 244, 0, 243, 0, 0, 293, 0, 0, - 0, 295, 0, 216, 0, 0, 220, 0, 0, 224, - 283, 0, 275, 284, 278, 0, 282, 0, 243, 276, - 0, 243, 0, 0, 294, 0, 0, 0, 296, 344, - 333, 0, 0, 335, 0, 329, 0, 319, 0, 0, - 0, 289, 0, 288, 0, 346, 0, 103, 265, 268, - 0, 104, 271, 107, 132, 109, 110, 75, 114, 115, - 66, 116, 119, 73, 76, 67, 243, 68, 78, 122, - 71, 124, 74, 126, 127, 272, 129, 130, 134, 0, - 96, 0, 0, 98, 102, 100, 87, 99, 101, 0, - 97, 86, 266, 264, 142, 143, 148, 0, 141, 0, - 318, 0, 305, 306, 0, 317, 0, 0, 0, 308, - 313, 311, 314, 0, 0, 312, 313, 0, 309, 0, - 310, 267, 316, 0, 267, 315, 0, 320, 321, 0, - 267, 322, 323, 0, 0, 324, 0, 0, 0, 325, - 326, 160, 159, 0, 0, 0, 292, 0, 0, 0, - 307, 280, 273, 0, 281, 277, 0, 279, 269, 0, - 270, 274, 90, 0, 0, 94, 81, 0, 83, 92, - 0, 84, 93, 95, 85, 91, 82, 0, 88, 164, - 162, 166, 163, 161, 165, 6, 338, 4, 2, 64, - 89, 0, 0, 67, 69, 68, 31, 5, 0, 65, - 0, 41, 40, 39, 0, 0, 54, 0, 55, 0, - 60, 61, 0, 41, 0, 0, 0, 0, 0, 50, - 0, 51, 0, 0, 26, 0, 0, 62, 27, 0, - 30, 28, 24, 0, 29, 25, 0, 52, 0, 53, - 0, 142, 0, 56, 57, 63, 0, 0, 0, 0, - 0, 58, 59, 0, 48, 42, 49, 43, 0, 0, - 0, 0, 45, 0, 46, 47, 44, 0, 0, 35, - 36, 37, 38, 142, 267, 0, 0, 104, 271, 107, - 132, 109, 110, 75, 114, 115, 66, 116, 119, 73, - 76, 67, 243, 68, 78, 122, 71, 124, 74, 126, - 127, 272, 129, 130, 134, 0, 32, 33, 0, 34, - 8, 0, 10, 0, 9, 0, 1, 21, 12, 0, - 13, 0, 14, 0, 19, 20, 0, 15, 16, 0, - 17, 18, 11, 23, 7, 347}; + 0, 0, 0, 0, 0, 0, 22, 0, 172, 239, + 203, 211, 207, 151, 223, 199, 3, 136, 70, 152, + 215, 219, 140, 169, 150, 155, 135, 189, 176, 0, + 77, 78, 73, 341, 64, 343, 0, 0, 0, 0, + 75, 0, 0, 71, 74, 68, 0, 0, 65, 67, + 66, 76, 69, 0, 72, 0, 0, 165, 0, 0, + 152, 171, 154, 153, 0, 0, 0, 167, 168, 166, + 170, 0, 200, 0, 0, 0, 0, 190, 0, 0, + 0, 0, 0, 0, 180, 0, 0, 0, 174, 175, + 173, 178, 182, 181, 179, 177, 192, 191, 193, 0, + 208, 0, 204, 0, 0, 146, 133, 145, 134, 102, + 103, 104, 129, 105, 130, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 131, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 132, + 0, 0, 144, 240, 147, 0, 148, 0, 149, 143, + 0, 236, 229, 227, 234, 235, 233, 232, 238, 231, + 230, 228, 237, 224, 0, 212, 0, 0, 216, 0, + 0, 220, 0, 0, 146, 138, 0, 137, 0, 142, + 156, 0, 342, 331, 332, 0, 329, 0, 330, 0, + 333, 247, 254, 253, 261, 249, 0, 250, 334, 0, + 340, 251, 252, 257, 255, 337, 335, 339, 258, 0, + 269, 0, 0, 0, 0, 341, 64, 0, 343, 65, + 241, 283, 66, 0, 0, 0, 270, 0, 0, 259, + 260, 0, 248, 256, 284, 285, 328, 338, 0, 299, + 300, 301, 302, 0, 295, 296, 297, 298, 325, 326, + 0, 0, 0, 0, 0, 288, 289, 245, 243, 205, + 213, 209, 225, 201, 246, 0, 152, 217, 221, 194, + 183, 0, 0, 202, 0, 0, 0, 0, 195, 0, + 0, 0, 0, 0, 187, 185, 188, 186, 184, 197, + 196, 198, 0, 210, 0, 206, 0, 244, 152, 0, + 226, 241, 242, 0, 241, 0, 0, 291, 0, 0, + 0, 293, 0, 214, 0, 0, 218, 0, 0, 222, + 281, 0, 273, 282, 276, 0, 280, 0, 241, 274, + 0, 241, 0, 0, 292, 0, 0, 0, 294, 342, + 331, 0, 0, 333, 0, 327, 0, 317, 0, 0, + 0, 287, 0, 286, 0, 344, 0, 101, 263, 266, + 0, 102, 269, 105, 130, 107, 108, 73, 112, 113, + 64, 114, 117, 71, 74, 65, 241, 66, 76, 120, + 69, 122, 72, 124, 125, 270, 127, 128, 132, 0, + 94, 0, 0, 96, 100, 98, 85, 97, 99, 0, + 95, 84, 264, 262, 140, 141, 146, 0, 139, 0, + 316, 0, 303, 304, 0, 315, 0, 0, 0, 306, + 311, 309, 312, 0, 0, 310, 311, 0, 307, 0, + 308, 265, 314, 0, 265, 313, 0, 318, 319, 0, + 265, 320, 321, 0, 0, 322, 0, 0, 0, 323, + 324, 158, 157, 0, 0, 0, 290, 0, 0, 0, + 305, 278, 271, 0, 279, 275, 0, 277, 267, 0, + 268, 272, 88, 0, 0, 92, 79, 0, 81, 90, + 0, 82, 91, 93, 83, 89, 80, 0, 86, 162, + 160, 164, 161, 159, 163, 6, 336, 4, 2, 62, + 87, 0, 0, 65, 67, 66, 31, 5, 0, 63, + 0, 42, 41, 40, 0, 0, 55, 0, 56, 35, + 36, 37, 38, 59, 0, 42, 0, 0, 0, 0, + 0, 51, 0, 52, 0, 0, 26, 0, 0, 60, + 27, 0, 30, 28, 24, 0, 29, 25, 0, 53, + 0, 54, 140, 0, 57, 61, 0, 0, 0, 0, + 58, 0, 49, 43, 50, 44, 0, 0, 0, 0, + 46, 0, 47, 48, 45, 0, 0, 140, 265, 0, + 0, 39, 102, 269, 105, 130, 107, 108, 73, 112, + 113, 64, 114, 117, 71, 74, 65, 241, 66, 76, + 120, 69, 122, 72, 124, 125, 270, 127, 128, 132, + 0, 32, 33, 0, 34, 8, 0, 10, 0, 9, + 0, 1, 21, 12, 0, 13, 0, 14, 0, 19, + 20, 0, 15, 16, 0, 17, 18, 11, 23, 7, + 345}; const short QDeclarativeJSGrammar::goto_default [] = { - 7, 626, 207, 196, 205, 507, 495, 625, 644, 620, - 624, 622, 627, 22, 623, 18, 506, 543, 533, 540, - 535, 191, 195, 197, 201, 524, 568, 567, 200, 232, - 26, 474, 473, 356, 355, 9, 354, 357, 107, 17, - 145, 24, 13, 144, 19, 25, 57, 23, 8, 28, - 27, 269, 15, 263, 10, 259, 12, 261, 11, 260, - 20, 267, 21, 268, 14, 262, 258, 299, 411, 264, - 265, 202, 193, 192, 204, 233, 203, 208, 229, 230, - 194, 360, 359, 231, 463, 462, 321, 322, 465, 324, - 464, 323, 419, 423, 426, 422, 421, 441, 442, 185, - 199, 181, 184, 198, 206, 0}; + 7, 621, 207, 196, 205, 507, 495, 620, 639, 615, + 619, 617, 622, 22, 618, 18, 506, 545, 535, 542, + 537, 523, 191, 195, 197, 201, 526, 566, 565, 200, + 232, 26, 474, 473, 356, 355, 9, 354, 357, 107, + 17, 145, 24, 13, 144, 19, 25, 57, 23, 8, + 28, 27, 269, 15, 263, 10, 259, 12, 261, 11, + 260, 20, 267, 21, 268, 14, 262, 258, 299, 411, + 264, 265, 202, 193, 192, 204, 233, 203, 208, 229, + 230, 194, 360, 359, 231, 463, 462, 321, 322, 465, + 324, 464, 323, 419, 423, 426, 422, 421, 441, 442, + 185, 199, 181, 184, 198, 206, 0}; const short QDeclarativeJSGrammar::action_index [] = { - 421, 1288, 2322, 2322, 2419, 1016, -52, 37, 140, -101, - 35, -13, -40, 190, -101, 272, 34, -101, -101, 658, - 42, 103, 194, 201, -101, -101, -101, 439, 256, 1288, - -101, -101, -101, 282, -101, 2128, 1751, 1288, 1288, 1288, - -101, 917, 1288, -101, -101, -101, 1288, 1288, -101, -101, - -101, -101, -101, 1288, -101, 1288, 1288, -101, 1288, 1288, - 109, 245, -101, -101, 1288, 1288, 1288, -101, -101, -101, - 185, 1288, 295, 1288, 1288, 1288, 1288, 461, 1288, 1288, - 1288, 1288, 1288, 1288, 256, 1288, 1288, 1288, 155, 119, - 114, 176, 256, 332, 202, 332, 560, 560, 471, 1288, - -23, 1288, 53, 2031, 1288, 1288, -101, -101, -101, -101, + 350, 1271, 2492, 2492, 2395, 999, 52, 93, 137, -101, + 104, 72, 66, 177, -101, 285, 80, -101, -101, 641, + 71, 130, 167, 178, -101, -101, -101, 431, 321, 1271, + -101, -101, -101, 393, -101, 2201, 2007, 1271, 1271, 1271, + -101, 811, 1271, -101, -101, -101, 1271, 1271, -101, -101, + -101, -101, -101, 1271, -101, 1271, 1271, -101, 1271, 1271, + 87, 188, -101, -101, 1271, 1271, 1271, -101, -101, -101, + 179, 1271, 263, 1271, 1271, 1271, 1271, 456, 1271, 1271, + 1271, 1271, 1271, 1271, 321, 1271, 1271, 1271, 128, 114, + 120, 193, 181, 172, 321, 321, 446, 395, 405, 1271, + -8, 1271, 76, 2104, 1271, 1271, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, - 100, 1288, -101, -101, 70, 59, -101, 1288, -101, -101, - 1288, -101, -101, -101, -101, -101, -101, -101, -101, -101, - -101, -101, -101, -101, 1288, 41, 1288, 1288, 98, 91, - 1288, -101, 2031, 1288, 1288, -101, 121, -101, 73, -101, - -101, 39, -101, 385, 180, 78, -101, 391, -101, 64, - 2322, -101, -101, -101, -101, -101, 208, -101, -101, 82, - -101, -101, -101, -101, -101, -101, 2322, -101, -101, 538, - -101, 495, 128, 2419, 54, 358, 62, 44, 2613, 67, - 1288, -101, 76, 63, 1288, 58, -101, 60, 46, -101, - -101, 309, -101, -101, -101, -101, -101, -101, 86, -101, - -101, -101, -101, 107, -101, -101, -101, -101, -101, -101, - 28, 52, 1288, 101, 102, -101, -101, 1472, -101, 83, - 75, 79, -101, 287, 84, 80, 585, 69, 89, 321, - 177, 482, 1288, 297, 1288, 1288, 1288, 1288, 331, 1288, - 1288, 1288, 1288, 1288, 332, 222, 332, 332, 332, 410, - 410, 410, 1288, 57, 1288, 72, 1288, -101, 658, 1288, - -101, 1288, 71, 45, 1288, 61, 2419, -101, 1288, 132, - 2419, -101, 1288, 47, 1288, 1288, 66, 65, 1288, -101, - 68, 112, 81, -101, -101, 1288, -101, 369, 1288, -101, - 85, 1288, 74, 2419, -101, 1288, 122, 2419, -101, 77, - 294, 16, -29, 2322, -53, -101, 2419, -101, 1288, 127, - 2419, -15, 2419, -101, 10, 11, -34, -101, -101, 2419, - -48, 504, 4, 476, 113, 1288, 2419, 2, -28, 420, - 6, -21, 719, 7, 87, -101, 1382, -101, -4, -16, - 5, 1288, 3, -27, 1288, 9, 1288, -18, -31, 1288, - -101, 2225, -7, -101, -101, -101, -101, -101, -101, 1288, - -101, -101, -101, -101, 246, -101, 1288, -38, -101, 2419, - -101, 88, -101, -101, 2419, -101, 1288, 106, 26, -101, - 55, -101, 50, 105, 1288, -101, 48, 38, -101, -8, - -101, 2419, -101, 94, 2419, -101, 238, -101, -101, 104, - 2419, 31, -101, 21, 19, -101, 305, 1, 30, -101, - -101, -101, -101, 1288, 136, 2419, -101, 1288, 134, 2419, - -101, 49, -101, 173, -101, -101, 1288, -101, -101, 363, - -101, -101, -101, 137, 1565, -101, -101, 1658, -101, -101, - 1844, -101, -101, -101, -101, -101, -101, 95, -101, -101, - -101, -101, -101, -101, -101, -101, 2322, -101, -101, -101, - 92, 15, 925, 169, 27, -6, -101, -101, 212, -101, - 191, -101, -101, -101, 323, 211, -101, 1288, -101, 214, - -101, -101, 216, 40, 317, 210, 43, 259, 236, -101, - 36, -101, 747, 96, -101, 29, 747, -101, -101, 1198, - -101, -101, -101, 1107, -101, -101, 231, -101, 1288, -101, - 217, 286, 32, -101, -101, -101, 188, 340, 51, 1288, - 175, -101, -101, 171, -101, 179, -101, 56, -11, 351, - 181, 336, -101, 110, -101, -101, -101, 1934, 647, -101, - -101, -101, -101, 253, 2516, 1751, -5, 460, 22, 468, - 138, 1288, 2419, 24, -2, 412, 23, -3, 836, 20, - 87, -101, 1382, -101, 17, -10, 18, 1288, 25, 8, - 1288, 33, 1288, 12, 14, 120, -101, -101, 13, -101, - -101, 747, -101, 248, -47, 828, -101, -101, 152, 482, - -101, 150, -101, 123, -101, -101, 398, -101, -101, 117, - -101, -101, -101, -101, -101, -101, + 110, 1271, -101, -101, 68, 38, -101, 1271, -101, -101, + 1271, -101, -101, -101, -101, -101, -101, -101, -101, -101, + -101, -101, -101, -101, 1271, 32, 1271, 1271, 85, 83, + 1271, -101, 2104, 1271, 1271, -101, 108, -101, 53, -101, + -101, 64, -101, 393, 89, 62, -101, 297, -101, 63, + 2492, -101, -101, -101, -101, -101, 154, -101, -101, 47, + -101, -101, -101, -101, -101, -101, 2492, -101, -101, 461, + -101, 470, 74, 2395, 59, 393, 92, 67, 2686, 152, + 1271, -101, 65, 43, 1271, 41, -101, 39, 34, -101, + -101, 393, -101, -101, -101, -101, -101, -101, 86, -101, + -101, -101, -101, 90, -101, -101, -101, -101, -101, -101, + -11, 50, 1271, 103, 82, -101, -101, 1455, -101, 84, + 44, 5, -101, 267, 70, 33, 575, 79, 69, 471, + 235, 393, 1271, 275, 1271, 1271, 1271, 1271, 305, 1271, + 1271, 1271, 1271, 1271, 229, 201, 225, 202, 321, 355, + 374, 380, 1271, 35, 1271, 81, 1271, -101, 641, 1271, + -101, 1271, 61, 1, 1271, 29, 2395, -101, 1271, 133, + 2395, -101, 1271, 73, 1271, 1271, 99, 97, 1271, -101, + 51, 153, 60, -101, -101, 1271, -101, 393, 1271, -101, + 56, 1271, -25, 2395, -101, 1271, 129, 2395, -101, -35, + 309, -56, -31, 2492, -39, -101, 2395, -101, 1271, 245, + 2395, -5, 2395, -101, 6, 0, -33, -101, -101, 2395, + -43, 543, 7, 488, 112, 1271, 2395, -1, -27, 453, + 8, -18, 630, 14, 16, -101, 1365, -101, 12, -19, + 3, 1271, 58, -30, 1271, -2, 1271, -29, -36, 1271, + -101, 2298, 18, -101, -101, -101, -101, -101, -101, 1271, + -101, -101, -101, -101, 223, -101, 1271, -10, -101, 2395, + -101, 95, -101, -101, 2395, -101, 1271, 107, 20, -101, + 40, -101, 46, 100, 1271, -101, 55, 57, -101, 28, + -101, 2395, -101, 118, 2395, -101, 161, -101, -101, 126, + 2395, 37, -101, -12, -4, -101, 393, -34, -6, -101, + -101, -101, -101, 1271, 98, 2395, -101, 1271, 116, 2395, + -101, 19, -101, 186, -101, -101, 1271, -101, -101, 303, + -101, -101, -101, 119, 1638, -101, -101, 1821, -101, -101, + 1914, -101, -101, -101, -101, -101, -101, 123, -101, -101, + -101, -101, -101, -101, -101, -101, 2492, -101, -101, -101, + 94, -26, 819, 158, -28, 4, -101, -101, 210, -101, + 203, -101, -101, -101, 393, 230, -101, 1545, -101, -101, + -101, -101, -101, -101, 234, 2, 393, 232, 17, 393, + 163, -101, 10, -101, 908, 125, -101, 13, 908, -101, + -101, 1090, -101, -101, -101, 1181, -101, -101, 214, -101, + 1545, -101, 262, 9, -101, -101, 180, 318, 30, 1545, + -101, 238, -101, 236, -101, 26, -32, 315, 183, 288, + -101, 77, -101, -101, -101, 1728, 908, 291, 2589, 2007, + -3, -101, 443, 25, 497, 88, 1271, 2395, 24, 11, + 384, 36, 27, 702, 48, 49, -101, 1365, -101, 54, + 31, 45, 1271, 58, 15, 1271, 42, 1271, 23, 22, + 122, -101, -101, 21, -101, -101, 730, -101, 254, -70, + 908, -101, -101, 138, 393, -101, 143, -101, 134, -101, + -101, 268, -101, -101, 124, -101, -101, -101, -101, -101, + -101, - -106, 6, -92, 10, 5, 278, -106, -106, -106, -106, - -106, -106, -106, -106, -106, -106, -106, -106, -106, -42, - -106, -106, -106, -106, -106, -106, -106, -106, -106, 109, - -106, -106, -106, -10, -106, -106, -35, 24, 73, 90, - -106, 219, 181, -106, -106, -106, 171, 120, -106, -106, - -106, -106, -106, 174, -106, 170, 167, -106, 175, 163, - -106, -106, -106, -106, 184, 177, 180, -106, -106, -106, - -106, 125, -106, 132, 134, 162, 130, -106, 121, 124, - 123, 141, 142, 152, -106, 154, 161, 160, -106, -106, - -106, -106, -106, -106, -106, -106, -106, -106, -106, 139, - -106, 143, -106, 156, 91, 55, -106, -106, -106, -106, - -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, - -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, - -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, - -106, 32, -106, -106, -106, -106, -106, 33, -106, -106, - 26, -106, -106, -106, -106, -106, -106, -106, -106, -106, - -106, -106, -106, -106, 96, -106, 119, 52, -106, -106, - 66, -106, 220, 69, 71, -106, -106, -106, -106, -106, - -106, -106, -106, 25, -106, -106, -106, 64, -106, -106, - -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, - -106, -106, -106, -106, -106, -106, 70, -106, -106, 61, - -106, 41, -106, 39, -106, 37, -106, -106, 42, -106, - 79, -106, -106, -106, 81, 72, -106, -106, -106, -106, - -106, -5, -106, -106, -106, -106, -106, -106, -106, -106, - -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, - -106, -106, 21, -106, -106, -106, -106, 112, -106, -106, - -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, - -106, 17, 237, -106, 192, 236, 224, 225, -106, 97, - 98, 101, 99, 113, -106, -106, -106, -106, -106, -106, - -106, -106, 204, -106, 223, -106, 235, -106, -106, 239, - -106, 197, -106, -106, 228, -106, 27, -106, 13, -106, - 2, -106, 233, -106, 190, 198, -106, -106, 196, -106, - -106, -106, -106, -106, -106, 200, -106, 107, 135, -106, - -106, 186, -106, 84, -106, 80, -106, 76, -106, -106, - 89, -106, -106, -49, -106, -106, 47, -106, 40, -106, - 44, -106, 68, -106, -106, -106, -106, -106, -106, 53, - -106, 35, -106, 49, -106, 87, 63, -106, -106, 30, - -106, -106, 103, -106, -106, -106, 51, -106, -106, -106, - -106, 86, -106, 67, 114, -106, 74, -106, -106, 65, - -106, 56, -106, -106, -106, -106, -106, -106, -106, 62, - -106, -106, -106, -106, -106, -106, 95, -106, -106, 78, - -106, -106, -106, -106, 75, -106, 88, -106, -106, -106, - -106, -106, -54, -106, 45, -106, -40, -106, -106, -106, - -106, 94, -106, -106, 100, -106, -106, -106, -106, -106, - 150, -41, -106, -106, 54, -106, 43, -106, 48, -106, - -106, -106, -106, 59, -106, 57, -106, 60, -106, 58, - -106, -106, -106, -106, -106, -106, 38, -106, -106, 144, - -106, -106, -106, -106, 31, -106, -106, 202, -106, -106, - 50, -106, -106, -106, -106, -106, -106, -106, -106, -106, - -106, -106, -106, -106, -106, -106, 77, -106, -106, -106, - -106, -106, 82, -106, -106, -106, -106, -106, -106, -106, - -17, -106, -106, -106, -4, -106, -106, 12, -106, -106, - -106, -106, -106, -106, -14, 46, -106, -13, -106, -106, - -106, -106, 108, -106, -106, -106, 243, -106, -106, 295, - -106, -106, -106, 290, -106, -106, -106, -106, 346, -106, - -106, -106, 16, -106, -106, -106, 22, 23, -106, 34, - -106, -106, -106, -106, -106, 11, -106, -106, -106, 7, - 1, 8, -106, -106, -106, -106, -106, 307, 179, -106, - -106, -106, -106, -106, 18, 281, 9, 15, -106, 4, - -106, 83, 29, -106, -106, -2, -106, -106, 85, -106, - -106, -106, 3, -106, -106, -106, -106, 14, -106, 0, - 105, -106, 93, -106, -106, -106, -106, -106, -1, -106, - -106, 20, -106, -106, 28, 92, -106, -106, -106, 19, - -106, -106, -106, -106, -106, -106, -12, -106, -106, -106, - -106, -106, -106, -106, -106, -106}; + -107, 25, -75, 27, 30, 272, -107, -107, -107, -107, + -107, -107, -107, -107, -107, -107, -107, -107, -107, -42, + -107, -107, -107, -107, -107, -107, -107, -107, -107, 95, + -107, -107, -107, 31, -107, -107, 1, 37, 91, 80, + -107, 89, 167, -107, -107, -107, 175, 181, -107, -107, + -107, -107, -107, 137, -107, 130, 129, -107, 144, 152, + -107, -107, -107, -107, 140, 133, 149, -107, -107, -107, + -107, 157, -107, 182, 179, 170, 70, -107, 66, 78, + 55, 94, 100, 114, -107, 120, 109, 104, -107, -107, + -107, -107, -107, -107, -107, -107, -107, -107, -107, 172, + -107, 128, -107, 122, 58, 34, -107, -107, -107, -107, + -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, + -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, + -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, + -107, 51, -107, -107, -107, -107, -107, 36, -107, -107, + 47, -107, -107, -107, -107, -107, -107, -107, -107, -107, + -107, -107, -107, -107, 154, -107, 158, -35, -107, -107, + 13, -107, 248, 42, 115, -107, -107, -107, -107, -107, + -107, -107, -107, 20, -107, -107, -107, 2, -107, -107, + -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, + -107, -107, -107, -107, -107, -107, 61, -107, -107, 67, + -107, 64, -107, 76, -107, 43, -107, -107, 57, -107, + 60, -107, -107, -107, 85, 69, -107, -107, -107, -107, + -107, -5, -107, -107, -107, -107, -107, -107, -107, -107, + -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, + -107, -107, 24, -107, -107, -107, -107, 148, -107, -107, + -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, + -107, 9, 186, -107, 196, 221, 220, 212, -107, 102, + 98, 96, 116, 118, -107, -107, -107, -107, -107, -107, + -107, -107, 230, -107, 199, -107, 193, -107, -107, 211, + -107, 132, -107, -107, 126, -107, 14, -107, 5, -107, + 10, -107, 208, -107, 189, 202, -107, -107, 209, -107, + -107, -107, -107, -107, -107, 200, -107, 103, 121, -107, + -107, 168, -107, 50, -107, 54, -107, 62, -107, -107, + 88, -107, -107, -21, -107, -107, 184, -107, 63, -107, + 65, -107, 74, -107, -107, -107, -107, -107, -107, 92, + -107, 35, -107, 45, -107, 171, 75, -107, -107, 56, + -107, -107, 166, -107, -107, -107, 90, -107, -107, -107, + -107, 39, -107, 32, 159, -107, 178, -107, -107, -3, + -107, -17, -107, -107, -107, -107, -107, -107, -107, 3, + -107, -107, -107, -107, -107, -107, 68, -107, -107, 79, + -107, -107, -107, -107, 16, -107, 11, -107, -107, -107, + -107, -107, -8, -107, 59, -107, -41, -107, -107, -107, + -107, 99, -107, -107, 160, -107, -107, -107, -107, -107, + 93, -7, -107, -107, 77, -107, 40, -107, 46, -107, + -107, -107, -107, 53, -107, 83, -107, 72, -107, 71, + -107, -107, -107, -107, -107, -107, 48, -107, -107, 81, + -107, -107, -107, -107, 38, -107, -107, 173, -107, -107, + 33, -107, -107, -107, -107, -107, -107, -107, -107, -107, + -107, -107, -107, -107, -107, -107, 86, -107, -107, -107, + -107, -107, 73, -107, -107, -107, -107, -107, -107, -107, + 22, -107, -107, -107, -10, -107, -107, 259, -107, -107, + -107, -107, -107, -107, -107, -107, -6, -15, -107, -2, + -107, -107, -107, -107, 101, -107, -107, -107, 106, -107, + -107, 290, -107, -107, -107, 294, -107, -107, -107, -107, + 318, -107, -107, -4, -107, -107, -19, -13, -107, 364, + -107, -107, -107, -26, -107, -107, -107, -11, -20, -12, + -107, -107, -107, -107, -107, 305, 278, -107, 17, 261, + 4, -107, 28, -107, 26, -107, 87, 19, -107, -107, + 23, -107, -107, 84, -107, -107, -107, 44, -107, -107, + -107, -107, 41, -107, 29, 125, -107, 110, -107, -107, + -107, -107, -107, 15, -107, -107, 12, -107, -107, 18, + 97, -107, -107, -107, 7, -107, -107, -107, -107, -107, + -107, 21, -107, -107, -107, -107, -107, -107, -107, -107, + -107}; const short QDeclarativeJSGrammar::action_info [] = { - 399, 352, 345, -101, 343, 457, 440, 403, 257, -112, - -125, -131, -123, 346, -120, 348, -128, 389, 453, 391, - 416, 401, 408, 563, -101, -123, 416, -120, 539, -131, - 346, -112, -125, 348, 257, 99, 71, 645, 621, 101, - -128, 440, 141, 621, 164, 431, 539, 430, 453, 573, - 457, 444, 440, 424, 71, 424, 101, 446, 559, 420, - 424, 448, 539, 440, 570, 539, 466, 527, 312, 346, - 532, 312, 318, 272, 409, 183, 342, 525, 147, 141, - 348, 510, 457, 414, 272, 325, 0, 0, 252, 99, - 257, 440, 296, 556, -102, 292, 453, 190, 170, 416, - 164, 434, 141, 141, 536, 251, 304, 172, 141, 141, - 443, 0, 335, 340, 141, 427, 0, 0, 0, 149, - 327, 306, 0, 292, 444, 0, 173, 0, 536, 141, - 141, 0, 0, 179, 333, 141, 294, 236, 189, 314, - 141, 301, 141, 315, 141, 477, 331, 242, 241, 413, - 412, 62, 537, 166, 58, 488, 142, 167, 294, 58, - 428, 254, 63, 256, 255, 59, 418, 172, 247, 246, - 59, 575, 574, 328, 249, 248, 616, 177, 641, 640, - 58, 469, 337, 141, 635, 634, 173, 350, 187, 249, - 248, 59, 310, 478, 459, 58, 455, 64, 523, 249, - 248, 85, 85, 86, 86, 103, 59, 565, 511, 172, - 511, 638, 637, 64, 87, 87, 141, 511, 517, 577, - 511, 0, 141, 0, 104, 141, 105, 85, 173, 86, - 174, 172, 566, 564, 470, 468, 562, 561, 548, 511, - 87, 636, 65, 530, 513, 539, 141, 85, 66, 86, - 173, 0, 406, 0, 513, 512, 513, 64, 65, 0, - 87, 172, 0, 513, 66, 512, 513, 512, 172, 235, - 234, 0, 518, 516, 512, 521, 520, 512, 554, 553, - 173, 85, 406, 86, 0, 513, -89, 173, 34, 174, - 73, 74, 549, 547, 87, 631, 512, 531, 529, 438, - 437, 172, 65, 0, 578, 274, 275, 0, 66, 632, - 630, 34, 0, 73, 74, 274, 275, 75, 76, -89, - 173, 0, 174, 34, 0, 48, 50, 49, 0, 0, - 0, 0, 276, 277, 34, 0, 0, 0, 34, 629, - 75, 76, 276, 277, 279, 280, 34, 0, 48, 50, - 49, 45, 34, 281, 279, 280, 282, 85, 283, 86, - 48, 50, 49, 281, 0, 34, 282, 0, 283, 34, - 87, 48, 50, 49, 45, 48, 50, 49, 0, 0, - 34, 0, 0, 48, 50, 49, 45, 34, 0, 48, - 50, 49, 34, 0, 0, 0, 0, 45, 34, 0, - 0, 45, 48, 50, 49, 0, 48, 50, 49, 45, - 0, 0, 0, 0, 34, 45, 0, 48, 50, 49, - 34, 0, 0, 0, 48, 50, 49, 34, 45, 48, - 50, 49, 45, 279, 280, 48, 50, 49, 0, 0, - 0, 34, 281, 45, 0, 282, 0, 283, -343, 34, - 45, 48, 50, 49, 0, 45, -343, 48, 50, 49, - 0, 45, 78, 79, 48, 50, 49, 0, 0, 0, - 80, 81, 0, 0, 82, 0, 83, 45, 48, 50, - 49, 0, 0, 45, 78, 79, 48, 50, 49, 34, - 45, 0, 80, 81, 78, 79, 82, 34, 83, 0, - 0, 0, 80, 81, 45, 34, 82, 0, 83, 0, - 0, 34, 45, 0, 6, 5, 4, 1, 3, 2, - 0, 240, 239, 0, 34, 0, 48, 50, 49, 245, - 244, 0, 0, 34, 48, 50, 49, 245, 244, 0, - 0, 0, 48, 50, 49, 0, 0, 0, 48, 50, - 49, 0, 45, 0, 0, 0, 245, 244, 0, 0, - 45, 48, 50, 49, 0, 240, 239, 34, 45, 0, - 48, 50, 49, 0, 45, 0, 0, 0, 0, 0, - 0, 0, 0, 78, 79, 0, 0, 45, 151, 0, - 0, 80, 81, 0, 0, 82, 45, 83, 152, 240, - 239, 0, 153, 0, 48, 50, 49, 0, 0, 0, - 0, 154, 0, 155, 0, 0, 308, 0, 0, 0, - 0, 0, 0, 0, 156, 0, 157, 62, 0, 0, - 45, 0, 0, 0, 158, 0, 0, 159, 63, 0, - 0, 0, 0, 160, 0, 0, 0, 0, 0, 161, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, - 31, 151, 0, 0, 0, 162, 0, 0, 0, 33, - 0, 152, 0, 0, 0, 153, 34, 0, 0, 0, - 35, 36, 0, 37, 154, 0, 155, 0, 0, 0, - 502, 0, 0, 0, 44, 0, 0, 156, 0, 157, - 62, 0, 0, 0, 0, 0, 0, 158, 0, 0, - 159, 63, 51, 48, 50, 49, 160, 52, 0, 0, - 0, 0, 161, 0, 0, 0, 0, 0, 43, 54, - 32, 30, 31, 0, 40, 0, 0, 0, 162, 45, - 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, - 0, 0, 35, 36, 0, 37, 0, 0, 0, 30, - 31, 0, 41, 0, 0, 0, 44, 0, 0, 33, - 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, - 35, 36, 0, 37, 51, 48, 50, 49, 0, 52, - 502, 0, 0, 0, 44, 0, 0, 0, 0, 0, - 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, - 0, 45, 51, 48, 50, 49, 0, 52, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 43, 54, - 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, - 30, 31, 0, 0, 0, 0, 0, 0, 30, 31, - 33, 0, 0, 0, 0, 0, 0, 34, 33, 0, - 0, 35, 36, 0, 37, 34, 0, 0, 0, 35, - 36, 502, 37, 0, 0, 44, 0, 0, 0, 41, - 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, - 0, 51, 48, 50, 49, 0, 52, 0, 0, 43, - 54, 32, 0, 0, 0, 40, 0, 43, 54, 32, - 45, 0, 0, 40, 0, 0, 0, 0, 45, 30, - 31, 0, 0, 0, 0, 0, 0, 30, 31, 33, - 0, 0, 0, 0, 0, 0, 34, 33, 0, 0, - 35, 36, 0, 37, 34, 0, 0, 0, 35, 36, - 41, 37, 0, 0, 44, 0, 0, 0, 502, 0, - 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 51, 48, 50, 49, 0, 52, 0, 0, - 51, 48, 50, 49, 0, 52, 0, 0, 43, 54, - 32, 0, 0, 0, 40, 0, 43, 54, 32, 45, - 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, - 0, 0, 0, 0, 0, 0, 501, 0, 30, 31, - 0, 0, 0, 0, 0, 0, 0, 0, 215, 0, - 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, - 36, 0, 37, 0, 0, 0, 0, 0, 0, 502, - 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 51, 503, 505, 504, 0, 52, 0, 0, 0, - 0, 226, 0, 0, 0, 0, 0, 43, 54, 32, - 210, 0, 0, 40, 0, 0, 0, 0, 45, 0, - 0, 0, 0, 0, 0, 0, 0, 501, 0, 30, - 31, 0, 0, 0, 0, 0, 0, 0, 0, 215, - 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, - 35, 36, 0, 37, 0, 0, 0, 0, 0, 0, - 502, 0, 0, 0, 44, 0, 0, 0, 0, 0, - 0, 0, 544, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 51, 503, 505, 504, 0, 52, 0, 0, - 0, 0, 226, 0, 0, 0, 0, 0, 43, 54, - 32, 210, 0, 0, 40, 0, 0, 0, 0, 45, - 0, 0, 0, 0, 0, 0, 0, 0, 501, 0, + 457, 340, 343, 440, 342, -126, -110, 453, 391, 257, + -121, 352, 403, 389, -129, 346, 345, 416, 348, -99, + 616, -118, 401, -100, 446, 399, 448, 440, 571, 440, + 541, -110, -129, 561, 568, 333, 466, 559, 556, 527, + 510, 529, 541, 346, 534, 424, 541, 257, 440, -126, + 408, 424, -121, 420, 541, -118, -100, 444, 457, 453, + 424, -99, 304, 348, 431, -123, 251, 416, 325, 141, + 457, 101, 414, 164, 440, 453, 147, 71, 296, 416, + 99, 312, 272, 430, 294, 272, 252, 164, 141, 306, + 170, 335, 292, 640, 301, 257, 190, 187, 149, 346, + 183, 312, 236, 348, 318, 71, 141, 0, 0, 172, + 427, 141, 0, 179, 294, 141, 141, 331, 141, 314, + 99, 292, 189, 315, 141, 434, 141, 477, 173, 62, + 538, 141, 443, 538, 0, 249, 248, 141, 573, 572, + 63, 141, 616, 256, 255, 101, 444, 242, 241, 249, + 248, 247, 246, 172, 58, 428, 413, 412, 455, 409, + 58, 327, 141, 254, 177, 59, 142, 418, 58, 141, + 532, 59, 173, 249, 248, 478, 459, 58, 611, 59, + 166, 539, 172, 488, 167, 636, 635, 525, 59, 337, + 64, 64, 103, 310, 469, 630, 629, 85, 0, 86, + 64, 173, 0, 174, 633, 632, 85, 0, 86, 511, + 87, 104, 511, 105, 328, 235, 234, 575, 85, 87, + 86, 550, 438, 437, 533, 531, 85, 85, 86, 86, + 0, 87, 511, 513, 631, 65, 65, 517, 172, 87, + 87, 66, 66, 541, 512, 65, 0, 470, 468, 172, + 85, 66, 86, 141, 85, 513, 86, 173, 513, 406, + 85, 511, 86, 87, 0, 511, 512, 87, 173, 512, + 406, 0, 0, 87, 563, 551, 549, 172, 513, 0, + 0, 73, 74, 0, 0, 274, 275, 0, 0, 512, + 0, 518, 516, 274, 275, -87, 173, 34, 174, 564, + 562, 626, 576, 73, 74, 350, 172, 513, 75, 76, + 0, 513, 276, 277, 0, 627, 625, 34, 512, 0, + 276, 277, 512, 0, -87, 173, 34, 174, 279, 280, + 75, 76, 34, 0, 48, 50, 49, 281, 34, 0, + 282, 0, 283, 0, 34, 624, 85, 34, 86, 0, + 0, 0, 0, 0, 48, 50, 49, 0, 0, 87, + 45, 0, 0, 48, 50, 49, 0, 0, 0, 48, + 50, 49, 0, 0, 0, 48, 50, 49, 279, 280, + 45, 48, 50, 49, 48, 50, 49, 281, 0, 45, + 282, 0, 283, 0, 0, 45, 0, 279, 280, 0, + 0, 45, 0, 279, 280, 0, 281, 45, 0, 282, + 45, 283, 281, 34, 0, 282, 0, 283, 78, 79, + -341, 0, 34, 0, 0, 0, 80, 81, 78, 79, + 82, 0, 83, 0, 0, 0, 80, 81, 0, 0, + 82, 0, 83, 6, 5, 4, 1, 3, 2, 0, + 48, 50, 49, 0, 78, 79, 0, 0, 0, 48, + 50, 49, 80, 81, 0, 0, 82, 0, 83, 78, + 79, 0, 34, 0, 0, 0, 45, 80, 81, 78, + 79, 82, 34, 83, 0, 45, 0, 80, 81, -341, + 34, 82, 0, 83, 279, 280, 0, 0, 0, 34, + 0, 0, 0, 281, 240, 239, 282, 0, 283, 48, + 50, 49, 0, 0, 0, 0, 0, 34, 0, 48, + 50, 49, 240, 239, 0, 0, 34, 48, 50, 49, + 0, 245, 244, 0, 0, 45, 48, 50, 49, 0, + 0, 0, 0, 0, 0, 45, 0, 0, 0, 245, + 244, 0, 0, 45, 48, 50, 49, 0, 245, 244, + 0, 0, 45, 48, 50, 49, 0, 0, 0, 0, + 0, 0, 34, 0, 0, 0, 0, 0, 151, 0, + 45, 0, 0, 0, 0, 0, 0, 0, 152, 45, + 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, + 0, 154, 0, 155, 240, 239, 308, 0, 0, 48, + 50, 49, 0, 0, 156, 0, 157, 62, 0, 0, + 0, 0, 0, 0, 158, 0, 0, 159, 63, 0, + 0, 0, 0, 160, 0, 45, 0, 0, 0, 161, + 0, 0, 30, 31, 151, 0, 0, 0, 0, 0, + 0, 0, 33, 0, 152, 162, 0, 0, 153, 34, + 0, 0, 0, 35, 36, 0, 37, 154, 0, 155, + 0, 0, 0, 41, 0, 0, 0, 44, 0, 0, + 156, 0, 157, 62, 0, 0, 0, 0, 0, 0, + 158, 0, 0, 159, 63, 51, 48, 50, 49, 160, + 52, 0, 0, 0, 0, 161, 0, 0, 0, 0, + 0, 43, 54, 32, 30, 31, 0, 40, 0, 0, + 0, 162, 45, 0, 33, 0, 0, 0, 0, 0, + 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, + 0, 0, 30, 31, 0, 41, 0, 0, 0, 44, + 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, + 0, 0, 0, 35, 36, 0, 37, 51, 48, 50, + 49, 0, 52, 502, 0, 0, 0, 44, 0, 0, + 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, + 0, 0, 0, 0, 45, 51, 48, 50, 49, 0, + 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, + 0, 0, 45, 30, 31, 0, 0, 0, 0, 0, + 0, 30, 31, 33, 0, 0, 0, 0, 0, 0, + 34, 33, 0, 0, 35, 36, 0, 37, 34, 0, + 0, 0, 35, 36, 41, 37, 0, 0, 44, 0, + 0, 0, 502, 0, 0, 0, 44, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, + 0, 52, 0, 0, 51, 48, 50, 49, 0, 52, + 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, + 43, 54, 32, 45, 0, 0, 40, 0, 0, 0, + 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, - 215, 0, 0, 0, 0, 0, 0, 34, 0, 0, + 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 0, 0, 0, 502, 0, 0, 0, 44, 0, 0, 0, 0, - 0, 0, 0, 541, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 51, 503, 505, 504, 0, 52, 0, - 0, 0, 0, 226, 0, 0, 0, 0, 0, 43, - 54, 32, 210, 0, 0, 40, 0, 0, 0, 0, - 45, 0, 0, 0, 0, 0, 0, 0, 0, 29, - 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, - 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, - 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, - 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, - 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, - 45, 0, 0, 0, 0, 0, 0, 0, 0, -121, - 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, - 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, - 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, - 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, - 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, - 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, - 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, - 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, - 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, - 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, - 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, - 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, - 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, - 49, 0, 52, 0, 53, 0, 55, 271, 56, 0, - 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, - 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, - 0, 0, 0, 483, 0, 0, 29, 30, 31, 0, + 45, 0, 0, 0, 0, 0, 0, 0, 0, 501, + 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, + 0, 215, 0, 0, 0, 0, 0, 0, 34, 0, + 0, 0, 35, 36, 0, 37, 0, 0, 0, 0, + 0, 0, 502, 0, 0, 0, 44, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 51, 503, 505, 504, 0, 52, + 0, 0, 0, 0, 226, 0, 0, 0, 0, 0, + 43, 54, 32, 210, 0, 0, 40, 0, 0, 0, + 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, + 501, 0, 30, 31, 0, 0, 0, 0, 0, 0, + 0, 0, 215, 0, 0, 0, 0, 0, 0, 34, + 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, + 0, 0, 0, 502, 0, 0, 0, 44, 0, 0, + 0, 0, 0, 0, 0, 543, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 51, 503, 505, 504, 0, + 52, 0, 0, 0, 0, 226, 0, 0, 0, 0, + 0, 43, 54, 32, 210, 0, 0, 40, 0, 0, + 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, + 0, 501, 0, 30, 31, 0, 0, 0, 0, 0, + 0, 0, 0, 215, 0, 0, 0, 0, 0, 0, + 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, + 0, 0, 0, 0, 502, 0, 0, 0, 44, 0, + 0, 0, 0, 0, 0, 0, 546, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 51, 503, 505, 504, + 0, 52, 0, 0, 0, 0, 226, 0, 0, 0, + 0, 0, 43, 54, 32, 210, 0, 0, 40, 0, + 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, + 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, + 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, + 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, + 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, + 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, + 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, + 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, + 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, + 0, 0, -119, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, - 0, 486, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, - 0, 0, 0, 0, 0, 0, 475, 0, 0, 29, + 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, + 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, + 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, + 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, + 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, + 271, 56, 0, 0, 0, 0, 43, 54, 32, 0, + 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, + 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, + 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, + 0, 0, 0, 0, 34, 217, 0, 0, 218, 36, + 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, + 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, + 0, 0, 0, 0, 0, 0, 221, 0, 0, 0, + 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, + 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, + 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, + 0, 0, 0, 0, 0, 0, 483, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, - 0, 47, 0, 0, 481, 0, 0, 0, 0, 0, + 0, 47, 0, 0, 486, 0, 0, 0, 0, 0, + 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, + 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, + 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, + 45, 0, 0, 0, 0, 0, 0, 0, 0, 29, + 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 0, 0, 0, 34, 217, 0, + 0, 578, 579, 0, 37, 0, 0, 0, 38, 0, + 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, + 0, 47, 0, 0, 0, 0, 0, 0, 0, 221, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, @@ -525,7 +532,7 @@ const short QDeclarativeJSGrammar::action_info [] = { 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, - 0, 0, 46, 0, 47, 0, 0, 476, 0, 0, + 0, 0, 46, 0, 47, 0, 0, 481, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, @@ -539,44 +546,54 @@ const short QDeclarativeJSGrammar::action_info [] = { 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, - 0, 0, 0, 0, 0, 29, 30, 31, 0, 0, - 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, - 0, 0, 0, 34, 217, 0, 0, 584, 585, 0, - 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, - 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, - 0, 0, 0, 0, 0, 221, 0, 0, 0, 51, - 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, - 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, - 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, + 0, 0, 0, 0, 0, 475, 0, 0, 29, 30, + 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, + 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, + 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, + 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, + 47, 0, 0, 476, 0, 0, 0, 0, 0, 0, + 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, + 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, + 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, + 0, 0, 0, 0, 0, 0, 0, 0, 109, 110, + 111, 0, 0, 113, 115, 116, 0, 0, 117, 0, + 118, 0, 0, 0, 120, 121, 122, 0, 0, 0, + 0, 0, 0, 34, 123, 124, 125, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 129, 0, 0, 0, 0, 0, 0, + 48, 50, 49, 130, 131, 132, 0, 134, 135, 136, + 137, 138, 139, 0, 0, 127, 133, 119, 112, 114, + 128, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 109, 110, 111, 0, 0, 113, 115, 116, 0, 0, 117, 0, 118, 0, 0, 0, 120, 121, 122, 0, 0, 0, 0, 0, 0, - 34, 123, 124, 125, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, + 393, 123, 124, 125, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 126, 0, 0, 0, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 129, 0, 0, 0, 0, 0, 0, 48, 50, 49, + 129, 0, 0, 0, 0, 0, 398, 395, 397, 0, 130, 131, 132, 0, 134, 135, 136, 137, 138, 139, 0, 0, 127, 133, 119, 112, 114, 128, 0, 0, - 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 110, 111, 0, 0, 113, 115, 116, 0, 0, 117, 0, 118, 0, 0, 0, 120, 121, 122, 0, 0, 0, 0, 0, 0, 393, 123, 124, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 394, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 129, 0, 0, + 0, 0, 0, 396, 0, 0, 0, 129, 0, 0, 0, 0, 0, 398, 395, 397, 0, 130, 131, 132, 0, 134, 135, 136, 137, 138, 139, 0, 0, 127, 133, 119, 112, 114, 128, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, - 110, 111, 0, 0, 113, 115, 116, 0, 0, 117, - 0, 118, 0, 0, 0, 120, 121, 122, 0, 0, - 0, 0, 0, 0, 393, 123, 124, 125, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, - 0, 0, 394, 0, 0, 0, 0, 0, 0, 0, - 396, 0, 0, 0, 129, 0, 0, 0, 0, 0, - 398, 395, 397, 0, 130, 131, 132, 0, 134, 135, - 136, 137, 138, 139, 0, 0, 127, 133, 119, 112, - 114, 128, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, + 0, 0, 0, 0, 211, 0, 29, 30, 31, 213, + 0, 0, 0, 0, 0, 0, 214, 33, 0, 0, + 0, 0, 0, 0, 216, 217, 0, 0, 218, 36, + 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, + 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, + 0, 0, 0, 0, 220, 0, 221, 0, 0, 0, + 51, 219, 222, 49, 223, 52, 224, 53, 225, 55, + 226, 56, 227, 228, 0, 0, 43, 54, 32, 210, + 212, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 209, 0, 0, 0, 0, 211, 0, 29, 30, 31, 213, 0, 0, 0, 0, 0, 0, 214, 215, 0, 0, 0, 0, 0, @@ -587,248 +604,238 @@ const short QDeclarativeJSGrammar::action_info [] = { 49, 223, 52, 224, 53, 225, 55, 226, 56, 227, 228, 0, 0, 43, 54, 32, 210, 212, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, - 0, 0, 0, 209, 0, 0, 0, 0, 211, 0, - 29, 30, 31, 213, 0, 0, 0, 0, 0, 0, - 214, 33, 0, 0, 0, 0, 0, 0, 216, 217, - 0, 0, 218, 36, 0, 37, 0, 0, 0, 38, - 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, - 46, 0, 47, 0, 0, 0, 0, 0, 220, 0, - 221, 0, 0, 0, 51, 219, 222, 49, 223, 52, - 224, 53, 225, 55, 226, 56, 227, 228, 0, 0, - 43, 54, 32, 210, 212, 0, 40, 0, 0, 0, + 0, 0, 0, 582, 110, 111, 0, 0, 584, 115, + 586, 30, 31, 587, 0, 118, 0, 0, 0, 120, + 589, 590, 0, 0, 0, 0, 0, 0, 591, 592, + 124, 125, 218, 36, 0, 37, 0, 0, 0, 38, + 0, 39, 593, 42, 0, 0, 595, 0, 0, 0, + 46, 0, 47, 0, 0, 0, 0, 0, 597, 0, + 221, 0, 0, 0, 599, 596, 598, 49, 600, 601, + 602, 53, 604, 605, 606, 607, 608, 609, 0, 0, + 594, 603, 588, 583, 585, 128, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, - 587, 110, 111, 0, 0, 589, 115, 591, 30, 31, - 592, 0, 118, 0, 0, 0, 120, 594, 595, 0, - 0, 0, 0, 0, 0, 596, 597, 124, 125, 218, - 36, 0, 37, 0, 0, 0, 38, 0, 39, 598, - 42, 0, 0, 600, 0, 0, 0, 46, 0, 47, - 0, 0, 0, 0, 0, 602, 0, 221, 0, 0, - 0, 604, 601, 603, 49, 605, 606, 607, 53, 609, - 610, 611, 612, 613, 614, 0, 0, 599, 608, 593, - 588, 590, 128, 40, 0, 0, 0, 0, 45, 0, - 0, 0, 0, 0, 0, 0, 0, 361, 110, 111, - 0, 0, 363, 115, 365, 30, 31, 366, 0, 118, - 0, 0, 0, 120, 368, 369, 0, 0, 0, 0, - 0, 0, 370, 371, 124, 125, 218, 36, 0, 37, - 0, 0, 0, 38, 0, 39, 372, 42, 0, 0, - 374, 0, 0, 0, 46, 0, 47, 0, -267, 0, - 0, 0, 376, 0, 221, 0, 0, 0, 378, 375, - 377, 49, 379, 380, 381, 53, 383, 384, 385, 386, - 387, 388, 0, 0, 373, 382, 367, 362, 364, 128, - 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, - 0, 0, 0, 0, + 361, 110, 111, 0, 0, 363, 115, 365, 30, 31, + 366, 0, 118, 0, 0, 0, 120, 368, 369, 0, + 0, 0, 0, 0, 0, 370, 371, 124, 125, 218, + 36, 0, 37, 0, 0, 0, 38, 0, 39, 372, + 42, 0, 0, 374, 0, 0, 0, 46, 0, 47, + 0, -265, 0, 0, 0, 376, 0, 221, 0, 0, + 0, 378, 375, 377, 49, 379, 380, 381, 53, 383, + 384, 385, 386, 387, 388, 0, 0, 373, 382, 367, + 362, 364, 128, 40, 0, 0, 0, 0, 45, 0, + 0, 0, 0, 0, 0, 0, 0, - 472, 546, 528, 639, 311, 182, 302, 498, 514, 16, - 461, 515, 496, 182, 497, 519, 309, 436, 619, 243, - 358, 439, 576, 572, 253, 150, 571, 487, 617, 307, - 238, 250, 320, 628, 633, 555, 569, 560, 558, 642, - 186, 250, 425, 349, 358, 182, 351, 557, 433, 347, - 238, 344, 339, 429, 302, 402, 243, 445, 447, 456, - 460, 163, 454, 458, 243, 250, 485, 143, 148, 449, - 353, 526, 176, 467, 237, 450, 238, 415, 338, 188, - 410, 237, 302, 336, 436, 482, 334, 169, 439, 436, - 146, 417, 392, 439, 140, 522, 358, 400, 404, 0, - 390, 171, 358, 0, 186, 500, 146, 0, 643, 0, - 0, 178, 0, 0, 0, 0, 404, 60, 60, 489, - 452, 500, 320, 0, 534, 0, 405, 60, 0, 180, - 146, 60, 0, 180, 60, 407, 490, 60, 302, 452, - 60, 60, 60, 60, 405, 60, 284, 285, 287, 60, - 286, 451, 358, 60, 165, 180, 266, 60, 60, 461, - 451, 270, 288, 60, 60, 60, 493, 60, 60, 60, - 84, 106, 92, 91, 60, 432, 60, 72, 60, 168, - 98, 435, 77, 60, 96, 60, 60, 60, 341, 302, - 93, 94, 500, 108, 329, 100, 60, 102, 60, 618, - 302, 95, 88, 330, 60, 60, 60, 60, 90, 89, - 70, 60, 97, 452, 60, 60, 451, 492, 60, 60, - 494, 60, 61, 68, 60, 60, 69, 491, 60, 471, - 67, 302, 404, 480, 60, 106, 60, 479, 0, 270, - 298, 270, 298, 278, 298, 270, 0, 270, 60, 270, - 0, 316, 0, 270, 332, 0, 500, 108, 175, 538, - 405, 293, 319, 0, 317, 303, 326, 60, 60, 60, - 0, 0, 270, 270, 270, 290, 291, 60, 295, 298, - 60, 60, 270, 298, 270, 270, 270, 289, 270, 0, - 273, 500, 313, 0, 551, 545, 305, 534, 508, 615, - 542, 297, 0, 500, 0, 300, 499, 509, 500, 0, - 508, 0, 0, 0, 0, 508, 472, 0, 499, 509, - 583, 0, 0, 499, 509, 0, 0, 586, 579, 580, - 581, 582, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 550, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 551, - 0, 0, 0, 0, 0, 0, 552, 0, 0, 0, + 567, 169, 558, 570, 574, 515, 569, 557, 309, 548, + 461, 528, 311, 530, 417, 555, 307, 188, 415, 358, + 392, 250, 628, 612, 320, 623, 150, 253, 16, 637, + 496, 497, 498, 390, 614, 186, 634, 472, 182, 400, + 487, 243, 436, 238, 436, 176, 182, 302, 514, 171, + 238, 439, 334, 429, 439, 447, 454, 336, 339, 358, + 243, 140, 433, 302, 338, 237, 349, 351, 449, 482, + 146, 182, 148, 460, 485, 458, 353, 250, 250, 243, + 344, 410, 238, 163, 467, 456, 524, 143, 436, 425, + 237, 439, 445, 302, 402, 358, 461, 404, 0, 450, + 60, 358, 404, 186, 146, 92, 0, 0, 0, 407, + 500, 60, 0, 638, 500, 60, 84, 536, 320, 500, + 0, 98, 540, 60, 302, 60, 405, 490, 91, 302, + 0, 405, 60, 0, 180, 302, 60, 106, 489, 60, + 60, 60, 180, 60, 93, 60, 286, 60, 285, 60, + 94, 146, 284, 90, 60, 60, 178, 452, 89, 60, + 108, 60, 358, 60, 95, 60, 287, 471, 288, 88, + 60, 302, 451, 60, 60, 60, 452, 451, 60, 404, + 68, 432, 60, 102, 494, 60, 347, 67, 341, 60, + 330, 329, 61, 266, 60, 305, 69, 60, 270, 60, + 70, 303, 60, 60, 60, 480, 451, 0, 405, 479, + 72, 0, 60, 165, 491, 60, 60, 60, 180, 168, + 60, 97, 492, 60, 60, 452, 60, 60, 493, 100, + 96, 60, 0, 77, 60, 0, 270, 332, 298, 270, + 273, 60, 435, 270, 60, 298, 270, 298, 278, 270, + 270, 316, 270, 60, 298, 295, 298, 60, 270, 270, + 297, 270, 270, 106, 291, 60, 60, 326, 313, 317, + 270, 270, 290, 289, 552, 60, 319, 536, 300, 610, + 270, 519, 520, 521, 522, 500, 108, 175, 293, 0, + 0, 500, 508, 0, 0, 544, 0, 472, 613, 547, + 0, 499, 509, 500, 0, 0, 0, 500, 0, 0, + 508, 0, 0, 0, 508, 0, 0, 0, 577, 499, + 509, 0, 0, 499, 509, 580, 581, 519, 520, 521, + 522, 552, 0, 0, 0, 0, 0, 0, 553, 554, + 519, 520, 521, 522, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 560, 519, 520, 521, 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0}; + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0}; const short QDeclarativeJSGrammar::action_check [] = { - 7, 16, 55, 7, 33, 36, 33, 55, 36, 7, - 7, 7, 7, 7, 7, 36, 7, 7, 36, 8, - 36, 55, 60, 29, 7, 7, 36, 7, 33, 7, - 7, 7, 7, 36, 36, 48, 1, 0, 90, 79, - 7, 33, 8, 90, 2, 7, 33, 55, 36, 60, - 36, 20, 33, 5, 1, 5, 79, 36, 7, 33, - 5, 60, 33, 33, 8, 33, 17, 24, 2, 7, - 34, 2, 7, 1, 7, 36, 60, 37, 8, 8, - 36, 66, 36, 7, 1, 17, -1, -1, 36, 48, - 36, 33, 8, 66, 7, 48, 36, 33, 7, 36, - 2, 7, 8, 8, 8, 77, 61, 15, 8, 8, - 6, -1, 31, 36, 8, 10, -1, -1, -1, 60, - 8, 60, -1, 48, 20, -1, 34, -1, 8, 8, - 8, -1, -1, 60, 60, 8, 79, 55, 60, 50, - 8, 61, 8, 54, 8, 8, 61, 61, 62, 61, - 62, 42, 56, 50, 40, 60, 56, 54, 79, 40, - 55, 60, 53, 61, 62, 51, 60, 15, 61, 62, - 51, 61, 62, 61, 61, 62, 56, 56, 61, 62, - 40, 8, 60, 8, 61, 62, 34, 60, 8, 61, - 62, 51, 60, 56, 60, 40, 60, 12, 29, 61, - 62, 25, 25, 27, 27, 15, 51, 36, 29, 15, - 29, 61, 62, 12, 38, 38, 8, 29, 7, 7, - 29, -1, 8, -1, 34, 8, 36, 25, 34, 27, - 36, 15, 61, 62, 61, 62, 61, 62, 7, 29, - 38, 91, 57, 7, 75, 33, 8, 25, 63, 27, - 34, -1, 36, -1, 75, 86, 75, 12, 57, -1, - 38, 15, -1, 75, 63, 86, 75, 86, 15, 61, - 62, -1, 61, 62, 86, 61, 62, 86, 61, 62, - 34, 25, 36, 27, -1, 75, 33, 34, 29, 36, - 18, 19, 61, 62, 38, 47, 86, 61, 62, 61, - 62, 15, 57, -1, 92, 18, 19, -1, 63, 61, - 62, 29, -1, 18, 19, 18, 19, 45, 46, 33, - 34, -1, 36, 29, -1, 66, 67, 68, -1, -1, - -1, -1, 45, 46, 29, -1, -1, -1, 29, 91, - 45, 46, 45, 46, 23, 24, 29, -1, 66, 67, - 68, 92, 29, 32, 23, 24, 35, 25, 37, 27, - 66, 67, 68, 32, -1, 29, 35, -1, 37, 29, - 38, 66, 67, 68, 92, 66, 67, 68, -1, -1, - 29, -1, -1, 66, 67, 68, 92, 29, -1, 66, - 67, 68, 29, -1, -1, -1, -1, 92, 29, -1, - -1, 92, 66, 67, 68, -1, 66, 67, 68, 92, - -1, -1, -1, -1, 29, 92, -1, 66, 67, 68, - 29, -1, -1, -1, 66, 67, 68, 29, 92, 66, - 67, 68, 92, 23, 24, 66, 67, 68, -1, -1, - -1, 29, 32, 92, -1, 35, -1, 37, 36, 29, - 92, 66, 67, 68, -1, 92, 36, 66, 67, 68, - -1, 92, 23, 24, 66, 67, 68, -1, -1, -1, - 31, 32, -1, -1, 35, -1, 37, 92, 66, 67, - 68, -1, -1, 92, 23, 24, 66, 67, 68, 29, - 92, -1, 31, 32, 23, 24, 35, 29, 37, -1, - -1, -1, 31, 32, 92, 29, 35, -1, 37, -1, - -1, 29, 92, -1, 93, 94, 95, 96, 97, 98, - -1, 61, 62, -1, 29, -1, 66, 67, 68, 61, - 62, -1, -1, 29, 66, 67, 68, 61, 62, -1, - -1, -1, 66, 67, 68, -1, -1, -1, 66, 67, - 68, -1, 92, -1, -1, -1, 61, 62, -1, -1, - 92, 66, 67, 68, -1, 61, 62, 29, 92, -1, - 66, 67, 68, -1, 92, -1, -1, -1, -1, -1, - -1, -1, -1, 23, 24, -1, -1, 92, 3, -1, - -1, 31, 32, -1, -1, 35, 92, 37, 13, 61, - 62, -1, 17, -1, 66, 67, 68, -1, -1, -1, - -1, 26, -1, 28, -1, -1, 31, -1, -1, -1, - -1, -1, -1, -1, 39, -1, 41, 42, -1, -1, - 92, -1, -1, -1, 49, -1, -1, 52, 53, -1, - -1, -1, -1, 58, -1, -1, -1, -1, -1, 64, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, - 13, 3, -1, -1, -1, 80, -1, -1, -1, 22, - -1, 13, -1, -1, -1, 17, 29, -1, -1, -1, - 33, 34, -1, 36, 26, -1, 28, -1, -1, -1, - 43, -1, -1, -1, 47, -1, -1, 39, -1, 41, - 42, -1, -1, -1, -1, -1, -1, 49, -1, -1, - 52, 53, 65, 66, 67, 68, 58, 70, -1, -1, - -1, -1, 64, -1, -1, -1, -1, -1, 81, 82, - 83, 12, 13, -1, 87, -1, -1, -1, 80, 92, - -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, - -1, -1, 33, 34, -1, 36, -1, -1, -1, 12, - 13, -1, 43, -1, -1, -1, 47, -1, -1, 22, - -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, - 33, 34, -1, 36, 65, 66, 67, 68, -1, 70, - 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, - 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, - -1, 92, 65, 66, 67, 68, -1, 70, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 81, 82, - 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, - 12, 13, -1, -1, -1, -1, -1, -1, 12, 13, - 22, -1, -1, -1, -1, -1, -1, 29, 22, -1, - -1, 33, 34, -1, 36, 29, -1, -1, -1, 33, - 34, 43, 36, -1, -1, 47, -1, -1, -1, 43, - -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, - -1, 65, 66, 67, 68, -1, 70, -1, -1, 81, - 82, 83, -1, -1, -1, 87, -1, 81, 82, 83, - 92, -1, -1, 87, -1, -1, -1, -1, 92, 12, - 13, -1, -1, -1, -1, -1, -1, 12, 13, 22, - -1, -1, -1, -1, -1, -1, 29, 22, -1, -1, - 33, 34, -1, 36, 29, -1, -1, -1, 33, 34, - 43, 36, -1, -1, 47, -1, -1, -1, 43, -1, - -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 65, 66, 67, 68, -1, 70, -1, -1, - 65, 66, 67, 68, -1, 70, -1, -1, 81, 82, - 83, -1, -1, -1, 87, -1, 81, 82, 83, 92, - -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, - -1, -1, -1, -1, -1, -1, 10, -1, 12, 13, - -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, - -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, - 34, -1, 36, -1, -1, -1, -1, -1, -1, 43, - -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 65, 66, 67, 68, -1, 70, -1, -1, -1, - -1, 75, -1, -1, -1, -1, -1, 81, 82, 83, - 84, -1, -1, 87, -1, -1, -1, -1, 92, -1, - -1, -1, -1, -1, -1, -1, -1, 10, -1, 12, - 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, - -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, - 33, 34, -1, 36, -1, -1, -1, -1, -1, -1, - 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, - -1, -1, 55, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 65, 66, 67, 68, -1, 70, -1, -1, - -1, -1, 75, -1, -1, -1, -1, -1, 81, 82, - 83, 84, -1, -1, 87, -1, -1, -1, -1, 92, - -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, + 36, 36, 33, 33, 60, 7, 7, 36, 8, 36, + 7, 16, 55, 7, 7, 7, 55, 36, 36, 7, + 90, 7, 55, 7, 36, 7, 60, 33, 60, 33, + 33, 7, 7, 29, 8, 60, 17, 7, 66, 37, + 66, 24, 33, 7, 34, 5, 33, 36, 33, 7, + 60, 5, 7, 33, 33, 7, 7, 20, 36, 36, + 5, 7, 61, 36, 7, 7, 77, 36, 17, 8, + 36, 79, 7, 2, 33, 36, 8, 1, 8, 36, + 48, 2, 1, 55, 79, 1, 36, 2, 8, 60, + 7, 31, 48, 0, 61, 36, 33, 8, 60, 7, + 36, 2, 55, 36, 7, 1, 8, -1, -1, 15, + 10, 8, -1, 60, 79, 8, 8, 61, 8, 50, + 48, 48, 60, 54, 8, 7, 8, 8, 34, 42, + 8, 8, 6, 8, -1, 61, 62, 8, 61, 62, + 53, 8, 90, 61, 62, 79, 20, 61, 62, 61, + 62, 61, 62, 15, 40, 55, 61, 62, 60, 7, + 40, 8, 8, 60, 56, 51, 56, 60, 40, 8, + 7, 51, 34, 61, 62, 56, 60, 40, 56, 51, + 50, 56, 15, 60, 54, 61, 62, 29, 51, 60, + 12, 12, 15, 60, 8, 61, 62, 25, -1, 27, + 12, 34, -1, 36, 61, 62, 25, -1, 27, 29, + 38, 34, 29, 36, 61, 61, 62, 7, 25, 38, + 27, 7, 61, 62, 61, 62, 25, 25, 27, 27, + -1, 38, 29, 75, 91, 57, 57, 7, 15, 38, + 38, 63, 63, 33, 86, 57, -1, 61, 62, 15, + 25, 63, 27, 8, 25, 75, 27, 34, 75, 36, + 25, 29, 27, 38, -1, 29, 86, 38, 34, 86, + 36, -1, -1, 38, 36, 61, 62, 15, 75, -1, + -1, 18, 19, -1, -1, 18, 19, -1, -1, 86, + -1, 61, 62, 18, 19, 33, 34, 29, 36, 61, + 62, 47, 92, 18, 19, 60, 15, 75, 45, 46, + -1, 75, 45, 46, -1, 61, 62, 29, 86, -1, + 45, 46, 86, -1, 33, 34, 29, 36, 23, 24, + 45, 46, 29, -1, 66, 67, 68, 32, 29, -1, + 35, -1, 37, -1, 29, 91, 25, 29, 27, -1, + -1, -1, -1, -1, 66, 67, 68, -1, -1, 38, + 92, -1, -1, 66, 67, 68, -1, -1, -1, 66, + 67, 68, -1, -1, -1, 66, 67, 68, 23, 24, + 92, 66, 67, 68, 66, 67, 68, 32, -1, 92, + 35, -1, 37, -1, -1, 92, -1, 23, 24, -1, + -1, 92, -1, 23, 24, -1, 32, 92, -1, 35, + 92, 37, 32, 29, -1, 35, -1, 37, 23, 24, + 36, -1, 29, -1, -1, -1, 31, 32, 23, 24, + 35, -1, 37, -1, -1, -1, 31, 32, -1, -1, + 35, -1, 37, 93, 94, 95, 96, 97, 98, -1, + 66, 67, 68, -1, 23, 24, -1, -1, -1, 66, + 67, 68, 31, 32, -1, -1, 35, -1, 37, 23, + 24, -1, 29, -1, -1, -1, 92, 31, 32, 23, + 24, 35, 29, 37, -1, 92, -1, 31, 32, 36, + 29, 35, -1, 37, 23, 24, -1, -1, -1, 29, + -1, -1, -1, 32, 61, 62, 35, -1, 37, 66, + 67, 68, -1, -1, -1, -1, -1, 29, -1, 66, + 67, 68, 61, 62, -1, -1, 29, 66, 67, 68, + -1, 61, 62, -1, -1, 92, 66, 67, 68, -1, + -1, -1, -1, -1, -1, 92, -1, -1, -1, 61, + 62, -1, -1, 92, 66, 67, 68, -1, 61, 62, + -1, -1, 92, 66, 67, 68, -1, -1, -1, -1, + -1, -1, 29, -1, -1, -1, -1, -1, 3, -1, + 92, -1, -1, -1, -1, -1, -1, -1, 13, 92, + -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, + -1, 26, -1, 28, 61, 62, 31, -1, -1, 66, + 67, 68, -1, -1, 39, -1, 41, 42, -1, -1, + -1, -1, -1, -1, 49, -1, -1, 52, 53, -1, + -1, -1, -1, 58, -1, 92, -1, -1, -1, 64, + -1, -1, 12, 13, 3, -1, -1, -1, -1, -1, + -1, -1, 22, -1, 13, 80, -1, -1, 17, 29, + -1, -1, -1, 33, 34, -1, 36, 26, -1, 28, + -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, + 39, -1, 41, 42, -1, -1, -1, -1, -1, -1, + 49, -1, -1, 52, 53, 65, 66, 67, 68, 58, + 70, -1, -1, -1, -1, 64, -1, -1, -1, -1, + -1, 81, 82, 83, 12, 13, -1, 87, -1, -1, + -1, 80, 92, -1, 22, -1, -1, -1, -1, -1, + -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, + -1, -1, 12, 13, -1, 43, -1, -1, -1, 47, + -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, + -1, -1, -1, 33, 34, -1, 36, 65, 66, 67, + 68, -1, 70, 43, -1, -1, -1, 47, -1, -1, + -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, + -1, -1, -1, -1, 92, 65, 66, 67, 68, -1, + 70, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, + -1, -1, 92, 12, 13, -1, -1, -1, -1, -1, + -1, 12, 13, 22, -1, -1, -1, -1, -1, -1, + 29, 22, -1, -1, 33, 34, -1, 36, 29, -1, + -1, -1, 33, 34, 43, 36, -1, -1, 47, -1, + -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, + -1, 70, -1, -1, 65, 66, 67, 68, -1, 70, + -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, + 81, 82, 83, 92, -1, -1, 87, -1, -1, -1, + -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, - -1, -1, -1, 55, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, - -1, -1, -1, 75, -1, -1, -1, -1, -1, 81, - 82, 83, 84, -1, -1, 87, -1, -1, -1, -1, - 92, -1, -1, -1, -1, -1, -1, -1, -1, 11, - 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, - 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, - -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, - 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, - -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, - 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, - 92, -1, -1, -1, -1, -1, -1, -1, -1, 7, - -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, - -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, - -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, - -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, - -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, - 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, - -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, - -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, - -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, - -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, - -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, - -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, - -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, - 68, -1, 70, -1, 72, -1, 74, 75, 76, -1, - -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, - -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, - -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, + 92, -1, -1, -1, -1, -1, -1, -1, -1, 10, + -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, + -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, + -1, -1, 33, 34, -1, 36, -1, -1, -1, -1, + -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, + -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, + 81, 82, 83, 84, -1, -1, 87, -1, -1, -1, + -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, + 10, -1, 12, 13, -1, -1, -1, -1, -1, -1, + -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, + -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, + -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, + -1, -1, -1, -1, -1, 55, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, + 70, -1, -1, -1, -1, 75, -1, -1, -1, -1, + -1, 81, 82, 83, 84, -1, -1, 87, -1, -1, + -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, + -1, 10, -1, 12, 13, -1, -1, -1, -1, -1, + -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, + 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, + -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, + -1, -1, -1, -1, -1, -1, 55, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, + -1, 70, -1, -1, -1, -1, 75, -1, -1, -1, + -1, -1, 81, 82, 83, 84, -1, -1, 87, -1, + -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, + -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, + -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, + 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, + -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, + -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, + -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, + -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, + -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, + -1, -1, 7, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, - -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, + -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, + -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, + -1, -1, -1, -1, -1, -1, 11, 12, 13, -1, + -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, + -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, + -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, + -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, + 75, 76, -1, -1, -1, -1, 81, 82, 83, -1, + -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, + -1, -1, -1, -1, -1, -1, 11, 12, 13, -1, + -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, + -1, -1, -1, -1, 29, 30, -1, -1, 33, 34, + -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, + -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, + -1, -1, -1, -1, -1, -1, 61, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, @@ -841,6 +848,15 @@ const short QDeclarativeJSGrammar::action_check [] = { -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, + 92, -1, -1, -1, -1, -1, -1, -1, -1, 11, + 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, + 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, + -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, + 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, + -1, 53, -1, -1, -1, -1, -1, -1, -1, 61, + -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, + 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, + 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, @@ -860,44 +876,54 @@ const short QDeclarativeJSGrammar::action_check [] = { 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, - -1, -1, -1, -1, -1, 11, 12, 13, -1, -1, - -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, - -1, -1, -1, 29, 30, -1, -1, 33, 34, -1, - 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, - -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, - -1, -1, -1, -1, -1, 61, -1, -1, -1, 65, - 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, - 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, - -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, + -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, + 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, + -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, + 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, + 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, + 53, -1, -1, 56, -1, -1, -1, -1, -1, -1, + -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, + -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, + 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, + -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, + 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, + 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, + -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 59, -1, -1, -1, -1, -1, -1, + 66, 67, 68, 69, 70, 71, -1, 73, 74, 75, + 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, + 86, -1, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 59, -1, -1, -1, -1, -1, -1, 66, 67, 68, + 59, -1, -1, -1, -1, -1, 65, 66, 67, -1, 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, -1, -1, - -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 59, -1, -1, + -1, -1, -1, 55, -1, -1, -1, 59, -1, -1, -1, -1, -1, 65, 66, 67, -1, 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, - 5, 6, -1, -1, 9, 10, 11, -1, -1, 14, - -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, - -1, -1, -1, -1, 29, 30, 31, 32, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, - -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, - 55, -1, -1, -1, 59, -1, -1, -1, -1, -1, - 65, 66, 67, -1, 69, 70, 71, -1, 73, 74, + -1, -1, -1, -1, 9, -1, 11, 12, 13, 14, + -1, -1, -1, -1, -1, -1, 21, 22, -1, -1, + -1, -1, -1, -1, 29, 30, -1, -1, 33, 34, + -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, + -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, + -1, -1, -1, -1, 59, -1, 61, -1, -1, -1, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, - 85, 86, -1, -1, -1, -1, -1, -1, -1, -1, + 85, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, 9, -1, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, 21, 22, -1, -1, -1, -1, -1, @@ -908,74 +934,66 @@ const short QDeclarativeJSGrammar::action_check [] = { 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, - -1, -1, -1, 4, -1, -1, -1, -1, 9, -1, - 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, + 11, 12, 13, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, - -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, + 31, 32, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, - 81, 82, 83, 84, 85, -1, 87, -1, -1, -1, + 81, 82, 83, 84, 85, 86, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, 12, 13, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, - -1, -1, -1, -1, -1, 59, -1, 61, -1, -1, + -1, 55, -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, 87, -1, -1, -1, -1, 92, -1, - -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, - -1, -1, 9, 10, 11, 12, 13, 14, -1, 16, - -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, - -1, -1, 29, 30, 31, 32, 33, 34, -1, 36, - -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, - 47, -1, -1, -1, 51, -1, 53, -1, 55, -1, - -1, -1, 59, -1, 61, -1, -1, -1, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, - 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, - -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, - 35, 15, 15, 15, 2, 15, 3, 2, 25, 3, - 15, 15, 104, 15, 4, 3, 3, 3, 19, 15, - 2, 21, 15, 15, 3, 67, 25, 3, 19, 2, - 15, 2, 15, 13, 15, 19, 25, 3, 15, 11, - 15, 2, 96, 3, 2, 15, 2, 25, 3, 2, - 15, 100, 15, 93, 3, 2, 15, 98, 15, 2, - 2, 35, 3, 3, 15, 2, 35, 35, 35, 21, - 2, 25, 3, 35, 4, 21, 15, 2, 2, 15, - 2, 4, 3, 3, 3, 35, 2, 35, 21, 3, - 35, 3, 36, 21, 3, 13, 2, 35, 13, -1, - 35, 35, 2, -1, 15, 13, 35, -1, 16, -1, - -1, 40, -1, -1, -1, -1, 13, 44, 44, 46, - 46, 13, 15, -1, 16, -1, 41, 44, -1, 46, - 35, 44, -1, 46, 44, 40, 46, 44, 3, 46, - 44, 44, 44, 44, 41, 44, 49, 49, 49, 44, - 49, 46, 2, 44, 58, 46, 44, 44, 44, 15, - 46, 49, 49, 44, 44, 44, 46, 44, 44, 44, - 49, 15, 49, 49, 44, 81, 44, 52, 44, 60, - 50, 81, 50, 44, 50, 44, 44, 44, 99, 3, - 49, 49, 13, 37, 87, 56, 44, 54, 44, 20, - 3, 49, 48, 68, 44, 44, 44, 44, 48, 48, - 47, 44, 50, 46, 44, 44, 46, 46, 44, 44, - 46, 44, 47, 46, 44, 44, 46, 46, 44, 85, - 46, 3, 13, 31, 44, 15, 44, 35, -1, 49, - 44, 49, 44, 51, 44, 49, -1, 49, 44, 49, - -1, 61, -1, 49, 68, -1, 13, 37, 38, 16, - 41, 57, 66, -1, 66, 68, 66, 44, 44, 44, - -1, -1, 49, 49, 49, 51, 51, 44, 55, 44, - 44, 44, 49, 44, 49, 49, 49, 51, 49, -1, - 53, 13, 59, -1, 13, 5, 68, 16, 20, 18, - 5, 66, -1, 13, -1, 66, 28, 29, 13, -1, - 20, -1, -1, -1, -1, 20, 35, -1, 28, 29, - 13, -1, -1, 28, 29, -1, -1, 20, 21, 22, - 23, 24, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, - -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, + 26, 36, 15, 15, 15, 15, 26, 26, 3, 15, + 15, 26, 2, 15, 3, 19, 2, 15, 2, 2, + 37, 2, 15, 19, 15, 13, 68, 3, 3, 11, + 105, 4, 2, 36, 19, 15, 15, 36, 15, 36, + 3, 15, 3, 15, 3, 3, 15, 3, 26, 36, + 15, 22, 2, 94, 22, 15, 3, 3, 15, 2, + 15, 3, 3, 3, 2, 4, 3, 2, 22, 36, + 36, 15, 36, 2, 36, 3, 2, 2, 2, 15, + 101, 2, 15, 36, 36, 2, 13, 36, 3, 97, + 4, 22, 99, 3, 2, 2, 15, 13, -1, 22, + 45, 2, 13, 15, 36, 50, -1, -1, -1, 41, + 13, 45, -1, 16, 13, 45, 50, 16, 15, 13, + -1, 51, 16, 45, 3, 45, 42, 47, 50, 3, + -1, 42, 45, -1, 47, 3, 45, 15, 47, 45, + 45, 45, 47, 45, 50, 45, 50, 45, 50, 45, + 50, 36, 50, 49, 45, 45, 41, 47, 49, 45, + 38, 45, 2, 45, 50, 45, 50, 86, 50, 49, + 45, 3, 47, 45, 45, 45, 47, 47, 45, 13, + 47, 82, 45, 55, 47, 45, 2, 47, 100, 45, + 69, 88, 48, 45, 45, 69, 47, 45, 50, 45, + 48, 69, 45, 45, 45, 32, 47, -1, 42, 36, + 53, -1, 45, 59, 47, 45, 45, 45, 47, 61, + 45, 51, 47, 45, 45, 47, 45, 45, 47, 57, + 51, 45, -1, 51, 45, -1, 50, 69, 45, 50, + 54, 45, 82, 50, 45, 45, 50, 45, 52, 50, + 50, 62, 50, 45, 45, 56, 45, 45, 50, 50, + 67, 50, 50, 15, 52, 45, 45, 67, 60, 67, + 50, 50, 52, 52, 13, 45, 67, 16, 67, 18, + 50, 22, 23, 24, 25, 13, 38, 39, 58, -1, + -1, 13, 20, -1, -1, 5, -1, 36, 20, 5, + -1, 29, 30, 13, -1, -1, -1, 13, -1, -1, + 20, -1, -1, -1, 20, -1, -1, -1, 13, 29, + 30, -1, -1, 29, 30, 20, 21, 22, 23, 24, + 25, 13, -1, -1, -1, -1, -1, -1, 20, 21, + 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -984,6 +1002,6 @@ const short QDeclarativeJSGrammar::action_check [] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1}; + -1}; QT_END_NAMESPACE diff --git a/src/declarative/qml/parser/qdeclarativejsgrammar_p.h b/src/declarative/qml/parser/qdeclarativejsgrammar_p.h index ed3ca19041..3530a88773 100644 --- a/src/declarative/qml/parser/qdeclarativejsgrammar_p.h +++ b/src/declarative/qml/parser/qdeclarativejsgrammar_p.h @@ -164,15 +164,15 @@ public: T_XOR = 79, T_XOR_EQ = 80, - ACCEPT_STATE = 645, - RULE_COUNT = 347, - STATE_COUNT = 646, + ACCEPT_STATE = 640, + RULE_COUNT = 345, + STATE_COUNT = 641, TERMINAL_COUNT = 101, - NON_TERMINAL_COUNT = 106, + NON_TERMINAL_COUNT = 107, - GOTO_INDEX_OFFSET = 646, - GOTO_INFO_OFFSET = 2714, - GOTO_CHECK_OFFSET = 2714 + GOTO_INDEX_OFFSET = 641, + GOTO_INFO_OFFSET = 2787, + GOTO_CHECK_OFFSET = 2787 }; static const char *const spell []; diff --git a/src/declarative/qml/parser/qdeclarativejsparser.cpp b/src/declarative/qml/parser/qdeclarativejsparser.cpp index 118dcc6538..5545e8c0be 100644 --- a/src/declarative/qml/parser/qdeclarativejsparser.cpp +++ b/src/declarative/qml/parser/qdeclarativejsparser.cpp @@ -361,7 +361,8 @@ case 33: { node->hasOnToken = true; sym(1).Node = node; } break; -case 34:case 35:case 36:case 37: + +case 38: { AST::UiScriptBinding *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId, sym(3).Statement); @@ -369,35 +370,35 @@ case 34:case 35:case 36:case 37: sym(1).Node = node; } break; -case 38: +case 39: -case 39: { +case 40: { sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); break; } -case 41: { +case 42: { sym(1).Node = 0; } break; -case 42: { +case 43: { sym(1).Node = sym(1).UiParameterList->finish (); } break; -case 43: { +case 44: { AST::UiParameterList *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).sval); node->identifierToken = loc(2); sym(1).Node = node; } break; -case 44: { +case 45: { AST::UiParameterList *node = makeAstNode (driver->nodePool(), sym(1).UiParameterList, sym(3).sval, sym(4).sval); node->commaToken = loc(2); node->identifierToken = loc(4); sym(1).Node = node; } break; -case 46: { +case 47: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), (NameId *)0, sym(2).sval); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); @@ -408,7 +409,7 @@ case 46: { sym(1).Node = node; } break; -case 48: { +case 49: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), (NameId *)0, sym(2).sval); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); @@ -418,7 +419,7 @@ case 48: { sym(1).Node = node; } break; -case 50: { +case 51: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(4).sval, sym(6).sval); node->typeModifier = sym(2).sval; node->propertyToken = loc(1); @@ -429,7 +430,7 @@ case 50: { sym(1).Node = node; } break; -case 52: { +case 53: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(3).sval); node->propertyToken = loc(1); node->typeToken = loc(2); @@ -438,7 +439,7 @@ case 52: { sym(1).Node = node; } break; -case 54: { +case 55: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(4).sval); node->isDefaultMember = true; node->defaultToken = loc(1); @@ -451,42 +452,39 @@ case 54: { case 56: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(3).sval, - sym(5).Expression); + sym(5).Statement); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); node->colonToken = loc(4); - node->semicolonToken = loc(6); sym(1).Node = node; } break; -case 58: { +case 57: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(4).sval, - sym(6).Expression); + sym(6).Statement); node->isReadonlyMember = true; node->readonlyToken = loc(1); node->propertyToken = loc(2); node->typeToken = loc(3); node->identifierToken = loc(4); node->colonToken = loc(5); - node->semicolonToken = loc(7); sym(1).Node = node; } break; -case 60: { +case 58: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(4).sval, - sym(6).Expression); + sym(6).Statement); node->isDefaultMember = true; node->defaultToken = loc(1); node->propertyToken = loc(2); node->typeToken = loc(3); node->identifierToken = loc(4); node->colonToken = loc(5); - node->semicolonToken = loc(7); sym(1).Node = node; } break; -case 61: { +case 59: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(4).sval, sym(6).sval); node->typeModifier = sym(2).sval; node->propertyToken = loc(1); @@ -510,7 +508,7 @@ case 61: { sym(1).Node = node; } break; -case 62: { +case 60: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(3).sval); node->propertyToken = loc(1); node->typeToken = loc(2); @@ -530,81 +528,81 @@ case 62: { sym(1).Node = node; } break; -case 63: { +case 61: { sym(1).Node = makeAstNode(driver->nodePool(), sym(1).Node); } break; -case 64: { +case 62: { sym(1).Node = makeAstNode(driver->nodePool(), sym(1).Node); } break; -case 66: { +case 64: { QString s = QLatin1String(QDeclarativeJSGrammar::spell[T_PROPERTY]); sym(1).sval = driver->intern(s.constData(), s.length()); break; } -case 67: { +case 65: { QString s = QLatin1String(QDeclarativeJSGrammar::spell[T_SIGNAL]); sym(1).sval = driver->intern(s.constData(), s.length()); break; } -case 68: { +case 66: { QString s = QLatin1String(QDeclarativeJSGrammar::spell[T_READONLY]); sym(1).sval = driver->intern(s.constData(), s.length()); break; } -case 69: { +case 67: { QString s = QLatin1String(QDeclarativeJSGrammar::spell[T_ON]); sym(1).sval = driver->intern(s.constData(), s.length()); break; } -case 70: { +case 68: { AST::ThisExpression *node = makeAstNode (driver->nodePool()); node->thisToken = loc(1); sym(1).Node = node; } break; -case 71: { +case 69: { AST::IdentifierExpression *node = makeAstNode (driver->nodePool(), sym(1).sval); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 72: { +case 70: { AST::NullExpression *node = makeAstNode (driver->nodePool()); node->nullToken = loc(1); sym(1).Node = node; } break; -case 73: { +case 71: { AST::TrueLiteral *node = makeAstNode (driver->nodePool()); node->trueToken = loc(1); sym(1).Node = node; } break; -case 74: { +case 72: { AST::FalseLiteral *node = makeAstNode (driver->nodePool()); node->falseToken = loc(1); sym(1).Node = node; } break; -case 75: { +case 73: { AST::NumericLiteral *node = makeAstNode (driver->nodePool(), sym(1).dval); node->literalToken = loc(1); sym(1).Node = node; } break; -case 76: -case 77: { +case 74: +case 75: { AST::StringLiteral *node = makeAstNode (driver->nodePool(), sym(1).sval); node->literalToken = loc(1); sym(1).Node = node; } break; -case 78: { +case 76: { bool rx = lexer->scanRegExp(Lexer::NoPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); @@ -618,7 +616,7 @@ case 78: { sym(1).Node = node; } break; -case 79: { +case 77: { bool rx = lexer->scanRegExp(Lexer::EqualPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); @@ -632,28 +630,28 @@ case 79: { sym(1).Node = node; } break; -case 80: { +case 78: { AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), (AST::Elision *) 0); node->lbracketToken = loc(1); node->rbracketToken = loc(2); sym(1).Node = node; } break; -case 81: { +case 79: { AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).Elision->finish()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; -case 82: { +case 80: { AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish ()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; -case 83: { +case 81: { AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish (), (AST::Elision *) 0); node->lbracketToken = loc(1); @@ -662,7 +660,7 @@ case 83: { sym(1).Node = node; } break; -case 84: { +case 82: { AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish (), sym(4).Elision->finish()); node->lbracketToken = loc(1); @@ -671,7 +669,7 @@ case 84: { sym(1).Node = node; } break; -case 85: { +case 83: { AST::ObjectLiteral *node = 0; if (sym(2).Node) node = makeAstNode (driver->nodePool(), @@ -683,7 +681,7 @@ case 85: { sym(1).Node = node; } break; -case 86: { +case 84: { AST::ObjectLiteral *node = makeAstNode (driver->nodePool(), sym(2).PropertyNameAndValueList->finish ()); node->lbraceToken = loc(1); @@ -691,14 +689,14 @@ case 86: { sym(1).Node = node; } break; -case 87: { +case 85: { AST::NestedExpression *node = makeAstNode(driver->nodePool(), sym(2).Expression); node->lparenToken = loc(1); node->rparenToken = loc(3); sym(1).Node = node; } break; -case 88: { +case 86: { if (AST::ArrayMemberExpression *mem = AST::cast(sym(1).Expression)) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken, QLatin1String("Ignored annotation"))); @@ -718,48 +716,48 @@ case 88: { } } break; -case 89: { +case 87: { sym(1).Node = makeAstNode (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression); } break; -case 90: { +case 88: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression); } break; -case 91: { +case 89: { AST::ElementList *node = makeAstNode (driver->nodePool(), sym(1).ElementList, (AST::Elision *) 0, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 92: { +case 90: { AST::ElementList *node = makeAstNode (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(), sym(4).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 93: { +case 91: { AST::Elision *node = makeAstNode (driver->nodePool()); node->commaToken = loc(1); sym(1).Node = node; } break; -case 94: { +case 92: { AST::Elision *node = makeAstNode (driver->nodePool(), sym(1).Elision); node->commaToken = loc(2); sym(1).Node = node; } break; -case 95: { +case 93: { AST::PropertyNameAndValueList *node = makeAstNode (driver->nodePool(), sym(1).PropertyName, sym(3).Expression); node->colonToken = loc(2); sym(1).Node = node; } break; -case 96: { +case 94: { AST::PropertyNameAndValueList *node = makeAstNode (driver->nodePool(), sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); node->commaToken = loc(2); @@ -767,36 +765,40 @@ case 96: { sym(1).Node = node; } break; -case 97: { +case 95: { AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 98: -case 99: { +case 96: +case 97: { AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 100: { +case 98: { AST::StringLiteralPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 101: { +case 99: { AST::NumericLiteralPropertyName *node = makeAstNode (driver->nodePool(), sym(1).dval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 102: { +case 100: { AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; +case 101: + +case 102: + case 103: case 104: @@ -854,29 +856,25 @@ case 129: case 130: case 131: - -case 132: - -case 133: { sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); } break; -case 138: { +case 136: { AST::ArrayMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; -case 139: { +case 137: { AST::FieldMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).sval); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 140: { +case 138: { AST::NewMemberExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList); node->newToken = loc(1); node->lparenToken = loc(3); @@ -884,384 +882,384 @@ case 140: { sym(1).Node = node; } break; -case 142: { +case 140: { AST::NewExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->newToken = loc(1); sym(1).Node = node; } break; -case 143: { +case 141: { AST::CallExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; -case 144: { +case 142: { AST::CallExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; -case 145: { +case 143: { AST::ArrayMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; -case 146: { +case 144: { AST::FieldMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).sval); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 147: { +case 145: { sym(1).Node = 0; } break; -case 148: { +case 146: { sym(1).Node = sym(1).ArgumentList->finish(); } break; -case 149: { +case 147: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Expression); } break; -case 150: { +case 148: { AST::ArgumentList *node = makeAstNode (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 154: { +case 152: { AST::PostIncrementExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression); node->incrementToken = loc(2); sym(1).Node = node; } break; -case 155: { +case 153: { AST::PostDecrementExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression); node->decrementToken = loc(2); sym(1).Node = node; } break; -case 157: { +case 155: { AST::DeleteExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->deleteToken = loc(1); sym(1).Node = node; } break; -case 158: { +case 156: { AST::VoidExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->voidToken = loc(1); sym(1).Node = node; } break; -case 159: { +case 157: { AST::TypeOfExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->typeofToken = loc(1); sym(1).Node = node; } break; -case 160: { +case 158: { AST::PreIncrementExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->incrementToken = loc(1); sym(1).Node = node; } break; -case 161: { +case 159: { AST::PreDecrementExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->decrementToken = loc(1); sym(1).Node = node; } break; -case 162: { +case 160: { AST::UnaryPlusExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->plusToken = loc(1); sym(1).Node = node; } break; -case 163: { +case 161: { AST::UnaryMinusExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->minusToken = loc(1); sym(1).Node = node; } break; -case 164: { +case 162: { AST::TildeExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->tildeToken = loc(1); sym(1).Node = node; } break; -case 165: { +case 163: { AST::NotExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->notToken = loc(1); sym(1).Node = node; } break; -case 167: { +case 165: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Mul, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 168: { +case 166: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Div, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 169: { +case 167: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Mod, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 171: { +case 169: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Add, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 172: { +case 170: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Sub, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 174: { +case 172: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::LShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 175: { +case 173: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::RShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 176: { +case 174: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::URShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 178: { +case 176: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 179: { +case 177: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 180: { +case 178: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 181: { +case 179: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 182: { +case 180: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 183: { +case 181: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::In, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 185: { +case 183: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 186: { +case 184: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 187: { +case 185: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 188: { +case 186: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 189: { +case 187: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 191: { +case 189: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 192: { +case 190: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 193: { +case 191: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 194: { +case 192: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 196: { +case 194: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 197: { +case 195: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 198: { +case 196: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 199: { +case 197: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 201: { +case 199: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 203: { +case 201: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 205: { +case 203: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 207: { +case 205: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 209: { +case 207: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 211: { +case 209: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 213: { +case 211: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 215: { +case 213: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 217: { +case 215: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 219: { +case 217: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 221: { +case 219: { AST::ConditionalExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); @@ -1269,7 +1267,7 @@ case 221: { sym(1).Node = node; } break; -case 223: { +case 221: { AST::ConditionalExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); @@ -1277,112 +1275,112 @@ case 223: { sym(1).Node = node; } break; -case 225: { +case 223: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 227: { +case 225: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 228: { +case 226: { sym(1).ival = QSOperator::Assign; } break; -case 229: { +case 227: { sym(1).ival = QSOperator::InplaceMul; } break; -case 230: { +case 228: { sym(1).ival = QSOperator::InplaceDiv; } break; -case 231: { +case 229: { sym(1).ival = QSOperator::InplaceMod; } break; -case 232: { +case 230: { sym(1).ival = QSOperator::InplaceAdd; } break; -case 233: { +case 231: { sym(1).ival = QSOperator::InplaceSub; } break; -case 234: { +case 232: { sym(1).ival = QSOperator::InplaceLeftShift; } break; -case 235: { +case 233: { sym(1).ival = QSOperator::InplaceRightShift; } break; -case 236: { +case 234: { sym(1).ival = QSOperator::InplaceURightShift; } break; -case 237: { +case 235: { sym(1).ival = QSOperator::InplaceAnd; } break; -case 238: { +case 236: { sym(1).ival = QSOperator::InplaceXor; } break; -case 239: { +case 237: { sym(1).ival = QSOperator::InplaceOr; } break; -case 241: { +case 239: { AST::Expression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 242: { +case 240: { sym(1).Node = 0; } break; -case 245: { +case 243: { AST::Expression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 246: { +case 244: { sym(1).Node = 0; } break; -case 263: { +case 261: { AST::Block *node = makeAstNode (driver->nodePool(), sym(2).StatementList); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; -case 264: { +case 262: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Statement); } break; -case 265: { +case 263: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).StatementList, sym(2).Statement); } break; -case 266: { +case 264: { sym(1).Node = 0; } break; -case 267: { +case 265: { sym(1).Node = sym(1).StatementList->finish (); } break; -case 269: { +case 267: { AST::VariableStatement *node = makeAstNode (driver->nodePool(), sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); node->declarationKindToken = loc(1); @@ -1390,76 +1388,76 @@ case 269: { sym(1).Node = node; } break; -case 270: { +case 268: { sym(1).ival = T_CONST; } break; -case 271: { +case 269: { sym(1).ival = T_VAR; } break; -case 272: { +case 270: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclaration); } break; -case 273: { +case 271: { AST::VariableDeclarationList *node = makeAstNode (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); node->commaToken = loc(2); sym(1).Node = node; } break; -case 274: { +case 272: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclaration); } break; -case 275: { +case 273: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); } break; -case 276: { +case 274: { AST::VariableDeclaration *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 277: { +case 275: { AST::VariableDeclaration *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 278: { +case 276: { // ### TODO: AST for initializer sym(1) = sym(2); } break; -case 279: { +case 277: { sym(1).Node = 0; } break; -case 281: { +case 279: { // ### TODO: AST for initializer sym(1) = sym(2); } break; -case 282: { +case 280: { sym(1).Node = 0; } break; -case 284: { +case 282: { AST::EmptyStatement *node = makeAstNode (driver->nodePool()); node->semicolonToken = loc(1); sym(1).Node = node; } break; -case 286: { +case 284: { AST::ExpressionStatement *node = makeAstNode (driver->nodePool(), sym(1).Expression); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 287: { +case 285: { AST::IfStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); @@ -1468,7 +1466,7 @@ case 287: { sym(1).Node = node; } break; -case 288: { +case 286: { AST::IfStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); @@ -1476,7 +1474,7 @@ case 288: { sym(1).Node = node; } break; -case 290: { +case 288: { AST::DoWhileStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(5).Expression); node->doToken = loc(1); node->whileToken = loc(3); @@ -1486,7 +1484,7 @@ case 290: { sym(1).Node = node; } break; -case 291: { +case 289: { AST::WhileStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); node->whileToken = loc(1); node->lparenToken = loc(2); @@ -1494,7 +1492,7 @@ case 291: { sym(1).Node = node; } break; -case 292: { +case 290: { AST::ForStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Expression, sym(7).Expression, sym(9).Statement); node->forToken = loc(1); @@ -1505,7 +1503,7 @@ case 292: { sym(1).Node = node; } break; -case 293: { +case 291: { AST::LocalForStatement *node = makeAstNode (driver->nodePool(), sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, sym(8).Expression, sym(10).Statement); @@ -1518,7 +1516,7 @@ case 293: { sym(1).Node = node; } break; -case 294: { +case 292: { AST:: ForEachStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Expression, sym(7).Statement); node->forToken = loc(1); @@ -1528,7 +1526,7 @@ case 294: { sym(1).Node = node; } break; -case 295: { +case 293: { AST::LocalForEachStatement *node = makeAstNode (driver->nodePool(), sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); node->forToken = loc(1); @@ -1539,14 +1537,14 @@ case 295: { sym(1).Node = node; } break; -case 297: { +case 295: { AST::ContinueStatement *node = makeAstNode (driver->nodePool()); node->continueToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 299: { +case 297: { AST::ContinueStatement *node = makeAstNode (driver->nodePool(), sym(2).sval); node->continueToken = loc(1); node->identifierToken = loc(2); @@ -1554,14 +1552,14 @@ case 299: { sym(1).Node = node; } break; -case 301: { +case 299: { AST::BreakStatement *node = makeAstNode (driver->nodePool()); node->breakToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 303: { +case 301: { AST::BreakStatement *node = makeAstNode (driver->nodePool(), sym(2).sval); node->breakToken = loc(1); node->identifierToken = loc(2); @@ -1569,14 +1567,14 @@ case 303: { sym(1).Node = node; } break; -case 305: { +case 303: { AST::ReturnStatement *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->returnToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; -case 306: { +case 304: { AST::WithStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); node->withToken = loc(1); node->lparenToken = loc(2); @@ -1584,7 +1582,7 @@ case 306: { sym(1).Node = node; } break; -case 307: { +case 305: { AST::SwitchStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock); node->switchToken = loc(1); node->lparenToken = loc(2); @@ -1592,90 +1590,90 @@ case 307: { sym(1).Node = node; } break; -case 308: { +case 306: { AST::CaseBlock *node = makeAstNode (driver->nodePool(), sym(2).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; -case 309: { +case 307: { AST::CaseBlock *node = makeAstNode (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(5); sym(1).Node = node; } break; -case 310: { +case 308: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).CaseClause); } break; -case 311: { +case 309: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause); } break; -case 312: { +case 310: { sym(1).Node = 0; } break; -case 313: { +case 311: { sym(1).Node = sym(1).CaseClauses->finish (); } break; -case 314: { +case 312: { AST::CaseClause *node = makeAstNode (driver->nodePool(), sym(2).Expression, sym(4).StatementList); node->caseToken = loc(1); node->colonToken = loc(3); sym(1).Node = node; } break; -case 315: { +case 313: { AST::DefaultClause *node = makeAstNode (driver->nodePool(), sym(3).StatementList); node->defaultToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; -case 316: -case 317: { +case 314: +case 315: { AST::LabelledStatement *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; -case 318: { +case 316: { AST::LabelledStatement *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; -case 320: { +case 318: { AST::ThrowStatement *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->throwToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; -case 321: { +case 319: { AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Catch); node->tryToken = loc(1); sym(1).Node = node; } break; -case 322: { +case 320: { AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; -case 323: { +case 321: { AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; -case 324: { +case 322: { AST::Catch *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(5).Block); node->catchToken = loc(1); node->lparenToken = loc(2); @@ -1684,20 +1682,20 @@ case 324: { sym(1).Node = node; } break; -case 325: { +case 323: { AST::Finally *node = makeAstNode (driver->nodePool(), sym(2).Block); node->finallyToken = loc(1); sym(1).Node = node; } break; -case 327: { +case 325: { AST::DebuggerStatement *node = makeAstNode (driver->nodePool()); node->debuggerToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 328: { +case 326: { AST::FunctionDeclaration *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); node->identifierToken = loc(2); @@ -1708,7 +1706,7 @@ case 328: { sym(1).Node = node; } break; -case 329: { +case 327: { AST::FunctionExpression *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); if (sym(2).sval) @@ -1720,60 +1718,60 @@ case 329: { sym(1).Node = node; } break; -case 330: { +case 328: { AST::FormalParameterList *node = makeAstNode (driver->nodePool(), sym(1).sval); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 331: { +case 329: { AST::FormalParameterList *node = makeAstNode (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval); node->commaToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 332: { +case 330: { sym(1).Node = 0; } break; -case 333: { +case 331: { sym(1).Node = sym(1).FormalParameterList->finish (); } break; -case 334: { +case 332: { sym(1).Node = 0; } break; -case 336: { +case 334: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElements->finish ()); } break; -case 337: { +case 335: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElements->finish ()); } break; -case 338: { +case 336: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElement); } break; -case 339: { +case 337: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement); } break; -case 340: { +case 338: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Statement); } break; -case 341: { +case 339: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).FunctionDeclaration); } break; -case 342: { +case 340: { sym(1).sval = 0; } break; -case 344: { +case 342: { sym(1).Node = 0; } break; diff --git a/src/declarative/qml/parser/qdeclarativejsparser_p.h b/src/declarative/qml/parser/qdeclarativejsparser_p.h index 5eec1a4850..1661a2e8d7 100644 --- a/src/declarative/qml/parser/qdeclarativejsparser_p.h +++ b/src/declarative/qml/parser/qdeclarativejsparser_p.h @@ -235,9 +235,9 @@ protected: -#define J_SCRIPT_REGEXPLITERAL_RULE1 78 +#define J_SCRIPT_REGEXPLITERAL_RULE1 76 -#define J_SCRIPT_REGEXPLITERAL_RULE2 79 +#define J_SCRIPT_REGEXPLITERAL_RULE2 77 QT_QML_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescriptparser.cpp index e9be923053..c2cdbb0d98 100644 --- a/src/declarative/qml/qdeclarativescriptparser.cpp +++ b/src/declarative/qml/qdeclarativescriptparser.cpp @@ -127,6 +127,7 @@ protected: LocationSpan location, AST::UiObjectInitializer *initializer = 0); + QDeclarativeParser::Variant getVariant(AST::Statement *stmt); QDeclarativeParser::Variant getVariant(AST::ExpressionNode *expr); LocationSpan location(AST::SourceLocation start, AST::SourceLocation end); @@ -604,16 +605,16 @@ bool ProcessAST::visit(AST::UiPublicMember *node) property.location = location(node->firstSourceLocation(), node->lastSourceLocation()); - if (node->expression) { // default value + if (node->statement) { // default value property.defaultValue = new Property; property.defaultValue->parent = _stateStack.top().object; property.defaultValue->location = - location(node->expression->firstSourceLocation(), - node->expression->lastSourceLocation()); + location(node->statement->firstSourceLocation(), + node->statement->lastSourceLocation()); QDeclarativeParser::Value *value = new QDeclarativeParser::Value; - value->location = location(node->expression->firstSourceLocation(), - node->expression->lastSourceLocation()); - value->value = getVariant(node->expression); + value->location = location(node->statement->firstSourceLocation(), + node->statement->lastSourceLocation()); + value->value = getVariant(node->statement); property.defaultValue->values << value; } @@ -658,6 +659,18 @@ bool ProcessAST::visit(AST::UiObjectBinding *node) return false; } +QDeclarativeParser::Variant ProcessAST::getVariant(AST::Statement *stmt) +{ + if (stmt) { + if (AST::ExpressionStatement *exprStmt = AST::cast(stmt)) + return getVariant(exprStmt->expression); + + return QDeclarativeParser::Variant(asString(stmt), stmt); + } + + return QDeclarativeParser::Variant(); +} + QDeclarativeParser::Variant ProcessAST::getVariant(AST::ExpressionNode *expr) { if (AST::StringLiteral *lit = AST::cast(expr)) { -- cgit v1.2.3 From e1aecce5ef238ca7fb1676fe0583594bd21a62dc Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Thu, 12 May 2011 13:41:11 +0200 Subject: QmlDirParser: Fix typeInfo accessor. Reviewed-by: Kai Koehne (cherry picked from commit 7fcda24112d690575007ddcb11e097a9c33e0f19) --- src/declarative/qml/qdeclarativedirparser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativedirparser.cpp b/src/declarative/qml/qdeclarativedirparser.cpp index 97f7f4dda8..c35a63112f 100644 --- a/src/declarative/qml/qdeclarativedirparser.cpp +++ b/src/declarative/qml/qdeclarativedirparser.cpp @@ -240,7 +240,7 @@ QList QDeclarativeDirParser::components() cons } #ifdef QT_CREATOR -QList QDeclarativeDirParser::typeInfos() const +QList QDeclarativeDirParser::typeInfos() const { return _typeInfos; } -- cgit v1.2.3 From 30327650798ba63281c7b9344c9d824d00dce82a Mon Sep 17 00:00:00 2001 From: Charles Yin Date: Tue, 15 Mar 2011 12:10:01 +1000 Subject: cache the arguments in property cache data Change-Id: Ie02b94c2ddb1d5d7b7bb6556a01a5ae86a438c57 (cherry picked from commit 39fed3e2601935c1d6834bb5e75266e5b280e5cd) --- src/declarative/qml/qdeclarativepropertycache.cpp | 31 ++++++++++++++++++++++- src/declarative/qml/qdeclarativepropertycache_p.h | 5 ++-- 2 files changed, 33 insertions(+), 3 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp index 9cbb4fa8cc..f39cdd9e6c 100644 --- a/src/declarative/qml/qdeclarativepropertycache.cpp +++ b/src/declarative/qml/qdeclarativepropertycache.cpp @@ -93,6 +93,26 @@ void QDeclarativePropertyCache::Data::load(const QMetaProperty &p, QDeclarativeE revision = p.revision(); } +int QDeclarativePropertyCache::Data::enumType(const QMetaObject *meta, const QString &strname) +{ + QByteArray str = strname.toUtf8(); + QByteArray scope; + QByteArray name; + int scopeIdx = str.lastIndexOf("::"); + if (scopeIdx != -1) { + scope = str.left(scopeIdx); + name = str.mid(scopeIdx + 2); + } else { + name = str; + } + for (int i = meta->enumeratorCount() - 1; i >= 0; --i) { + QMetaEnum m = meta->enumerator(i); + if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) + return QVariant::Int; + } + return QVariant::Invalid; +} + void QDeclarativePropertyCache::Data::load(const QMetaMethod &m) { coreIndex = m.methodIndex(); @@ -107,8 +127,17 @@ void QDeclarativePropertyCache::Data::load(const QMetaMethod &m) propType = QMetaType::type(returnType); QList params = m.parameterTypes(); - if (!params.isEmpty()) + if (!params.isEmpty()) { flags |= Data::HasArguments; + paramTypes.resize(params.size()); + for (int i = 0; i < params.size(); ++i) { + paramTypes[i] = QMetaType::type(params.at(i)); + if (paramTypes[i] == QVariant::Invalid) + paramTypes[i] = enumType(m.enclosingMetaObject(), QString::fromLatin1(params.at(i))); + if (paramTypes[i] == QVariant::Invalid) + paramTypes[i] = -1; //Unknown method parameter type + } + } revision = m.revision(); } diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h index 65a8725b8f..86ccfe0187 100644 --- a/src/declarative/qml/qdeclarativepropertycache_p.h +++ b/src/declarative/qml/qdeclarativepropertycache_p.h @@ -64,7 +64,6 @@ QT_BEGIN_NAMESPACE class QDeclarativeEngine; class QMetaProperty; - class Q_AUTOTEST_EXPORT QDeclarativePropertyCache : public QDeclarativeRefCount, public QDeclarativeCleanup { public: @@ -74,6 +73,7 @@ public: struct Data { inline Data(); + inline bool operator==(const Data &); enum Flag { @@ -115,8 +115,9 @@ public: int overrideIndex : 31; int revision; int metaObjectOffset; - + QVector paramTypes; static Flags flagsForProperty(const QMetaProperty &, QDeclarativeEngine *engine = 0); + int enumType(const QMetaObject *meta, const QString &strname); void load(const QMetaProperty &, QDeclarativeEngine *engine = 0); void load(const QMetaMethod &); QString name(QObject *); -- cgit v1.2.3 From 68d18d77ebac49c2b863c425969c70c5426864cd Mon Sep 17 00:00:00 2001 From: Charles Yin Date: Tue, 15 Mar 2011 12:11:00 +1000 Subject: uses the cached argument info Change-Id: I884516c9c20425bfd17a2db7d5541fbc5cff41c6 (cherry picked from commit b4613a346effee81f10bee99a6a8d3064cbdd13e) --- .../qml/qdeclarativeobjectscriptclass.cpp | 25 +++++----------------- .../qml/qdeclarativeobjectscriptclass_p.h | 2 +- 2 files changed, 6 insertions(+), 21 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index edc1755a72..f4ca9fe758 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -672,7 +672,7 @@ struct MetaCallArgument { inline void *dataPtr(); inline void initAsType(int type, QDeclarativeEngine *); - void fromScriptValue(int type, QDeclarativeEngine *, const QScriptValue &); + inline void fromScriptValue(int type, QDeclarativeEngine *, const QScriptValue &); inline QScriptDeclarativeClass::Value toValue(QDeclarativeEngine *); private: @@ -908,24 +908,9 @@ QDeclarativeObjectMethodScriptClass::callPrecise(QObject *object, const QDeclara QScriptContext *ctxt) { if (data.flags & QDeclarativePropertyCache::Data::HasArguments) { - - QMetaMethod m = object->metaObject()->method(data.coreIndex); - QList argTypeNames = m.parameterTypes(); - QVarLengthArray argTypes(argTypeNames.count()); - - // ### Cache - for (int ii = 0; ii < argTypeNames.count(); ++ii) { - argTypes[ii] = QMetaType::type(argTypeNames.at(ii)); - if (argTypes[ii] == QVariant::Invalid) - argTypes[ii] = enumType(object->metaObject(), QString::fromLatin1(argTypeNames.at(ii))); - if (argTypes[ii] == QVariant::Invalid) - return Value(ctxt, ctxt->throwError(QString::fromLatin1("Unknown method parameter type: %1").arg(QLatin1String(argTypeNames.at(ii))))); - } - - if (argTypes.count() > ctxt->argumentCount()) - return Value(ctxt, ctxt->throwError(QLatin1String("Insufficient arguments"))); - - return callMethod(object, data.coreIndex, data.propType, argTypes.count(), argTypes.data(), ctxt); + if (data.paramTypes.size() > ctxt->argumentCount()) + return Value(ctxt, ctxt->throwError(QLatin1String("Insufficient arguments"))); + return callMethod(object, data.coreIndex, data.propType, data.paramTypes.size(), data.paramTypes.data(), ctxt); } else { @@ -936,7 +921,7 @@ QDeclarativeObjectMethodScriptClass::callPrecise(QObject *object, const QDeclara QDeclarativeObjectMethodScriptClass::Value QDeclarativeObjectMethodScriptClass::callMethod(QObject *object, int index, - int returnType, int argCount, int *argTypes, + int returnType, int argCount, const int *argTypes, QScriptContext *ctxt) { if (argCount > 0) { diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h b/src/declarative/qml/qdeclarativeobjectscriptclass_p.h index 850a94f364..24fcbda106 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h +++ b/src/declarative/qml/qdeclarativeobjectscriptclass_p.h @@ -85,7 +85,7 @@ private: Value callPrecise(QObject *, const QDeclarativePropertyCache::Data &, QScriptContext *); Value callOverloaded(MethodData *, QScriptContext *); - Value callMethod(QObject *, int index, int returnType, int argCount, int *argTypes, QScriptContext *ctxt); + Value callMethod(QObject *, int index, int returnType, int argCount, const int *argTypes, QScriptContext *ctxt); int matchScore(const QScriptValue &, int, const QByteArray &); QDeclarativePropertyCache::Data *relatedMethod(QObject *, QDeclarativePropertyCache::Data *current, -- cgit v1.2.3 From 220b2384a5022a786b96cbd8a0fac7c4af5c76fe Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 16 May 2011 11:08:38 +1000 Subject: Doc Change-Id: I25f1885ef285fb3bd14c1f499b9f42e38bba5ec6 Task-number: QTBUG-19265 (cherry picked from commit 01a374fe8a6ac0b6e374081c07720e77c61effff) --- src/declarative/qml/qdeclarativeproperty.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index 7f74da4ee6..1cd33634d7 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -183,6 +183,9 @@ QDeclarativeProperty::QDeclarativeProperty(QObject *obj, const QString &name) /*! Creates a QDeclarativeProperty for the property \a name of \a obj using the \l{QDeclarativeContext} {context} \a ctxt. + + Creating a QDeclarativeProperty without a context will render some + properties - like attached properties - inaccessible. */ QDeclarativeProperty::QDeclarativeProperty(QObject *obj, const QString &name, QDeclarativeContext *ctxt) : d(new QDeclarativePropertyPrivate) -- cgit v1.2.3 From 616c7e768f3d88f6b8be6af72290769e99500e72 Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Wed, 18 May 2011 12:32:28 +1000 Subject: Revert "Support mirroring the source rectangle of ShaderEffectSource." This reverts commit 155faa3b8b1e04241bd53df3eb008d54a71cc667. The original commit broke behavior enforced by the tst_qdeclarativeqt unit test, specifically relating to QRectF. --- src/declarative/qml/qdeclarativeengine.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index eb2974f46a..001884161b 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -1740,6 +1740,9 @@ QScriptValue QDeclarativeEnginePrivate::rect(QScriptContext *ctxt, QScriptEngine qsreal w = ctxt->argument(2).toNumber(); qsreal h = ctxt->argument(3).toNumber(); + if (w < 0 || h < 0) + return engine->nullValue(); + return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QRectF(x, y, w, h))); } -- cgit v1.2.3 From fcdd4d4dd565c4ec8b22d9ee5aa0ad2428a4336b Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Thu, 19 May 2011 18:02:21 +1000 Subject: Normalize createQmlObject error message --- src/declarative/qml/qdeclarativeengine.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 001884161b..86b7e9412f 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -1398,7 +1398,7 @@ QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QS QScriptValue arr = ctxt->engine()->newArray(errors.length()); int i = 0; foreach (const QDeclarativeError &error, errors){ - errstr += QLatin1String(" ") + error.toString() + QLatin1String("\n"); + errstr += QLatin1String("\n ") + error.toString(); QScriptValue qmlErrObject = ctxt->engine()->newObject(); qmlErrObject.setProperty(QLatin1String("lineNumber"), QScriptValue(error.line())); qmlErrObject.setProperty(QLatin1String("columnNumber"), QScriptValue(error.column())); @@ -1425,7 +1425,7 @@ QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QS QScriptValue arr = ctxt->engine()->newArray(errors.length()); int i = 0; foreach (const QDeclarativeError &error, errors){ - errstr += QLatin1String(" ") + error.toString() + QLatin1String("\n"); + errstr += QLatin1String("\n ") + error.toString(); QScriptValue qmlErrObject = ctxt->engine()->newObject(); qmlErrObject.setProperty(QLatin1String("lineNumber"), QScriptValue(error.line())); qmlErrObject.setProperty(QLatin1String("columnNumber"), QScriptValue(error.column())); -- cgit v1.2.3 From 9d7eb51da37e8dffbe284fc564c9b9f08a89bea2 Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Thu, 19 May 2011 10:26:55 +0200 Subject: Re-apply "Support mirroring the source rectangle of ShaderEffectSource." This reverts commit 616c7e768f3d88f6b8be6af72290769e99500e72. --- src/declarative/qml/qdeclarativeengine.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 001884161b..eb2974f46a 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -1740,9 +1740,6 @@ QScriptValue QDeclarativeEnginePrivate::rect(QScriptContext *ctxt, QScriptEngine qsreal w = ctxt->argument(2).toNumber(); qsreal h = ctxt->argument(3).toNumber(); - if (w < 0 || h < 0) - return engine->nullValue(); - return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QRectF(x, y, w, h))); } -- cgit v1.2.3 From 9bf28fbf0ee26dfde7d6060b10186cfccdcfcd67 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 20 May 2011 11:37:06 +1000 Subject: Some of the QML C++ methods should be slots. Change-Id: Ib9465cf2a7638d013ce831f49ed0177741c22ab0 --- src/declarative/qml/qdeclarativecomponent.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativecomponent.h b/src/declarative/qml/qdeclarativecomponent.h index 72e77dab85..6c05881f52 100644 --- a/src/declarative/qml/qdeclarativecomponent.h +++ b/src/declarative/qml/qdeclarativecomponent.h @@ -96,13 +96,14 @@ public: virtual QObject *beginCreate(QDeclarativeContext *); virtual void completeCreate(); - void loadUrl(const QUrl &url); - void setData(const QByteArray &, const QUrl &baseUrl); - QDeclarativeContext *creationContext() const; static QDeclarativeComponentAttached *qmlAttachedProperties(QObject *); +public Q_SLOTS: + void loadUrl(const QUrl &url); + void setData(const QByteArray &, const QUrl &baseUrl); + Q_SIGNALS: void statusChanged(QDeclarativeComponent::Status); void progressChanged(qreal); -- cgit v1.2.3 From 9605fc786482bdd208cc3bfe92f318f7c314329c Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Mon, 23 May 2011 15:22:37 +1000 Subject: Support change slots for properties starting with '_' According to ECMA-262r3, property names may begin with a letter, underscore ('_'), dollar sign ('$'), or unicode escape sequence. We previously supported Change slots for properties only if the property name began with a letter; this patch adds support for properties which begin with one or more underscore. Task-number: QTBUG-17950 Reviewed-by: Aaron Kennedy Change-Id: I6f28bde18a38e32c2131e0990fe0f69bda36f90e --- src/declarative/qml/qdeclarativecompiler.cpp | 32 ++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 31a9f668ef..3a686be9ec 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -122,13 +122,26 @@ bool QDeclarativeCompiler::isAttachedPropertyName(const QByteArray &name) /*! Returns true if \a name refers to a signal property, false otherwise. - Signal property names are those that start with "on", followed by a capital - letter. + 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 QDeclarativeCompiler::isSignalPropertyName(const QByteArray &name) { - return name.length() >= 3 && name.startsWith("on") && - 'A' <= name.at(2) && 'Z' >= name.at(2); + if (name.length() < 3) return false; + if (!name.startsWith("on")) return false; + int ns = name.size(); + for (int i = 2; i < ns; ++i) { + char curr = name.at(i); + if (curr == '_') continue; + if (curr >= 'A' && curr <= 'Z') return true; + return false; + } + return false; // consists solely of underscores - invalid. } /*! @@ -1340,8 +1353,15 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl QByteArray name = prop->name; Q_ASSERT(name.startsWith("on")); name = name.mid(2); - if(name[0] >= 'A' && name[0] <= 'Z') - name[0] = name[0] - 'A' + 'a'; + + // 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[firstAlphaIndex] >= 'A' && name[firstAlphaIndex] <= 'Z') { + name[firstAlphaIndex] = name[firstAlphaIndex] - 'A' + 'a'; + break; + } + } bool notInRevision = false; int sigIdx = indexOfSignal(obj, name, ¬InRevision); -- cgit v1.2.3 From c741910ef6857e355c0715b872902df87fd4443f Mon Sep 17 00:00:00 2001 From: Charles Yin Date: Wed, 25 May 2011 13:45:18 +1000 Subject: Revert "cache the arguments in property cache data" This reverts commit 30327650798ba63281c7b9344c9d824d00dce82a. --- src/declarative/qml/qdeclarativepropertycache.cpp | 31 +---------------------- src/declarative/qml/qdeclarativepropertycache_p.h | 5 ++-- 2 files changed, 3 insertions(+), 33 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp index f39cdd9e6c..9cbb4fa8cc 100644 --- a/src/declarative/qml/qdeclarativepropertycache.cpp +++ b/src/declarative/qml/qdeclarativepropertycache.cpp @@ -93,26 +93,6 @@ void QDeclarativePropertyCache::Data::load(const QMetaProperty &p, QDeclarativeE revision = p.revision(); } -int QDeclarativePropertyCache::Data::enumType(const QMetaObject *meta, const QString &strname) -{ - QByteArray str = strname.toUtf8(); - QByteArray scope; - QByteArray name; - int scopeIdx = str.lastIndexOf("::"); - if (scopeIdx != -1) { - scope = str.left(scopeIdx); - name = str.mid(scopeIdx + 2); - } else { - name = str; - } - for (int i = meta->enumeratorCount() - 1; i >= 0; --i) { - QMetaEnum m = meta->enumerator(i); - if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) - return QVariant::Int; - } - return QVariant::Invalid; -} - void QDeclarativePropertyCache::Data::load(const QMetaMethod &m) { coreIndex = m.methodIndex(); @@ -127,17 +107,8 @@ void QDeclarativePropertyCache::Data::load(const QMetaMethod &m) propType = QMetaType::type(returnType); QList params = m.parameterTypes(); - if (!params.isEmpty()) { + if (!params.isEmpty()) flags |= Data::HasArguments; - paramTypes.resize(params.size()); - for (int i = 0; i < params.size(); ++i) { - paramTypes[i] = QMetaType::type(params.at(i)); - if (paramTypes[i] == QVariant::Invalid) - paramTypes[i] = enumType(m.enclosingMetaObject(), QString::fromLatin1(params.at(i))); - if (paramTypes[i] == QVariant::Invalid) - paramTypes[i] = -1; //Unknown method parameter type - } - } revision = m.revision(); } diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h index 86ccfe0187..65a8725b8f 100644 --- a/src/declarative/qml/qdeclarativepropertycache_p.h +++ b/src/declarative/qml/qdeclarativepropertycache_p.h @@ -64,6 +64,7 @@ QT_BEGIN_NAMESPACE class QDeclarativeEngine; class QMetaProperty; + class Q_AUTOTEST_EXPORT QDeclarativePropertyCache : public QDeclarativeRefCount, public QDeclarativeCleanup { public: @@ -73,7 +74,6 @@ public: struct Data { inline Data(); - inline bool operator==(const Data &); enum Flag { @@ -115,9 +115,8 @@ public: int overrideIndex : 31; int revision; int metaObjectOffset; - QVector paramTypes; + static Flags flagsForProperty(const QMetaProperty &, QDeclarativeEngine *engine = 0); - int enumType(const QMetaObject *meta, const QString &strname); void load(const QMetaProperty &, QDeclarativeEngine *engine = 0); void load(const QMetaMethod &); QString name(QObject *); -- cgit v1.2.3 From d5f12d1348fa882577d24b47958b03ab9d037b8a Mon Sep 17 00:00:00 2001 From: Charles Yin Date: Wed, 25 May 2011 13:45:25 +1000 Subject: Revert "uses the cached argument info" This reverts commit 68d18d77ebac49c2b863c425969c70c5426864cd. --- .../qml/qdeclarativeobjectscriptclass.cpp | 25 +++++++++++++++++----- .../qml/qdeclarativeobjectscriptclass_p.h | 2 +- 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index f4ca9fe758..edc1755a72 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -672,7 +672,7 @@ struct MetaCallArgument { inline void *dataPtr(); inline void initAsType(int type, QDeclarativeEngine *); - inline void fromScriptValue(int type, QDeclarativeEngine *, const QScriptValue &); + void fromScriptValue(int type, QDeclarativeEngine *, const QScriptValue &); inline QScriptDeclarativeClass::Value toValue(QDeclarativeEngine *); private: @@ -908,9 +908,24 @@ QDeclarativeObjectMethodScriptClass::callPrecise(QObject *object, const QDeclara QScriptContext *ctxt) { if (data.flags & QDeclarativePropertyCache::Data::HasArguments) { - if (data.paramTypes.size() > ctxt->argumentCount()) - return Value(ctxt, ctxt->throwError(QLatin1String("Insufficient arguments"))); - return callMethod(object, data.coreIndex, data.propType, data.paramTypes.size(), data.paramTypes.data(), ctxt); + + QMetaMethod m = object->metaObject()->method(data.coreIndex); + QList argTypeNames = m.parameterTypes(); + QVarLengthArray argTypes(argTypeNames.count()); + + // ### Cache + for (int ii = 0; ii < argTypeNames.count(); ++ii) { + argTypes[ii] = QMetaType::type(argTypeNames.at(ii)); + if (argTypes[ii] == QVariant::Invalid) + argTypes[ii] = enumType(object->metaObject(), QString::fromLatin1(argTypeNames.at(ii))); + if (argTypes[ii] == QVariant::Invalid) + return Value(ctxt, ctxt->throwError(QString::fromLatin1("Unknown method parameter type: %1").arg(QLatin1String(argTypeNames.at(ii))))); + } + + if (argTypes.count() > ctxt->argumentCount()) + return Value(ctxt, ctxt->throwError(QLatin1String("Insufficient arguments"))); + + return callMethod(object, data.coreIndex, data.propType, argTypes.count(), argTypes.data(), ctxt); } else { @@ -921,7 +936,7 @@ QDeclarativeObjectMethodScriptClass::callPrecise(QObject *object, const QDeclara QDeclarativeObjectMethodScriptClass::Value QDeclarativeObjectMethodScriptClass::callMethod(QObject *object, int index, - int returnType, int argCount, const int *argTypes, + int returnType, int argCount, int *argTypes, QScriptContext *ctxt) { if (argCount > 0) { diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h b/src/declarative/qml/qdeclarativeobjectscriptclass_p.h index 24fcbda106..850a94f364 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h +++ b/src/declarative/qml/qdeclarativeobjectscriptclass_p.h @@ -85,7 +85,7 @@ private: Value callPrecise(QObject *, const QDeclarativePropertyCache::Data &, QScriptContext *); Value callOverloaded(MethodData *, QScriptContext *); - Value callMethod(QObject *, int index, int returnType, int argCount, const int *argTypes, QScriptContext *ctxt); + Value callMethod(QObject *, int index, int returnType, int argCount, int *argTypes, QScriptContext *ctxt); int matchScore(const QScriptValue &, int, const QByteArray &); QDeclarativePropertyCache::Data *relatedMethod(QObject *, QDeclarativePropertyCache::Data *current, -- cgit v1.2.3 From d58472c1b1727b5695c692ab8e99545b5b6c1158 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 5 May 2011 13:24:32 +1000 Subject: Uninitialized memory is compared. Memory is allocated and used without first clearing it. At the least this annoys valgrind, but also has potential for real problems. Change-Id: Icf3fd39f44ee0481dd732510e7f8b3ad6cef477d Task-number: QTBUG-15187 Reviewed-by: Aaron Kennedy (cherry picked from commit 95aa4e4f9b82c3652ffc93310b190db869d491df) --- src/declarative/qml/qdeclarativeproperty.cpp | 2 ++ src/declarative/qml/qmetaobjectbuilder.cpp | 2 ++ 2 files changed, 4 insertions(+) (limited to 'src/declarative/qml') diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index 1cd33634d7..b91b820e0f 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -1454,6 +1454,7 @@ QByteArray QDeclarativePropertyPrivate::saveValueType(const QMetaObject *metaObj QMetaProperty subProp = subObject->property(subIndex); ValueTypeSerializedData sd; + memset(&sd, 0, sizeof(sd)); sd.isValueType = true; sd.core.load(metaObject->property(index)); sd.valueType.flags = QDeclarativePropertyCache::Data::flagsForProperty(subProp); @@ -1468,6 +1469,7 @@ QByteArray QDeclarativePropertyPrivate::saveValueType(const QMetaObject *metaObj QByteArray QDeclarativePropertyPrivate::saveProperty(const QMetaObject *metaObject, int index) { SerializedData sd; + memset(&sd, 0, sizeof(sd)); sd.isValueType = false; sd.core.load(metaObject->property(index)); diff --git a/src/declarative/qml/qmetaobjectbuilder.cpp b/src/declarative/qml/qmetaobjectbuilder.cpp index a63656bc28..d8a7b77f11 100644 --- a/src/declarative/qml/qmetaobjectbuilder.cpp +++ b/src/declarative/qml/qmetaobjectbuilder.cpp @@ -1452,6 +1452,7 @@ QMetaObject *QMetaObjectBuilder::toMetaObject() const { int size = buildMetaObject(d, 0, false); char *buf = reinterpret_cast(qMalloc(size)); + memset(buf, 0, size); buildMetaObject(d, buf, false); return reinterpret_cast(buf); } @@ -1481,6 +1482,7 @@ QByteArray QMetaObjectBuilder::toRelocatableData(bool *ok) const QByteArray data; data.resize(size); char *buf = data.data(); + memset(buf, 0, size); buildMetaObject(d, buf, true); if (ok) *ok = true; return data; -- cgit v1.2.3