aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2011-07-06 13:43:47 +1000
committerQt by Nokia <qt-info@nokia.com>2011-08-30 13:18:28 +0200
commit809ee66b67ce70dba89a04b92daccc9445af2e75 (patch)
tree84c6d4023312d72583ccfcd2ad79df4fdf714527 /src/declarative
parentf8f9db6cc74a34d3648ac693196c0f5d4bda9c50 (diff)
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 <roberto.raggi@nokia.com>
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/qml/qdeclarativeimport.cpp86
-rw-r--r--src/declarative/qml/qdeclarativemetatype.cpp317
-rw-r--r--src/declarative/qml/qdeclarativemetatype_p.h52
-rw-r--r--src/declarative/qml/qdeclarativeproperty.cpp96
-rw-r--r--src/declarative/qml/qdeclarativetypenamecache.cpp97
-rw-r--r--src/declarative/qml/qdeclarativetypenamecache_p.h93
-rw-r--r--src/declarative/qml/v4/qdeclarativev4irbuilder.cpp91
-rw-r--r--src/declarative/qml/v8/qv8contextwrapper.cpp18
-rw-r--r--src/declarative/qml/v8/qv8qobjectwrapper.cpp22
-rw-r--r--src/declarative/qml/v8/qv8typewrapper.cpp42
-rw-r--r--src/declarative/qml/v8/qv8typewrapper_p.h3
11 files changed, 626 insertions, 291 deletions
diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp
index b2fa071f91..a28428ca24 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<QDeclarativeType *> 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<QString,QDeclarativeImportedNamespace* >::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<QString,QDeclarativeImportedNamespace* >::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 41705bce72..da7be11545 100644
--- a/src/declarative/qml/qdeclarativemetatype.cpp
+++ b/src/declarative/qml/qdeclarativemetatype.cpp
@@ -42,9 +42,10 @@
#include <QtDeclarative/qdeclarativeprivate.h>
#include "private/qdeclarativemetatype_p.h"
-#include "private/qdeclarativeproxymetaobject_p.h"
-#include "private/qdeclarativecustomparser_p.h"
-#include "private/qdeclarativeguard_p.h"
+#include <private/qdeclarativeproxymetaobject_p.h>
+#include <private/qdeclarativecustomparser_p.h>
+#include <private/qdeclarativeguard_p.h>
+#include <private/qhashedstring_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qstringlist.h>
@@ -99,6 +100,21 @@ struct QDeclarativeMetaTypeData
MetaObjects metaObjectToType;
typedef QHash<int, QDeclarativeMetaType::StringConverter> 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<VersionedUri, QDeclarativeTypeModule *> TypeModules;
+ TypeModules uriToModule;
+
struct ModuleApiList {
ModuleApiList() : sorted(true) {}
QList<QDeclarativeMetaType::ModuleApi> 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<QPair<QByteArray,int>, ModuleInfo> ModuleInfoHash;
- ModuleInfoHash modules;
-
QBitArray objects;
QBitArray interfaces;
QBitArray lists;
QList<QDeclarativePrivate::AutoParentFunction> parentFunctions;
};
+
+class QDeclarativeTypeModulePrivate
+{
+public:
+ QDeclarativeTypeModulePrivate()
+ : minMinorVersion(INT_MAX), maxMinorVersion(0) {}
+
+ QDeclarativeMetaTypeData::VersionedUri uri;
+
+ int minMinorVersion;
+ int maxMinorVersion;
+
+ void add(QDeclarativeType *);
+
+ QStringHash<QList<QDeclarativeType *> > typeHash;
+ QList<QDeclarativeType *> 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<QDeclarativeProxyMetaObject::ProxyData> m_metaObjects;
+ mutable QStringHash<int> m_enums;
static QHash<const QMetaObject *, int> 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<QDeclarativeType *> &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<QDeclarativeType *> QDeclarativeTypeModule::types()
+{
+ QList<QDeclarativeType *> rv;
+ QReadLocker lock(metaTypeDataLock());
+ rv = d->types;
+ return rv;
+}
+
+QList<QDeclarativeType *> QDeclarativeTypeModule::type(const QString &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QList<QDeclarativeType *> 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<QDeclarativeType *> *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<QDeclarativeType *> *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<QByteArray,int> 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<QByteArray,int>(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<QDeclarativePrivate::AutoParentFunction> 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 429aa7a98f..ca1d869850 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<QDeclarativePrivate::AutoParentFunction> 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<QDeclarativeType *> types();
+ QList<QDeclarativeType *> 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 3406109a28..60e785510a 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[] = { &currentObject, 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[] = { &currentObject, 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 23183aa9fb..b7e4259b4c 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 e89747b15a..a80bb6492c 100644
--- a/src/declarative/qml/qdeclarativetypenamecache_p.h
+++ b/src/declarative/qml/qdeclarativetypenamecache_p.h
@@ -59,6 +59,8 @@
#include <private/qhashedstring_p.h>
+#include <QtCore/qvector.h>
+
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<Data> StringCache;
+ friend class QDeclarativeImports;
- StringCache stringCache;
+ struct Import {
+ inline Import();
+ // Imported module
+ QDeclarativeMetaType::ModuleApiInstance *moduleApi;
+ QVector<QDeclarativeTypeModuleVersion> modules;
+
+ // Or, imported script
+ int scriptIndex;
+ };
+
+ QStringHash<Import> m_namedImports;
+ QVector<QDeclarativeTypeModuleVersion> 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 bddfca18b4..6a6f4f0baf 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 f41c994a0d..29857b2585 100644
--- a/src/declarative/qml/v8/qv8contextwrapper.cpp
+++ b/src/declarative/qml/v8/qv8contextwrapper.cpp
@@ -282,19 +282,19 @@ v8::Handle<v8::Value> QV8ContextWrapper::Getter(v8::Local<v8::String> 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 f59e995e2d..52e106494c 100644
--- a/src/declarative/qml/v8/qv8qobjectwrapper.cpp
+++ b/src/declarative/qml/v8/qv8qobjectwrapper.cpp
@@ -618,14 +618,20 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Getter(v8::Local<v8::String> 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 98ed1d51b2..6bd9a54db5 100644
--- a/src/declarative/qml/v8/qv8typewrapper.cpp
+++ b/src/declarative/qml/v8/qv8typewrapper.cpp
@@ -61,12 +61,14 @@ public:
QV8TypeWrapper::TypeNameMode mode;
QDeclarativeGuard<QObject> 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<v8::Function>(ft->GetFunction());
}
+// Returns a type wrapper for type t on o. This allows access of enums, and attached properties.
v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeType *t, TypeNameMode mode)
{
Q_ASSERT(t);
@@ -109,14 +112,18 @@ v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeType *t,
return rv;
}
-v8::Local<v8::Object> 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<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeTypeNameCache *t,
+ const void *importNamespace, TypeNameMode mode)
{
Q_ASSERT(t);
+ Q_ASSERT(importNamespace);
// XXX NewInstance() should be optimized
v8::Local<v8::Object> 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<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> 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<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> 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 e7403dfa40..2e79946a6e 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<v8::Object> newObject(QObject *, QDeclarativeType *, TypeNameMode = IncludeEnums);
- v8::Local<v8::Object> newObject(QObject *, QDeclarativeTypeNameCache *, TypeNameMode = IncludeEnums);
+ v8::Local<v8::Object> newObject(QObject *, QDeclarativeTypeNameCache *, const void *,
+ TypeNameMode = IncludeEnums);
private:
static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,