diff options
author | Matthew Vogt <matthew.vogt@nokia.com> | 2012-01-18 17:12:25 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-01-24 23:18:34 +0100 |
commit | 149f6afe321ce59aebe4ce2f9dddd1881d0ac22b (patch) | |
tree | 45233b8c808ed553051799b38a6b1e73898db2e1 /src/declarative | |
parent | 49212ef6d8934a023e6d0a7b778ec25605a8be7a (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.h | 13 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativecompiler.cpp | 27 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativedirparser.cpp | 19 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativedirparser_p.h | 17 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativeimport.cpp | 114 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativeimport_p.h | 9 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativetypeloader.cpp | 26 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativetypeloader_p.h | 3 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativetypenamecache.cpp | 70 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativetypenamecache_p.h | 30 | ||||
-rw-r--r-- | src/declarative/qml/v8/qv8typewrapper.cpp | 11 |
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) { |