From 809ee66b67ce70dba89a04b92daccc9445af2e75 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 6 Jul 2011 13:43:47 +1000 Subject: [PATCH] More efficient type name cache Instead of creating completely separate hashes for all the types used by every QML file, we simply link to the QDeclarativeTypeModule. This uses much less memory, and is faster to construct at startup. Change-Id: I28bc2807074f9c6f38096d6e4ce8be744159d023 Reviewed-on: http://codereview.qt.nokia.com/3741 Reviewed-by: Roberto Raggi --- src/declarative/qml/qdeclarativeimport.cpp | 86 ++---- src/declarative/qml/qdeclarativemetatype.cpp | 317 ++++++++++++++++++--- src/declarative/qml/qdeclarativemetatype_p.h | 52 +++- src/declarative/qml/qdeclarativeproperty.cpp | 96 ++++--- src/declarative/qml/qdeclarativetypenamecache.cpp | 97 +++++-- src/declarative/qml/qdeclarativetypenamecache_p.h | 93 +++--- src/declarative/qml/v4/qdeclarativev4irbuilder.cpp | 91 +++--- src/declarative/qml/v8/qv8contextwrapper.cpp | 18 +- src/declarative/qml/v8/qv8qobjectwrapper.cpp | 22 +- src/declarative/qml/v8/qv8typewrapper.cpp | 42 ++- src/declarative/qml/v8/qv8typewrapper_p.h | 3 +- tools/qmlscene/main.cpp | 11 +- 12 files changed, 634 insertions(+), 294 deletions(-) diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp index b2fa071..a28428c 100644 --- a/src/declarative/qml/qdeclarativeimport.cpp +++ b/src/declarative/qml/qdeclarativeimport.cpp @@ -161,22 +161,32 @@ QUrl QDeclarativeImports::baseUrl() const return d->base; } -static QDeclarativeTypeNameCache * -cacheForNamespace(QDeclarativeEngine *engine, const QDeclarativeImportedNamespace &set, - QDeclarativeTypeNameCache *cache, bool importWasQualified) +void QDeclarativeImports::populateCache(QDeclarativeTypeNameCache *cache, QDeclarativeEngine *engine) const { - if (!cache) - cache = new QDeclarativeTypeNameCache(engine); - - QList types = QDeclarativeMetaType::qmlTypes(); + const QDeclarativeImportedNamespace &set = d->unqualifiedset; - for (int ii = 0; ii < set.uris.count(); ++ii) { - QByteArray uri = set.uris.at(ii).toUtf8(); - int major = set.majversions.at(ii); - int minor = set.minversions.at(ii); + for (int ii = set.uris.count() - 1; ii >= 0; --ii) { + const QByteArray uri = set.uris.at(ii).toUtf8(); // XXX sigh + int majversion = set.majversions.at(ii); + int minversion = set.minversions.at(ii); + QDeclarativeTypeModule *module = QDeclarativeMetaType::typeModule(uri, majversion); + if (module) cache->m_anonymousImports.append(QDeclarativeTypeModuleVersion(module, minversion)); + } - if (importWasQualified) { - QDeclarativeMetaType::ModuleApi moduleApi = QDeclarativeMetaType::moduleApi(uri, major, minor); + for (QHash::ConstIterator iter = d->set.begin(); + iter != d->set.end(); + ++iter) { + + const QDeclarativeImportedNamespace &set = *iter.value(); + QDeclarativeTypeNameCache::Import &import = cache->m_namedImports[iter.key()]; + for (int ii = set.uris.count() - 1; ii >= 0; --ii) { + const QByteArray uri = set.uris.at(ii).toUtf8(); // XXX sigh + int majversion = set.majversions.at(ii); + int minversion = set.minversions.at(ii); + QDeclarativeTypeModule *module = QDeclarativeMetaType::typeModule(uri, majversion); + if (module) import.modules.append(QDeclarativeTypeModuleVersion(module, minversion)); + + QDeclarativeMetaType::ModuleApi moduleApi = QDeclarativeMetaType::moduleApi(uri, majversion, minversion); if (moduleApi.script || moduleApi.qobject) { QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); QDeclarativeMetaType::ModuleApiInstance *a = ep->moduleApiInstances.value(moduleApi); @@ -186,46 +196,12 @@ cacheForNamespace(QDeclarativeEngine *engine, const QDeclarativeImportedNamespac 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) && - (major < 0 || type->availableInVersion(major,minor))) - { - QString name = QString::fromUtf8(type->qmlTypeName().mid(base.length())); - - cache->add(name, type); + import.moduleApi = a; } } } - return cache; -} - -void QDeclarativeImports::populateCache(QDeclarativeTypeNameCache *cache, QDeclarativeEngine *engine) const -{ - const QDeclarativeImportedNamespace &set = d->unqualifiedset; - - for (QHash::ConstIterator iter = d->set.begin(); - iter != d->set.end(); ++iter) { - - QDeclarativeTypeNameCache::Data *d = cache->data(iter.key()); - if (d) { - if (!d->typeNamespace) - cacheForNamespace(engine, *(*iter), d->typeNamespace, true); - } else { - QDeclarativeTypeNameCache *nc = cacheForNamespace(engine, *(*iter), 0, true); - cache->add(iter.key(), nc); - nc->release(); - } - } - cacheForNamespace(engine, set, cache, false); } /*! @@ -513,10 +489,10 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp bool found = false; QString dir; - // step 1: search for extension with fully encoded version number - foreach (const QString &p, database->fileImportPath) { - dir = p+QLatin1Char('/')+url; + if (!found) { + foreach (const QString &p, database->fileImportPath) { + dir = p+QLatin1Char('/')+url; QFileInfo fi(dir+QString(QLatin1String(".%1.%2")).arg(vmaj).arg(vmin)+QLatin1String("/qmldir")); const QString absoluteFilePath = fi.absoluteFilePath(); @@ -533,8 +509,9 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp } // step 2: search for extension with encoded version major - foreach (const QString &p, database->fileImportPath) { - dir = p+QLatin1Char('/')+url; + if (!found) { + foreach (const QString &p, database->fileImportPath) { + dir = p+QLatin1Char('/')+url; QFileInfo fi(dir+QString(QLatin1String(".%1")).arg(vmaj)+QLatin1String("/qmldir")); const QString absoluteFilePath = fi.absoluteFilePath(); @@ -577,9 +554,8 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp if (!versionFound && qmldircomponents.isEmpty()) { if (errors) { - bool anyversion = QDeclarativeMetaType::isAnyModule(uri.toUtf8()); QDeclarativeError error; // we don't set the url or line or column as these will be set by the loader. - if (anyversion) + if (QDeclarativeMetaType::isAnyModule(uri.toUtf8())) error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin)); else error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" is not installed").arg(uri_arg)); diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp index 41705bc..da7be11 100644 --- a/src/declarative/qml/qdeclarativemetatype.cpp +++ b/src/declarative/qml/qdeclarativemetatype.cpp @@ -42,9 +42,10 @@ #include #include "private/qdeclarativemetatype_p.h" -#include "private/qdeclarativeproxymetaobject_p.h" -#include "private/qdeclarativecustomparser_p.h" -#include "private/qdeclarativeguard_p.h" +#include +#include +#include +#include #include #include @@ -99,6 +100,21 @@ struct QDeclarativeMetaTypeData MetaObjects metaObjectToType; typedef QHash StringConverters; StringConverters stringConverters; + + struct VersionedUri { + VersionedUri() + : majorVersion(0) {} + VersionedUri(const QByteArray &uri, int majorVersion) + : uri(uri), majorVersion(majorVersion) {} + bool operator==(const VersionedUri &other) const { + return other.majorVersion == majorVersion && other.uri == uri; + } + QByteArray uri; + int majorVersion; + }; + typedef QHash TypeModules; + TypeModules uriToModule; + struct ModuleApiList { ModuleApiList() : sorted(true) {} QList moduleApis; @@ -108,26 +124,38 @@ struct QDeclarativeMetaTypeData ModuleApis moduleApis; int moduleApiCount; - struct ModuleInfo { - ModuleInfo(int major, int minor) - : vmajor(major), vminor_min(minor), vminor_max(minor) {} - ModuleInfo(int major, int minor_min, int minor_max) - : vmajor(major), vminor_min(minor_min), vminor_max(minor_max) {} - int vmajor; - int vminor_min, vminor_max; - }; - typedef QHash, ModuleInfo> ModuleInfoHash; - ModuleInfoHash modules; - QBitArray objects; QBitArray interfaces; QBitArray lists; QList parentFunctions; }; + +class QDeclarativeTypeModulePrivate +{ +public: + QDeclarativeTypeModulePrivate() + : minMinorVersion(INT_MAX), maxMinorVersion(0) {} + + QDeclarativeMetaTypeData::VersionedUri uri; + + int minMinorVersion; + int maxMinorVersion; + + void add(QDeclarativeType *); + + QStringHash > typeHash; + QList types; +}; + Q_GLOBAL_STATIC(QDeclarativeMetaTypeData, metaTypeData) Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock) +static uint qHash(const QDeclarativeMetaTypeData::VersionedUri &v) +{ + return qHash(v.uri) ^ qHash(v.majorVersion); +} + QDeclarativeMetaTypeData::QDeclarativeMetaTypeData() : moduleApiCount(0) { @@ -145,11 +173,13 @@ public: QDeclarativeTypePrivate(); void init() const; + void initEnums() const; bool m_isInterface : 1; const char *m_iid; QByteArray m_module; QByteArray m_name; + QString m_elementName; int m_version_maj; int m_version_min; int m_typeId; int m_listId; @@ -173,8 +203,10 @@ public: int m_index; QDeclarativeCustomParser *m_customParser; mutable volatile bool m_isSetup:1; - mutable bool m_haveSuperType : 1; + mutable volatile bool m_isEnumSetup:1; + mutable bool m_haveSuperType:1; mutable QList m_metaObjects; + mutable QStringHash m_enums; static QHash m_attachedPropertyIds; }; @@ -186,7 +218,7 @@ QDeclarativeTypePrivate::QDeclarativeTypePrivate() m_superType(0), m_allocationSize(0), m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0), m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_propertyValueInterceptorCast(-1), m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), - m_isSetup(false), m_haveSuperType(false) + m_isSetup(false), m_isEnumSetup(false), m_haveSuperType(false) { } @@ -268,11 +300,13 @@ int QDeclarativeType::minorVersion() const bool QDeclarativeType::availableInVersion(int vmajor, int vminor) const { + Q_ASSERT(vmajor >= 0 && vminor >= 0); return vmajor == d->m_version_maj && vminor >= d->m_version_min; } bool QDeclarativeType::availableInVersion(const QByteArray &module, int vmajor, int vminor) const { + Q_ASSERT(vmajor >= 0 && vminor >= 0); return module == d->m_module && vmajor == d->m_version_maj && vminor >= d->m_version_min; } @@ -431,6 +465,27 @@ void QDeclarativeTypePrivate::init() const lock.unlock(); } +void QDeclarativeTypePrivate::initEnums() const +{ + if (m_isEnumSetup) return; + + init(); + + QWriteLocker lock(metaTypeDataLock()); + if (m_isEnumSetup) return; + + const QMetaObject *metaObject = m_baseMetaObject; + for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) { + + QMetaEnum e = metaObject->enumerator(ii); + + for (int jj = 0; jj < e.keyCount(); ++jj) + m_enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj)); + } + + m_isEnumSetup = true; +} + QByteArray QDeclarativeType::typeName() const { if (d->m_baseMetaObject) @@ -439,6 +494,16 @@ QByteArray QDeclarativeType::typeName() const return QByteArray(); } +const QString &QDeclarativeType::elementName() const +{ + if (d->m_elementName.isEmpty()) { + QByteArray n = qmlTypeName(); + int idx = n.lastIndexOf('/'); + d->m_elementName = QString::fromUtf8(n.mid(idx + 1)); + } + return d->m_elementName; +} + QByteArray QDeclarativeType::qmlTypeName() const { return d->m_name; @@ -591,6 +656,164 @@ int QDeclarativeType::index() const return d->m_index; } +int QDeclarativeType::enumValue(const QHashedStringRef &name) const +{ + d->initEnums(); + + int *rv = d->m_enums.value(name); + return rv?*rv:-1; +} + +int QDeclarativeType::enumValue(const QHashedV8String &name) const +{ + d->initEnums(); + + int *rv = d->m_enums.value(name); + return rv?*rv:-1; +} + +QDeclarativeTypeModule::QDeclarativeTypeModule() +: d(new QDeclarativeTypeModulePrivate) +{ +} + +QDeclarativeTypeModule::~QDeclarativeTypeModule() +{ + delete d; d = 0; +} + +QByteArray QDeclarativeTypeModule::module() const +{ + return d->uri.uri; +} + +int QDeclarativeTypeModule::majorVersion() const +{ + return d->uri.majorVersion; +} + +int QDeclarativeTypeModule::minimumMinorVersion() const +{ + return d->minMinorVersion; +} + +int QDeclarativeTypeModule::maximumMinorVersion() const +{ + return d->maxMinorVersion; +} + +void QDeclarativeTypeModulePrivate::add(QDeclarativeType *type) +{ + types << type; + + minMinorVersion = qMin(minMinorVersion, type->minorVersion()); + maxMinorVersion = qMax(maxMinorVersion, type->minorVersion()); + + QList &list = typeHash[type->elementName()]; + for (int ii = 0; ii < list.count(); ++ii) { + if (list.at(ii)->minorVersion() < type->minorVersion()) { + list.insert(ii, type); + return; + } + } + list.append(type); +} + +QList QDeclarativeTypeModule::types() +{ + QList rv; + QReadLocker lock(metaTypeDataLock()); + rv = d->types; + return rv; +} + +QList QDeclarativeTypeModule::type(const QString &name) +{ + QReadLocker lock(metaTypeDataLock()); + QList rv; + for (int ii = 0; ii < d->types.count(); ++ii) { + if (d->types.at(ii)->elementName() == name) + rv << d->types.at(ii); + } + return rv; +} + +QDeclarativeType *QDeclarativeTypeModule::type(const QHashedStringRef &name, int minor) +{ + QReadLocker lock(metaTypeDataLock()); + + QList *types = d->typeHash.value(name); + if (!types) return 0; + + for (int ii = 0; ii < types->count(); ++ii) + if (types->at(ii)->minorVersion() <= minor) + return types->at(ii); + + return 0; +} + +QDeclarativeType *QDeclarativeTypeModule::type(const QHashedV8String &name, int minor) +{ + QReadLocker lock(metaTypeDataLock()); + + QList *types = d->typeHash.value(name); + if (!types) return 0; + + for (int ii = 0; ii < types->count(); ++ii) + if (types->at(ii)->minorVersion() <= minor) + return types->at(ii); + + return 0; +} + + +QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion() +: m_module(0), m_minor(0) +{ +} + +QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion(QDeclarativeTypeModule *module, int minor) +: m_module(module), m_minor(minor) +{ + Q_ASSERT(m_module); + Q_ASSERT(m_minor >= 0); +} + +QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion(const QDeclarativeTypeModuleVersion &o) +: m_module(o.m_module), m_minor(o.m_minor) +{ +} + +QDeclarativeTypeModuleVersion &QDeclarativeTypeModuleVersion::operator=(const QDeclarativeTypeModuleVersion &o) +{ + m_module = o.m_module; + m_minor = o.m_minor; + return *this; +} + +QDeclarativeTypeModule *QDeclarativeTypeModuleVersion::module() const +{ + return m_module; +} + +int QDeclarativeTypeModuleVersion::minorVersion() const +{ + return m_minor; +} + +QDeclarativeType *QDeclarativeTypeModuleVersion::type(const QHashedStringRef &name) const +{ + if (m_module) return m_module->type(name, m_minor); + else return 0; +} + +QDeclarativeType *QDeclarativeTypeModuleVersion::type(const QHashedV8String &name) const +{ + if (m_module) return m_module->type(name, m_minor); + else return 0; +} + + int registerAutoParentFunction(QDeclarativePrivate::RegisterAutoParent &autoparent) { QWriteLocker lock(metaTypeDataLock()); @@ -665,20 +888,15 @@ int registerType(const QDeclarativePrivate::RegisterType &type) if (type.uri) { QByteArray mod(type.uri); - QPair key(mod,type.versionMajor); - QDeclarativeMetaTypeData::ModuleInfoHash::Iterator it = data->modules.find(key); - if (it == data->modules.end()) { - // New module - data->modules.insert(key, QDeclarativeMetaTypeData::ModuleInfo(type.versionMajor,type.versionMinor)); - } else { - if ((*it).vminor_max < type.versionMinor) { - // Newer module - data->modules.insert(key, QDeclarativeMetaTypeData::ModuleInfo((*it).vmajor, (*it).vminor_min, type.versionMinor)); - } else if ((*it).vminor_min > type.versionMinor) { - // Older module - data->modules.insert(key, QDeclarativeMetaTypeData::ModuleInfo((*it).vmajor, type.versionMinor, (*it).vminor_min)); - } + + QDeclarativeMetaTypeData::VersionedUri versionedUri(mod, type.versionMajor); + QDeclarativeTypeModule *module = data->uriToModule.value(versionedUri); + if (!module) { + module = new QDeclarativeTypeModule; + module->d->uri = versionedUri; + data->uriToModule.insert(versionedUri, module); } + module->d->add(dtype); } return index; @@ -745,6 +963,23 @@ bool QDeclarativeMetaType::isAnyModule(const QByteArray &module) } /* + Returns true if a module \a uri of any version is installed. +*/ +bool QDeclarativeMetaType::isAnyModule(const QByteArray &uri) +{ + QReadLocker lock(metaTypeDataLock()); + QDeclarativeMetaTypeData *data = metaTypeData(); + + for (QDeclarativeMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin(); + iter != data->uriToModule.end(); ++iter) { + if ((*iter)->module() == uri) + return true; + } + + return false; +} + +/* 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. @@ -753,25 +988,33 @@ bool QDeclarativeMetaType::isAnyModule(const QByteArray &module) */ bool QDeclarativeMetaType::isModule(const QByteArray &module, int versionMajor, int versionMinor) { + Q_ASSERT(versionMajor >= 0 && versionMinor >= 0); + QReadLocker lock(metaTypeDataLock()); + QDeclarativeMetaTypeData *data = metaTypeData(); // first, check Types - QDeclarativeMetaTypeData::ModuleInfoHash::Iterator it = data->modules.find(QPair(module,versionMajor)); - if (it != data->modules.end()) { - if (((*it).vminor_max >= versionMinor && (*it).vminor_min <= versionMinor)) - return true; - } + QDeclarativeTypeModule *tm = + data->uriToModule.value(QDeclarativeMetaTypeData::VersionedUri(module, versionMajor)); + if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor) + return true; // then, check ModuleApis foreach (const QDeclarativeMetaType::ModuleApi &mApi, data->moduleApis.value(module).moduleApis) { - if (mApi.major == versionMajor && mApi.minor == versionMinor) { + if (mApi.major == versionMajor && mApi.minor == versionMinor) // XXX is this correct? return true; - } } return false; } +QDeclarativeTypeModule *QDeclarativeMetaType::typeModule(const QByteArray &uri, int majorVersion) +{ + QReadLocker lock(metaTypeDataLock()); + QDeclarativeMetaTypeData *data = metaTypeData(); + return data->uriToModule.value(QDeclarativeMetaTypeData::VersionedUri(uri, majorVersion)); +} + QList QDeclarativeMetaType::parentFunctions() { QReadLocker lock(metaTypeDataLock()); @@ -1003,6 +1246,7 @@ QDeclarativeMetaType::StringConverter QDeclarativeMetaType::customStringConverte */ QDeclarativeType *QDeclarativeMetaType::qmlType(const QByteArray &name, int version_major, int version_minor) { + Q_ASSERT(version_major >= 0 && version_minor >= 0); QReadLocker lock(metaTypeDataLock()); QDeclarativeMetaTypeData *data = metaTypeData(); @@ -1034,6 +1278,7 @@ QDeclarativeType *QDeclarativeMetaType::qmlType(const QMetaObject *metaObject) */ QDeclarativeType *QDeclarativeMetaType::qmlType(const QMetaObject *metaObject, const QByteArray &module, int version_major, int version_minor) { + Q_ASSERT(version_major >= 0 && version_minor >= 0); QReadLocker lock(metaTypeDataLock()); QDeclarativeMetaTypeData *data = metaTypeData(); diff --git a/src/declarative/qml/qdeclarativemetatype_p.h b/src/declarative/qml/qdeclarativemetatype_p.h index 429aa7a..ca1d869 100644 --- a/src/declarative/qml/qdeclarativemetatype_p.h +++ b/src/declarative/qml/qdeclarativemetatype_p.h @@ -66,6 +66,7 @@ QT_BEGIN_NAMESPACE class QDeclarativeType; class QDeclarativeCustomParser; class QDeclarativeTypePrivate; +class QDeclarativeTypeModule; class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeMetaType { @@ -104,8 +105,9 @@ public: static void registerCustomStringConverter(int, StringConverter); static StringConverter customStringConverter(int); - static bool isAnyModule(const QByteArray &module); + static bool isAnyModule(const QByteArray &uri); static bool isModule(const QByteArray &module, int versionMajor, int versionMinor); + static QDeclarativeTypeModule *typeModule(const QByteArray &uri, int majorVersion); static QList parentFunctions(); @@ -129,11 +131,14 @@ public: static ModuleApi moduleApi(const QByteArray &, int, int); }; +class QHashedStringRef; +class QHashedV8String; class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeType { public: QByteArray typeName() const; QByteArray qmlTypeName() const; + const QString &elementName() const; QByteArray module() const; int majorVersion() const; @@ -176,6 +181,8 @@ public: int index() const; + int enumValue(const QHashedStringRef &) const; + int enumValue(const QHashedV8String &) const; private: QDeclarativeType *superType() const; friend class QDeclarativeTypePrivate; @@ -189,8 +196,49 @@ private: QDeclarativeTypePrivate *d; }; +class QDeclarativeTypeModulePrivate; +class QDeclarativeTypeModule +{ +public: + QByteArray module() const; + int majorVersion() const; + + int minimumMinorVersion() const; + int maximumMinorVersion() const; + + QList types(); + QList type(const QString &); + + QDeclarativeType *type(const QHashedStringRef &, int); + QDeclarativeType *type(const QHashedV8String &, int); + +private: + friend int registerType(const QDeclarativePrivate::RegisterType &); + QDeclarativeTypeModule(); + ~QDeclarativeTypeModule(); + QDeclarativeTypeModulePrivate *d; +}; + +class QDeclarativeTypeModuleVersion +{ +public: + QDeclarativeTypeModuleVersion(); + QDeclarativeTypeModuleVersion(QDeclarativeTypeModule *, int); + QDeclarativeTypeModuleVersion(const QDeclarativeTypeModuleVersion &); + QDeclarativeTypeModuleVersion &operator=(const QDeclarativeTypeModuleVersion &); + + QDeclarativeTypeModule *module() const; + int minorVersion() const; + + QDeclarativeType *type(const QHashedStringRef &) const; + QDeclarativeType *type(const QHashedV8String &) const; + +private: + QDeclarativeTypeModule *m_module; + int m_minor; +}; + QDeclarativeMetaType::ModuleApi::ModuleApi() -// : major(0), minor(0), script(0), qobject(0) { major = 0; minor = 0; diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index 3406109..60e7855 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -235,63 +235,71 @@ void QDeclarativePropertyPrivate::initProperty(QObject *obj, const QString &name for (int ii = 0; ii < path.count() - 1; ++ii) { const QString &pathName = path.at(ii); - if (QDeclarativeTypeNameCache::Data *data = typeNameCache?typeNameCache->data(pathName):0) { - if (data->type) { - QDeclarativeAttachedPropertiesFunc func = data->type->attachedPropertiesFunction(); - if (!func) return; // Not an attachable type - - currentObject = qmlAttachedPropertiesObjectById(data->type->attachedPropertiesId(), currentObject); - if (!currentObject) return; // Something is broken with the attachable type - } else { - Q_ASSERT(data->typeNamespace); - if ((ii + 1) == path.count()) return; // No type following the namespace + if (typeNameCache) { + QDeclarativeTypeNameCache::Result r = typeNameCache->query(pathName); + if (r.isValid()) { + if (r.type) { + QDeclarativeAttachedPropertiesFunc func = r.type->attachedPropertiesFunction(); + if (!func) return; // Not an attachable type + + currentObject = qmlAttachedPropertiesObjectById(r.type->attachedPropertiesId(), currentObject); + if (!currentObject) return; // Something is broken with the attachable type + } else if (r.importNamespace) { + if ((ii + 1) == path.count()) return; // No type following the namespace + + ++ii; r = typeNameCache->query(path.at(ii), r.importNamespace); + if (!r.type) return; // Invalid type in namespace - ++ii; data = data->typeNamespace->data(path.at(ii)); - if (!data || !data->type) return; // Invalid type in namespace + QDeclarativeAttachedPropertiesFunc func = r.type->attachedPropertiesFunction(); + if (!func) return; // Not an attachable type - QDeclarativeAttachedPropertiesFunc func = data->type->attachedPropertiesFunction(); - if (!func) return; // Not an attachable type + currentObject = qmlAttachedPropertiesObjectById(r.type->attachedPropertiesId(), currentObject); + if (!currentObject) return; // Something is broken with the attachable type - currentObject = qmlAttachedPropertiesObjectById(data->type->attachedPropertiesId(), currentObject); - if (!currentObject) return; // Something is broken with the attachable type + } else if (r.scriptIndex != -1) { + return; // Not a type + } else { + Q_ASSERT(!"Unreachable"); + } + continue; } - } else { - QDeclarativePropertyCache::Data local; - QDeclarativePropertyCache::Data *property = - QDeclarativePropertyCache::property(engine, obj, pathName, local); + } - if (!property) return; // Not a property - if (property->isFunction()) - return; // Not an object property + QDeclarativePropertyCache::Data local; + QDeclarativePropertyCache::Data *property = + QDeclarativePropertyCache::property(engine, obj, pathName, local); - if (ii == (path.count() - 2) && QDeclarativeValueTypeFactory::isValueType(property->propType)) { - // We're now at a value type property. We can use a global valuetypes array as we - // never actually use the objects, just look up their properties. - QObject *typeObject = (*qmlValueTypes())[property->propType]; - if (!typeObject) return; // Not a value type + if (!property) return; // Not a property + if (property->isFunction()) + return; // Not an object property - int idx = typeObject->metaObject()->indexOfProperty(path.last().toUtf8().constData()); - if (idx == -1) return; // Value type property does not exist + if (ii == (path.count() - 2) && QDeclarativeValueTypeFactory::isValueType(property->propType)) { + // We're now at a value type property. We can use a global valuetypes array as we + // never actually use the objects, just look up their properties. + QObject *typeObject = (*qmlValueTypes())[property->propType]; + if (!typeObject) return; // Not a value type - QMetaProperty vtProp = typeObject->metaObject()->property(idx); + int idx = typeObject->metaObject()->indexOfProperty(path.last().toUtf8().constData()); + if (idx == -1) return; // Value type property does not exist - object = currentObject; - core = *property; - valueType.flags = QDeclarativePropertyCache::Data::flagsForProperty(vtProp); - valueType.valueTypeCoreIdx = idx; - valueType.valueTypePropType = vtProp.userType(); + QMetaProperty vtProp = typeObject->metaObject()->property(idx); - return; - } else { - if (!property->isQObject()) - return; // Not an object property + object = currentObject; + core = *property; + valueType.flags = QDeclarativePropertyCache::Data::flagsForProperty(vtProp); + valueType.valueTypeCoreIdx = idx; + valueType.valueTypePropType = vtProp.userType(); - void *args[] = { ¤tObject, 0 }; - QMetaObject::metacall(currentObject, QMetaObject::ReadProperty, property->coreIndex, args); - if (!currentObject) return; // No value + return; + } else { + if (!property->isQObject()) + return; // Not an object property + + void *args[] = { ¤tObject, 0 }; + QMetaObject::metacall(currentObject, QMetaObject::ReadProperty, property->coreIndex, args); + if (!currentObject) return; // No value - } } } diff --git a/src/declarative/qml/qdeclarativetypenamecache.cpp b/src/declarative/qml/qdeclarativetypenamecache.cpp index 23183aa..b7e4259 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), m_moduleApi(0) +: QDeclarativeCleanup(e), engine(e) { } @@ -57,52 +57,93 @@ QDeclarativeTypeNameCache::~QDeclarativeTypeNameCache() void QDeclarativeTypeNameCache::clear() { - stringCache.clear(); - m_moduleApi = 0; + m_namedImports.clear(); + m_anonymousImports.clear(); engine = 0; } -void QDeclarativeTypeNameCache::add(const QString &name, int importedScriptIndex) +void QDeclarativeTypeNameCache::add(const QHashedString &name, int importedScriptIndex) { - if (stringCache.contains(name)) + if (m_namedImports.contains(name)) return; - Data data; - data.importedScriptIndex = importedScriptIndex; - stringCache.insert(name, data); + Import import; + import.scriptIndex = importedScriptIndex; + m_namedImports.insert(name, import); } -void QDeclarativeTypeNameCache::add(const QString &name, QDeclarativeType *type) +QDeclarativeTypeNameCache::Result QDeclarativeTypeNameCache::query(const QHashedStringRef &name) { - if (stringCache.contains(name)) - return; - - Data data; - data.type = type; - stringCache.insert(name, data); + Import *i = m_namedImports.value(name); + if (i) { + if (i->scriptIndex != -1) + return Result(i->scriptIndex); + else + return Result((const void *)i); + } + + for (int ii = 0; ii < m_anonymousImports.count(); ++ii) { + if (QDeclarativeType *type = m_anonymousImports.at(ii).type(name)) + return Result(type); + } + + return Result(); } -void QDeclarativeTypeNameCache::add(const QString &name, QDeclarativeTypeNameCache *typeNamespace) +QDeclarativeTypeNameCache::Result QDeclarativeTypeNameCache::query(const QHashedStringRef &name, + const void *importNamespace) { - if (stringCache.contains(name)) - return; - - QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); + Q_ASSERT(importNamespace); + Import *i = (Import *)importNamespace; + Q_ASSERT(i->scriptIndex == -1); + + for (int ii = 0; ii < i->modules.count(); ++ii) { + if (QDeclarativeType *type = i->modules.at(ii).type(name)) + return Result(type); + } + + return Result(); +} - Data data; - typeNamespace->addref(); - data.typeNamespace = typeNamespace; - stringCache.insert(name, data); +QDeclarativeTypeNameCache::Result QDeclarativeTypeNameCache::query(const QHashedV8String &name) +{ + Import *i = m_namedImports.value(name); + if (i) { + if (i->scriptIndex != -1) + return Result(i->scriptIndex); + else + return Result((const void *)i); + } + + for (int ii = 0; ii < m_anonymousImports.count(); ++ii) { + if (QDeclarativeType *type = m_anonymousImports.at(ii).type(name)) + return Result(type); + } + + return Result(); } -QDeclarativeTypeNameCache::Data *QDeclarativeTypeNameCache::data(const QString &id) const +QDeclarativeTypeNameCache::Result QDeclarativeTypeNameCache::query(const QHashedV8String &name, const void *importNamespace) { - return stringCache.value(id); + Q_ASSERT(importNamespace); + Import *i = (Import *)importNamespace; + Q_ASSERT(i->scriptIndex == -1); + + for (int ii = 0; ii < i->modules.count(); ++ii) { + if (QDeclarativeType *type = i->modules.at(ii).type(name)) + return Result(type); + } + + return Result(); } -void QDeclarativeTypeNameCache::setModuleApi(QDeclarativeMetaType::ModuleApiInstance *api) +QDeclarativeMetaType::ModuleApiInstance *QDeclarativeTypeNameCache::moduleApi(const void *importNamespace) { - m_moduleApi = api; + Q_ASSERT(importNamespace); + Import *i = (Import *)importNamespace; + Q_ASSERT(i->scriptIndex == -1); + + return i->moduleApi; } QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativetypenamecache_p.h b/src/declarative/qml/qdeclarativetypenamecache_p.h index e89747b..a80bb64 100644 --- a/src/declarative/qml/qdeclarativetypenamecache_p.h +++ b/src/declarative/qml/qdeclarativetypenamecache_p.h @@ -59,6 +59,8 @@ #include +#include + QT_BEGIN_NAMESPACE class QDeclarativeType; @@ -69,78 +71,89 @@ public: QDeclarativeTypeNameCache(QDeclarativeEngine *); virtual ~QDeclarativeTypeNameCache(); - struct Data { - inline Data(); - inline Data(const Data &); - inline ~Data(); - inline Data &operator=(const Data &); - QDeclarativeType *type; - QDeclarativeTypeNameCache *typeNamespace; - int importedScriptIndex; - }; + inline bool isEmpty() const; - void add(const QString &, int); - void add(const QString &, QDeclarativeType *); - void add(const QString &, QDeclarativeTypeNameCache *); + void add(const QHashedString &, int); - Data *data(const QString &) const; - inline Data *data(const QHashedV8String &) const; - inline bool isEmpty() const; + struct Result { + inline Result(); + inline Result(const void *importNamespace); + inline Result(QDeclarativeType *type); + inline Result(int scriptIndex); + inline Result(const Result &); + + inline bool isValid() const; - inline QDeclarativeMetaType::ModuleApiInstance *moduleApi() const; - void setModuleApi(QDeclarativeMetaType::ModuleApiInstance *); + QDeclarativeType *type; + const void *importNamespace; + int scriptIndex; + }; + Result query(const QHashedStringRef &); + Result query(const QHashedStringRef &, const void *importNamespace); + Result query(const QHashedV8String &); + Result query(const QHashedV8String &, const void *importNamespace); + QDeclarativeMetaType::ModuleApiInstance *moduleApi(const void *importNamespace); protected: virtual void clear(); private: - typedef QStringHash StringCache; + friend class QDeclarativeImports; - StringCache stringCache; + struct Import { + inline Import(); + // Imported module + QDeclarativeMetaType::ModuleApiInstance *moduleApi; + QVector modules; + + // Or, imported script + int scriptIndex; + }; + + QStringHash m_namedImports; + QVector m_anonymousImports; QDeclarativeEngine *engine; - QDeclarativeMetaType::ModuleApiInstance *m_moduleApi; }; -QDeclarativeTypeNameCache::Data::Data() -: type(0), typeNamespace(0), importedScriptIndex(-1) +QDeclarativeTypeNameCache::Result::Result() +: type(0), importNamespace(0), scriptIndex(-1) { } -QDeclarativeTypeNameCache::Data::~Data() +QDeclarativeTypeNameCache::Result::Result(const void *importNamespace) +: type(0), importNamespace(importNamespace), scriptIndex(-1) { - if (typeNamespace) typeNamespace->release(); } -bool QDeclarativeTypeNameCache::isEmpty() const +QDeclarativeTypeNameCache::Result::Result(QDeclarativeType *type) +: type(type), importNamespace(0), scriptIndex(-1) { - return stringCache.isEmpty(); } -QDeclarativeTypeNameCache::Data::Data(const QDeclarativeTypeNameCache::Data &o) -: type(o.type), typeNamespace(o.typeNamespace), importedScriptIndex(o.importedScriptIndex) +QDeclarativeTypeNameCache::Result::Result(int scriptIndex) +: type(0), importNamespace(0), scriptIndex(scriptIndex) { - if (typeNamespace) typeNamespace->addref(); } -QDeclarativeTypeNameCache::Data &QDeclarativeTypeNameCache::Data::operator=(const QDeclarativeTypeNameCache::Data &o) +QDeclarativeTypeNameCache::Result::Result(const Result &o) +: type(o.type), importNamespace(o.importNamespace), scriptIndex(o.scriptIndex) { - if (o.typeNamespace) o.typeNamespace->addref(); - if (typeNamespace) typeNamespace->release(); - type = o.type; - typeNamespace = o.typeNamespace; - importedScriptIndex = o.importedScriptIndex; - return *this; } -QDeclarativeMetaType::ModuleApiInstance *QDeclarativeTypeNameCache::moduleApi() const +bool QDeclarativeTypeNameCache::Result::isValid() const { - return m_moduleApi; + return type || importNamespace || scriptIndex != -1; } -QDeclarativeTypeNameCache::Data *QDeclarativeTypeNameCache::data(const QHashedV8String &name) const +QDeclarativeTypeNameCache::Import::Import() +: scriptIndex(-1) +{ +} + +bool QDeclarativeTypeNameCache::isEmpty() const { - return stringCache.value(name); + return m_namedImports.isEmpty() && m_anonymousImports.isEmpty(); } QT_END_NAMESPACE diff --git a/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp index bddfca1..6a6f4f0 100644 --- a/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp +++ b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp @@ -444,64 +444,63 @@ bool QDeclarativeV4IRBuilder::visit(AST::IdentifierExpression *ast) 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); + QDeclarativeTypeNameCache::Result r = m_expression->importCache->query(name); + if (r.isValid()) { + if (r.type) { + _expr.code = _block->ATTACH_TYPE(name, r.type, IR::Name::ScopeStorage, line, column); + } + // We don't support anything else + } 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); + QDeclarativePropertyCache::Data *data = cache->property(name); + + if (data && data->revision != 0) { + if (qmlVerboseCompiler()) + qWarning() << "*** versioned symbol:" << name; + discard(); + return false; + } - if (data && data->revision != 0) { - if (qmlVerboseCompiler()) - qWarning() << "*** versioned symbol:" << name; - discard(); - return false; + if (data && !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 (data && !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); - 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); - QDeclarativePropertyCache::Data *data = cache->property(name); + if (data && data->revision != 0) { + if (qmlVerboseCompiler()) + qWarning() << "*** versioned symbol:" << name; + discard(); + return false; + } - if (data && data->revision != 0) { - if (qmlVerboseCompiler()) - qWarning() << "*** versioned symbol:" << name; - discard(); - return false; + if (data && !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 (data && !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 (!found && qmlVerboseCompiler()) - qWarning() << "*** unknown symbol:" << name; } if (_expr.code && _expr.hint == ExprResult::cx) { diff --git a/src/declarative/qml/v8/qv8contextwrapper.cpp b/src/declarative/qml/v8/qv8contextwrapper.cpp index f41c994..29857b2 100644 --- a/src/declarative/qml/v8/qv8contextwrapper.cpp +++ b/src/declarative/qml/v8/qv8contextwrapper.cpp @@ -282,19 +282,19 @@ v8::Handle QV8ContextWrapper::Getter(v8::Local property, if (context->imports && QV8Engine::startsWithUpper(property)) { // Search for attached properties, enums and imported scripts - QDeclarativeTypeNameCache::Data *data = context->imports->data(propertystring); - - if (data) { - if (data->importedScriptIndex != -1) { - int index = data->importedScriptIndex; + QDeclarativeTypeNameCache::Result r = context->imports->query(propertystring); + + if (r.isValid()) { + if (r.scriptIndex != -1) { + int index = r.scriptIndex; if (index < context->importedScripts.count()) return context->importedScripts.at(index); else return v8::Undefined(); - } else if (data->type) { - return engine->typeWrapper()->newObject(scopeObject, data->type); - } else if (data->typeNamespace) { - return engine->typeWrapper()->newObject(scopeObject, data->typeNamespace); + } else if (r.type) { + return engine->typeWrapper()->newObject(scopeObject, r.type); + } else if (r.importNamespace) { + return engine->typeWrapper()->newObject(scopeObject, context->imports, r.importNamespace); } Q_ASSERT(!"Unreachable"); } diff --git a/src/declarative/qml/v8/qv8qobjectwrapper.cpp b/src/declarative/qml/v8/qv8qobjectwrapper.cpp index f59e995..52e1064 100644 --- a/src/declarative/qml/v8/qv8qobjectwrapper.cpp +++ b/src/declarative/qml/v8/qv8qobjectwrapper.cpp @@ -618,14 +618,20 @@ v8::Handle QV8QObjectWrapper::Getter(v8::Local property, if (QV8Engine::startsWithUpper(property)) { // Check for attached properties QDeclarativeContextData *context = v8engine->callingContext(); - QDeclarativeTypeNameCache::Data *data = - context && (context->imports)?context->imports->data(propertystring):0; - - if (data) { - if (data->type) { - return v8engine->typeWrapper()->newObject(object, data->type, QV8TypeWrapper::ExcludeEnums); - } else if (data->typeNamespace) { - return v8engine->typeWrapper()->newObject(object, data->typeNamespace, QV8TypeWrapper::ExcludeEnums); + + if (context && context->imports) { + QDeclarativeTypeNameCache::Result r = context->imports->query(propertystring); + + if (r.isValid()) { + if (r.scriptIndex != -1) { + return v8::Undefined(); + } else if (r.type) { + return v8engine->typeWrapper()->newObject(object, r.type, QV8TypeWrapper::ExcludeEnums); + } else if (r.importNamespace) { + return v8engine->typeWrapper()->newObject(object, context->imports, r.importNamespace, + QV8TypeWrapper::ExcludeEnums); + } + Q_ASSERT(!"Unreachable"); } } } diff --git a/src/declarative/qml/v8/qv8typewrapper.cpp b/src/declarative/qml/v8/qv8typewrapper.cpp index 98ed1d5..6bd9a54 100644 --- a/src/declarative/qml/v8/qv8typewrapper.cpp +++ b/src/declarative/qml/v8/qv8typewrapper.cpp @@ -61,12 +61,14 @@ public: QV8TypeWrapper::TypeNameMode mode; QDeclarativeGuard object; + QDeclarativeType *type; QDeclarativeTypeNameCache *typeNamespace; + const void *importNamespace; }; QV8TypeResource::QV8TypeResource(QV8Engine *engine) -: QV8ObjectResource(engine), mode(QV8TypeWrapper::IncludeEnums), type(0), typeNamespace(0) +: QV8ObjectResource(engine), mode(QV8TypeWrapper::IncludeEnums), type(0), typeNamespace(0), importNamespace(0) { } @@ -98,6 +100,7 @@ void QV8TypeWrapper::init(QV8Engine *engine) m_constructor = qPersistentNew(ft->GetFunction()); } +// Returns a type wrapper for type t on o. This allows access of enums, and attached properties. v8::Local QV8TypeWrapper::newObject(QObject *o, QDeclarativeType *t, TypeNameMode mode) { Q_ASSERT(t); @@ -109,14 +112,18 @@ v8::Local QV8TypeWrapper::newObject(QObject *o, QDeclarativeType *t, return rv; } -v8::Local QV8TypeWrapper::newObject(QObject *o, QDeclarativeTypeNameCache *t, TypeNameMode mode) +// Returns a type wrapper for importNamespace (of t) on o. This allows nested resolution of a type in a +// namespace. +v8::Local QV8TypeWrapper::newObject(QObject *o, QDeclarativeTypeNameCache *t, + const void *importNamespace, TypeNameMode mode) { Q_ASSERT(t); + Q_ASSERT(importNamespace); // XXX NewInstance() should be optimized v8::Local rv = m_constructor->NewInstance(); QV8TypeResource *r = new QV8TypeResource(m_engine); t->addref(); - r->mode = mode; r->object = o; r->typeNamespace = t; + r->mode = mode; r->object = o; r->typeNamespace = t; r->importNamespace = importNamespace; rv->SetExternalResource(r); return rv; } @@ -139,19 +146,9 @@ v8::Handle QV8TypeWrapper::Getter(v8::Local property, QDeclarativeType *type = resource->type; if (QV8Engine::startsWithUpper(property)) { - if (resource->mode == IncludeEnums) { - QString name = v8engine->toString(property); - - // ### Optimize - QByteArray enumName = name.toUtf8(); - const QMetaObject *metaObject = type->baseMetaObject(); - for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) { - QMetaEnum e = metaObject->enumerator(ii); - int value = e.keyToValue(enumName.constData()); - if (value != -1) - return v8::Integer::New(value); - } - } + int value = type->enumValue(propertystring); + if (-1 != value) + return v8::Integer::New(value); // Fall through to return empty handle @@ -167,14 +164,15 @@ v8::Handle QV8TypeWrapper::Getter(v8::Local property, // Fall through to return empty handle } else if (resource->typeNamespace) { + Q_ASSERT(resource->importNamespace); + QDeclarativeTypeNameCache::Result r = resource->typeNamespace->query(propertystring, + resource->importNamespace); - QDeclarativeTypeNameCache *typeNamespace = resource->typeNamespace; - QDeclarativeTypeNameCache::Data *d = typeNamespace->data(propertystring); - Q_ASSERT(!d || !d->typeNamespace); // Nested namespaces not supported + if (r.isValid()) { + Q_ASSERT(r.type); - if (d && d->type) { - return v8engine->typeWrapper()->newObject(object, d->type, resource->mode); - } else if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = typeNamespace->moduleApi()) { + return v8engine->typeWrapper()->newObject(object, r.type, resource->mode); + } else if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = resource->typeNamespace->moduleApi(resource->importNamespace)) { if (moduleApi->scriptCallback) { moduleApi->scriptApi = moduleApi->scriptCallback(v8engine->engine(), v8engine->engine()); diff --git a/src/declarative/qml/v8/qv8typewrapper_p.h b/src/declarative/qml/v8/qv8typewrapper_p.h index e7403df..2e79946 100644 --- a/src/declarative/qml/v8/qv8typewrapper_p.h +++ b/src/declarative/qml/v8/qv8typewrapper_p.h @@ -73,7 +73,8 @@ public: enum TypeNameMode { IncludeEnums, ExcludeEnums }; v8::Local newObject(QObject *, QDeclarativeType *, TypeNameMode = IncludeEnums); - v8::Local newObject(QObject *, QDeclarativeTypeNameCache *, TypeNameMode = IncludeEnums); + v8::Local newObject(QObject *, QDeclarativeTypeNameCache *, const void *, + TypeNameMode = IncludeEnums); private: static v8::Handle Getter(v8::Local property, diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp index e6603ad..ed2512c 100644 --- a/tools/qmlscene/main.cpp +++ b/tools/qmlscene/main.cpp @@ -358,6 +358,7 @@ static void checkAndAdaptVersion(const QUrl &url) } QRegExp quick1("^\\s*import +QtQuick +1\\."); + QRegExp quick2("^\\s*import +QtQuick +2\\."); QRegExp qt47("^\\s*import +Qt +4\\.7"); QString envToWrite; @@ -365,16 +366,20 @@ static void checkAndAdaptVersion(const QUrl &url) QTextStream stream(&f); bool codeFound= false; - while (!codeFound && envToWrite.isEmpty()) { + while (!codeFound) { QString line = stream.readLine(); if (line.contains("{")) codeFound = true; - if (quick1.indexIn(line) >= 0) { + if (envToWrite.isEmpty() && quick1.indexIn(line) >= 0) { envToWrite = QLatin1String("quick1"); compat = QLatin1String("QtQuick 1.0"); - } else if (qt47.indexIn(line) >= 0) { + } else if (envToWrite.isEmpty() && qt47.indexIn(line) >= 0) { envToWrite = QLatin1String("qt"); compat = QLatin1String("Qt 4.7"); + } else if (quick2.indexIn(line) >= 0) { + envToWrite.clear(); + compat.clear(); + break; } } -- 2.7.4