aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
authorMatthew Vogt <matthew.vogt@nokia.com>2012-01-18 17:12:25 +1000
committerQt by Nokia <qt-info@nokia.com>2012-01-24 23:18:34 +0100
commit149f6afe321ce59aebe4ce2f9dddd1881d0ac22b (patch)
tree45233b8c808ed553051799b38a6b1e73898db2e1 /src/declarative
parent49212ef6d8934a023e6d0a7b778ec25605a8be7a (diff)
Allow JS API in modules
Allow modules to export verisoned javascript code into specified namespaces. Task-number: QTBUG-20857 Change-Id: Ic968c697ba36cbc4535870ed5eed2fe7f01af11d Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/qml/ftw/qhashedstring_p.h13
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp27
-rw-r--r--src/declarative/qml/qdeclarativedirparser.cpp19
-rw-r--r--src/declarative/qml/qdeclarativedirparser_p.h17
-rw-r--r--src/declarative/qml/qdeclarativeimport.cpp114
-rw-r--r--src/declarative/qml/qdeclarativeimport_p.h9
-rw-r--r--src/declarative/qml/qdeclarativetypeloader.cpp26
-rw-r--r--src/declarative/qml/qdeclarativetypeloader_p.h3
-rw-r--r--src/declarative/qml/qdeclarativetypenamecache.cpp70
-rw-r--r--src/declarative/qml/qdeclarativetypenamecache_p.h30
-rw-r--r--src/declarative/qml/v8/qv8typewrapper.cpp11
11 files changed, 266 insertions, 73 deletions
diff --git a/src/declarative/qml/ftw/qhashedstring_p.h b/src/declarative/qml/ftw/qhashedstring_p.h
index 00c9e341ca..f4dd6ee87f 100644
--- a/src/declarative/qml/ftw/qhashedstring_p.h
+++ b/src/declarative/qml/ftw/qhashedstring_p.h
@@ -104,6 +104,8 @@ public:
inline v8::Handle<v8::String> string() const;
+ inline QString toString() const;
+
private:
v8::String::CompleteHashData m_hash;
v8::Handle<v8::String> m_string;
@@ -917,6 +919,17 @@ v8::Handle<v8::String> QHashedV8String::string() const
return m_string;
}
+QString QHashedV8String::toString() const
+{
+ QString result;
+ result.reserve(m_hash.length);
+
+ for (int i = 0; i < m_hash.length; ++i)
+ result.append(m_string->GetCharacter(i));
+
+ return result;
+}
+
QHashedStringRef::QHashedStringRef()
: m_data(0), m_length(0), m_utf8length(-1), m_hash(0)
{
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index aec3993f18..07e381c18f 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -859,19 +859,28 @@ void QDeclarativeCompiler::compileTree(QDeclarativeScript::Object *tree)
if (componentStats)
componentStats->componentStat.lineNumber = tree->location.start.line;
- // Build global import scripts
- QStringList importedScriptIndexes;
-
- foreach (const QDeclarativeTypeData::ScriptReference &script, unit->resolvedScripts()) {
- importedScriptIndexes.append(script.qualifier);
- }
-
// We generate the importCache before we build the tree so that
// it can be used in the binding compiler. Given we "expect" the
// QML compilation to succeed, this isn't a waste.
output->importCache = new QDeclarativeTypeNameCache();
- for (int ii = 0; ii < importedScriptIndexes.count(); ++ii)
- output->importCache->add(importedScriptIndexes.at(ii), ii);
+ foreach (const QString &ns, unit->namespaces()) {
+ output->importCache->add(ns);
+ }
+
+ int scriptIndex = 0;
+ foreach (const QDeclarativeTypeData::ScriptReference &script, unit->resolvedScripts()) {
+ QString qualifier = script.qualifier;
+ QString enclosingNamespace;
+
+ const int lastDotIndex = qualifier.lastIndexOf(QLatin1Char('.'));
+ if (lastDotIndex != -1) {
+ enclosingNamespace = qualifier.left(lastDotIndex);
+ qualifier = qualifier.mid(lastDotIndex+1);
+ }
+
+ output->importCache->add(qualifier, scriptIndex++, enclosingNamespace);
+ }
+
unit->imports().populateCache(output->importCache, engine);
if (!buildObject(tree, BindingContext()) || !completeComponentBuild())
diff --git a/src/declarative/qml/qdeclarativedirparser.cpp b/src/declarative/qml/qdeclarativedirparser.cpp
index d7c44e4ba6..c4a11a9a43 100644
--- a/src/declarative/qml/qdeclarativedirparser.cpp
+++ b/src/declarative/qml/qdeclarativedirparser.cpp
@@ -103,6 +103,7 @@ bool QDeclarativeDirParser::parse()
_errors.clear();
_plugins.clear();
_components.clear();
+ _scripts.clear();
if (_source.isEmpty() && !_filePathSouce.isEmpty()) {
QFile file(_filePathSouce);
@@ -220,9 +221,16 @@ bool QDeclarativeDirParser::parse()
const int minorVersion = version.mid(dotIndex + 1).toInt(&validVersionNumber);
if (validVersionNumber) {
- const Component entry(sections[0], sections[2], majorVersion, minorVersion);
-
- _components.append(entry);
+ const QString &fileName = sections[2];
+
+ if (fileName.endsWith(QLatin1String(".js"))) {
+ // A 'js' extension indicates a namespaced script import
+ const Script entry(sections[0], fileName, majorVersion, minorVersion);
+ _scripts.append(entry);
+ } else {
+ const Component entry(sections[0], fileName, majorVersion, minorVersion);
+ _components.append(entry);
+ }
}
}
}
@@ -275,6 +283,11 @@ QList<QDeclarativeDirParser::Component> QDeclarativeDirParser::components() cons
return _components;
}
+QList<QDeclarativeDirParser::Script> QDeclarativeDirParser::scripts() const
+{
+ return _scripts;
+}
+
#ifdef QT_CREATOR
QList<QDeclarativeDirParser::TypeInfo> QDeclarativeDirParser::typeInfos() const
{
diff --git a/src/declarative/qml/qdeclarativedirparser_p.h b/src/declarative/qml/qdeclarativedirparser_p.h
index d31666cdb2..0f726b7060 100644
--- a/src/declarative/qml/qdeclarativedirparser_p.h
+++ b/src/declarative/qml/qdeclarativedirparser_p.h
@@ -109,7 +109,22 @@ public:
bool internal;
};
+ struct Script
+ {
+ Script()
+ : majorVersion(0), minorVersion(0) {}
+
+ Script(const QString &nameSpace, const QString &fileName, int majorVersion, int minorVersion)
+ : nameSpace(nameSpace), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion) {}
+
+ QString nameSpace;
+ QString fileName;
+ int majorVersion;
+ int minorVersion;
+ };
+
QList<Component> components() const;
+ QList<Script> scripts() const;
QList<Plugin> plugins() const;
#ifdef QT_CREATOR
@@ -134,6 +149,7 @@ private:
QString _source;
QString _filePathSouce;
QList<Component> _components;
+ QList<Script> _scripts;
QList<Plugin> _plugins;
#ifdef QT_CREATOR
QList<TypeInfo> _typeInfos;
@@ -142,6 +158,7 @@ private:
};
typedef QList<QDeclarativeDirParser::Component> QDeclarativeDirComponents;
+typedef QList<QDeclarativeDirParser::Script> QDeclarativeDirScripts;
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp
index 7c4c582f11..34527e6414 100644
--- a/src/declarative/qml/qdeclarativeimport.cpp
+++ b/src/declarative/qml/qdeclarativeimport.cpp
@@ -94,6 +94,7 @@ public:
int minversion;
bool isLibrary;
QDeclarativeDirComponents qmlDirComponents;
+ QDeclarativeDirScripts qmlDirScripts;
};
QList<Data> imports;
@@ -112,6 +113,7 @@ public:
bool importExtension(const QString &absoluteFilePath, const QString &uri,
QDeclarativeImportDatabase *database, QDeclarativeDirComponents* components,
+ QDeclarativeDirScripts *scripts,
QList<QDeclarativeError> *errors);
QString resolvedUri(const QString &dir_arg, QDeclarativeImportDatabase *database);
@@ -199,15 +201,17 @@ void QDeclarativeImports::populateCache(QDeclarativeTypeNameCache *cache, QDecla
++iter) {
const QDeclarativeImportedNamespace &set = *iter.value();
- QDeclarativeTypeNameCache::Import &import = cache->m_namedImports[iter.key()];
for (int ii = set.imports.count() - 1; ii >= 0; --ii) {
const QDeclarativeImportedNamespace::Data &data = set.imports.at(ii);
QDeclarativeTypeModule *module = QDeclarativeMetaType::typeModule(data.uri, data.majversion);
- if (module)
+ if (module) {
+ QDeclarativeTypeNameCache::Import &import = cache->m_namedImports[iter.key()];
import.modules.append(QDeclarativeTypeModuleVersion(module, data.minversion));
+ }
QDeclarativeMetaType::ModuleApi moduleApi = QDeclarativeMetaType::moduleApi(data.uri, data.majversion, data.minversion);
if (moduleApi.script || moduleApi.qobject) {
+ QDeclarativeTypeNameCache::Import &import = cache->m_namedImports[iter.key()];
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
import.moduleApi = ep->moduleApiInstance(moduleApi);
}
@@ -215,6 +219,44 @@ void QDeclarativeImports::populateCache(QDeclarativeTypeNameCache *cache, QDecla
}
}
+QList<QDeclarativeImports::ScriptReference> QDeclarativeImports::resolvedScripts() const
+{
+ QList<QDeclarativeImports::ScriptReference> scripts;
+
+ const QDeclarativeImportedNamespace &set = d->unqualifiedset;
+
+ for (int ii = set.imports.count() - 1; ii >= 0; --ii) {
+ const QDeclarativeImportedNamespace::Data &data = set.imports.at(ii);
+
+ foreach (const QDeclarativeDirParser::Script &script, data.qmlDirScripts) {
+ ScriptReference ref;
+ ref.nameSpace = script.nameSpace;
+ ref.location = QUrl(data.url).resolved(QUrl(script.fileName));
+ scripts.append(ref);
+ }
+ }
+
+ for (QHash<QString,QDeclarativeImportedNamespace* >::ConstIterator iter = d->set.constBegin();
+ iter != d->set.constEnd();
+ ++iter) {
+ const QDeclarativeImportedNamespace &set = *iter.value();
+
+ for (int ii = set.imports.count() - 1; ii >= 0; --ii) {
+ const QDeclarativeImportedNamespace::Data &data = set.imports.at(ii);
+
+ foreach (const QDeclarativeDirParser::Script &script, data.qmlDirScripts) {
+ ScriptReference ref;
+ ref.nameSpace = script.nameSpace;
+ ref.qualifier = iter.key();
+ ref.location = QUrl(data.url).resolved(QUrl(script.fileName));
+ scripts.append(ref);
+ }
+ }
+ }
+
+ return scripts;
+}
+
/*!
\internal
@@ -350,9 +392,11 @@ QDeclarativeImportsPrivate::~QDeclarativeImportsPrivate()
delete s;
}
-bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath, const QString &uri,
- QDeclarativeImportDatabase *database,
- QDeclarativeDirComponents* components, QList<QDeclarativeError> *errors)
+bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath, const QString &uri,
+ QDeclarativeImportDatabase *database,
+ QDeclarativeDirComponents* components,
+ QDeclarativeDirScripts* scripts,
+ QList<QDeclarativeError> *errors)
{
const QDeclarativeDirParser *qmldirParser = typeLoader->qmlDirParser(absoluteFilePath);
if (qmldirParser->hasError()) {
@@ -406,6 +450,8 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath
if (components)
*components = qmldirParser->components();
+ if (scripts)
+ *scripts = qmldirParser->scripts();
return true;
}
@@ -450,6 +496,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
static QLatin1Char Slash('/');
QDeclarativeDirComponents qmldircomponents = qmldircomponentsnetwork;
+ QDeclarativeDirScripts qmldirscripts;
QString uri = uri_arg;
QDeclarativeImportedNamespace *s;
if (prefix.isEmpty()) {
@@ -486,12 +533,14 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
else
url = QUrl::fromLocalFile(fi.absolutePath()).toString();
uri = resolvedUri(dir, database);
- if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errors))
+ if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
return false;
break;
}
}
+ // TODO: Should this search be omitted if found == true?
+
// step 2: search for extension with encoded version major
foreach (const QString &p, database->fileImportPath) {
dir = p+Slash+url;
@@ -508,7 +557,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
else
url = QUrl::fromLocalFile(fi.absolutePath()).toString();
uri = resolvedUri(dir, database);
- if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errors))
+ if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
return false;
break;
}
@@ -530,7 +579,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
else
url = QUrl::fromLocalFile(absolutePath).toString();
uri = resolvedUri(dir, database);
- if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errors))
+ if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
return false;
break;
}
@@ -540,7 +589,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
if (QDeclarativeMetaType::isModule(uri, vmaj, vmin))
versionFound = true;
- if (!versionFound && qmldircomponents.isEmpty()) {
+ if (!versionFound && qmldircomponents.isEmpty() && qmldirscripts.isEmpty()) {
if (errors) {
QDeclarativeError error; // we don't set the url or line or column as these will be set by the loader.
if (QDeclarativeMetaType::isAnyModule(uri))
@@ -570,7 +619,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
if (uri.endsWith(Slash))
uri.chop(1);
if (!typeLoader->absoluteFilePath(localFileOrQrc).isEmpty()) {
- if (!importExtension(localFileOrQrc,uri,database,&qmldircomponents,errors))
+ if (!importExtension(localFileOrQrc,uri,database,&qmldircomponents,&qmldirscripts,errors))
return false;
}
} else {
@@ -596,16 +645,18 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
url = resolveLocalUrl(base, url);
}
- if (!versionFound && vmaj > -1 && vmin > -1 && !qmldircomponents.isEmpty()) {
- QList<QDeclarativeDirParser::Component>::ConstIterator it = qmldircomponents.begin();
+ if (!versionFound && (vmaj > -1) && (vmin > -1) && !qmldircomponents.isEmpty()) {
int lowest_min = INT_MAX;
int highest_min = INT_MIN;
- for (; it != qmldircomponents.end(); ++it) {
- if (it->majorVersion == vmaj) {
- lowest_min = qMin(lowest_min, it->minorVersion);
- highest_min = qMax(highest_min, it->minorVersion);
+
+ QList<QDeclarativeDirParser::Component>::const_iterator cend = qmldircomponents.constEnd();
+ for (QList<QDeclarativeDirParser::Component>::const_iterator cit = qmldircomponents.constBegin(); cit != cend; ++cit) {
+ if (cit->majorVersion == vmaj) {
+ lowest_min = qMin(lowest_min, cit->minorVersion);
+ highest_min = qMax(highest_min, cit->minorVersion);
}
}
+
if (lowest_min > vmin || highest_min < vmin) {
if (errors) {
QDeclarativeError error; // we don't set the url or line or column information, as these will be set by the loader.
@@ -619,6 +670,35 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
if (!url.endsWith(Slash))
url += Slash;
+ QMap<QString, QDeclarativeDirParser::Script> scripts;
+
+ if (!qmldirscripts.isEmpty()) {
+ // Verify that we haven't imported these scripts already
+ QList<QDeclarativeImportedNamespace::Data>::const_iterator end = s->imports.constEnd();
+ for (QList<QDeclarativeImportedNamespace::Data>::const_iterator it = s->imports.constBegin(); it != end; ++it) {
+ if (it->uri == uri) {
+ QDeclarativeError error;
+ error.setDescription(QDeclarativeImportDatabase::tr("\"%1\" is ambiguous. Found in %2 and in %3").arg(uri).arg(url).arg(it->url));
+ errors->prepend(error);
+ return false;
+ }
+ }
+
+ QList<QDeclarativeDirParser::Script>::const_iterator send = qmldirscripts.constEnd();
+ for (QList<QDeclarativeDirParser::Script>::const_iterator sit = qmldirscripts.constBegin(); sit != send; ++sit) {
+ // Only include scripts that match our requested version
+ if (((vmaj == -1) || (sit->majorVersion == vmaj)) &&
+ ((vmin == -1) || (sit->minorVersion <= vmin))) {
+
+ // Load the highest version that matches
+ QMap<QString, QDeclarativeDirParser::Script>::iterator it = scripts.find(sit->nameSpace);
+ if (it == scripts.end() || (it->minorVersion < sit->minorVersion)) {
+ scripts.insert(sit->nameSpace, *sit);
+ }
+ }
+ }
+ }
+
QDeclarativeImportedNamespace::Data data;
data.uri = uri;
data.url = url;
@@ -626,6 +706,8 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
data.minversion = vmin;
data.isLibrary = importType == QDeclarativeScript::Import::Library;
data.qmlDirComponents = qmldircomponents;
+ data.qmlDirScripts = scripts.values();
+
s->imports.prepend(data);
return true;
diff --git a/src/declarative/qml/qdeclarativeimport_p.h b/src/declarative/qml/qdeclarativeimport_p.h
index 31e6676056..a9648c0413 100644
--- a/src/declarative/qml/qdeclarativeimport_p.h
+++ b/src/declarative/qml/qdeclarativeimport_p.h
@@ -101,6 +101,15 @@ public:
void populateCache(QDeclarativeTypeNameCache *cache, QDeclarativeEngine *) const;
+ struct ScriptReference
+ {
+ QString nameSpace;
+ QString qualifier;
+ QUrl location;
+ };
+
+ QList<ScriptReference> resolvedScripts() const;
+
private:
friend class QDeclarativeImportDatabase;
QDeclarativeImportsPrivate *d;
diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp
index 005e1750a0..bf319e5387 100644
--- a/src/declarative/qml/qdeclarativetypeloader.cpp
+++ b/src/declarative/qml/qdeclarativetypeloader.cpp
@@ -1427,6 +1427,11 @@ const QList<QDeclarativeTypeData::ScriptReference> &QDeclarativeTypeData::resolv
return m_scripts;
}
+const QSet<QString> &QDeclarativeTypeData::namespaces() const
+{
+ return m_namespaces;
+}
+
QDeclarativeCompiledData *QDeclarativeTypeData::compiledData() const
{
if (m_compiledData)
@@ -1648,6 +1653,27 @@ void QDeclarativeTypeData::resolveTypes()
}
}
+ // Add any imported scripts to our resolved set
+ foreach (const QDeclarativeImports::ScriptReference &script, m_imports.resolvedScripts())
+ {
+ QDeclarativeScriptBlob *blob = typeLoader()->getScript(script.location);
+ addDependency(blob);
+
+ ScriptReference ref;
+ //ref.location = ...
+ ref.qualifier = script.nameSpace;
+ if (!script.qualifier.isEmpty())
+ {
+ ref.qualifier.prepend(script.qualifier + QLatin1Char('.'));
+
+ // Add a reference to the enclosing namespace
+ m_namespaces.insert(script.qualifier);
+ }
+
+ ref.script = blob;
+ m_scripts << ref;
+ }
+
foreach (QDeclarativeScript::TypeReference *parserRef, scriptParser.referencedTypes()) {
TypeReference ref;
diff --git a/src/declarative/qml/qdeclarativetypeloader_p.h b/src/declarative/qml/qdeclarativetypeloader_p.h
index 36e8d93356..7b29f4b233 100644
--- a/src/declarative/qml/qdeclarativetypeloader_p.h
+++ b/src/declarative/qml/qdeclarativetypeloader_p.h
@@ -294,6 +294,7 @@ public:
const QList<TypeReference> &resolvedTypes() const;
const QList<ScriptReference> &resolvedScripts() const;
+ const QSet<QString> &namespaces() const;
QDeclarativeCompiledData *compiledData() const;
@@ -327,6 +328,8 @@ private:
QList<ScriptReference> m_scripts;
QList<QDeclarativeQmldirData *> m_qmldirs;
+ QSet<QString> m_namespaces;
+
QList<TypeReference> m_types;
bool m_typesResolved:1;
diff --git a/src/declarative/qml/qdeclarativetypenamecache.cpp b/src/declarative/qml/qdeclarativetypenamecache.cpp
index b183bca493..58ab1998c6 100644
--- a/src/declarative/qml/qdeclarativetypenamecache.cpp
+++ b/src/declarative/qml/qdeclarativetypenamecache.cpp
@@ -53,85 +53,71 @@ QDeclarativeTypeNameCache::~QDeclarativeTypeNameCache()
{
}
-void QDeclarativeTypeNameCache::add(const QHashedString &name, int importedScriptIndex)
+void QDeclarativeTypeNameCache::add(const QHashedString &name, int importedScriptIndex, const QHashedString &nameSpace)
{
+ Import import;
+ import.scriptIndex = importedScriptIndex;
+
+ if (nameSpace.length() != 0) {
+ Import *i = m_namedImports.value(nameSpace);
+ Q_ASSERT(i != 0);
+ m_namespacedImports[i].insert(name, import);
+ return;
+ }
+
if (m_namedImports.contains(name))
return;
- Import import;
- import.scriptIndex = importedScriptIndex;
m_namedImports.insert(name, import);
}
QDeclarativeTypeNameCache::Result QDeclarativeTypeNameCache::query(const QHashedStringRef &name)
{
- Import *i = m_namedImports.value(name);
- if (i) {
- if (i->scriptIndex != -1)
- return Result(i->scriptIndex);
- else
- return Result((const void *)i);
- }
+ Result result = query(m_namedImports, name);
- for (int ii = 0; ii < m_anonymousImports.count(); ++ii) {
- if (QDeclarativeType *type = m_anonymousImports.at(ii).type(name))
- return Result(type);
- }
+ if (!result.isValid())
+ result = typeSearch(m_anonymousImports, name);
- return Result();
+ return result;
}
QDeclarativeTypeNameCache::Result QDeclarativeTypeNameCache::query(const QHashedStringRef &name,
const void *importNamespace)
{
Q_ASSERT(importNamespace);
- Import *i = (Import *)importNamespace;
+ const Import *i = static_cast<const 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();
+ return typeSearch(i->modules, name);
}
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);
- }
+ Result result = query(m_namedImports, name);
- for (int ii = 0; ii < m_anonymousImports.count(); ++ii) {
- if (QDeclarativeType *type = m_anonymousImports.at(ii).type(name))
- return Result(type);
- }
+ if (!result.isValid())
+ result = typeSearch(m_anonymousImports, name);
- return Result();
+ return result;
}
QDeclarativeTypeNameCache::Result QDeclarativeTypeNameCache::query(const QHashedV8String &name, const void *importNamespace)
{
Q_ASSERT(importNamespace);
- Import *i = (Import *)importNamespace;
+ const Import *i = static_cast<const 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();
+ QMap<const Import *, QStringHash<Import> >::const_iterator it = m_namespacedImports.find(i);
+ if (it != m_namespacedImports.constEnd())
+ return query(*it, name);
+
+ return typeSearch(i->modules, name);
}
QDeclarativeMetaType::ModuleApiInstance *QDeclarativeTypeNameCache::moduleApi(const void *importNamespace)
{
Q_ASSERT(importNamespace);
- Import *i = (Import *)importNamespace;
+ const Import *i = static_cast<const Import *>(importNamespace);
Q_ASSERT(i->scriptIndex == -1);
return i->moduleApi;
diff --git a/src/declarative/qml/qdeclarativetypenamecache_p.h b/src/declarative/qml/qdeclarativetypenamecache_p.h
index 68f6044eef..8edc34d293 100644
--- a/src/declarative/qml/qdeclarativetypenamecache_p.h
+++ b/src/declarative/qml/qdeclarativetypenamecache_p.h
@@ -73,7 +73,7 @@ public:
inline bool isEmpty() const;
- void add(const QHashedString &, int);
+ void add(const QHashedString &name, int sciptIndex = -1, const QHashedString &nameSpace = QHashedString());
struct Result {
inline Result();
@@ -107,7 +107,35 @@ private:
int scriptIndex;
};
+ template<typename Key>
+ Result query(const QStringHash<Import> &imports, Key key)
+ {
+ Import *i = imports.value(key);
+ if (i) {
+ if (i->scriptIndex != -1) {
+ return Result(i->scriptIndex);
+ } else {
+ return Result(static_cast<const void *>(i));
+ }
+ }
+
+ return Result();
+ }
+
+ template<typename Key>
+ Result typeSearch(const QVector<QDeclarativeTypeModuleVersion> &modules, Key key)
+ {
+ QVector<QDeclarativeTypeModuleVersion>::const_iterator end = modules.constEnd();
+ for (QVector<QDeclarativeTypeModuleVersion>::const_iterator it = modules.constBegin(); it != end; ++it) {
+ if (QDeclarativeType *type = it->type(key))
+ return Result(type);
+ }
+
+ return Result();
+ }
+
QStringHash<Import> m_namedImports;
+ QMap<const Import *, QStringHash<Import> > m_namespacedImports;
QVector<QDeclarativeTypeModuleVersion> m_anonymousImports;
QDeclarativeEngine *engine;
diff --git a/src/declarative/qml/v8/qv8typewrapper.cpp b/src/declarative/qml/v8/qv8typewrapper.cpp
index 32db26324f..f1c095678b 100644
--- a/src/declarative/qml/v8/qv8typewrapper.cpp
+++ b/src/declarative/qml/v8/qv8typewrapper.cpp
@@ -196,9 +196,16 @@ v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property,
resource->importNamespace);
if (r.isValid()) {
- Q_ASSERT(r.type);
+ if (r.type) {
+ return v8engine->typeWrapper()->newObject(object, r.type, resource->mode);
+ } else if (r.scriptIndex != -1) {
+ int index = r.scriptIndex;
+ QDeclarativeContextData *context = v8engine->callingContext();
+ if (index < context->importedScripts.count())
+ return context->importedScripts.at(index);
+ }
- return v8engine->typeWrapper()->newObject(object, r.type, resource->mode);
+ return v8::Undefined();
} else if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = resource->typeNamespace->moduleApi(resource->importNamespace)) {
if (moduleApi->scriptCallback) {