Ensure JS files imported inside modules work correctly
When a module exports functionality provided by a script, ensure that imported script modules inside that script resolve correctly. Task-number: QTBUG-24596 Change-Id: I3885dcc56946423f0d7cf00afdcdfaa0cb11967a Reviewed-by: Chris Adams <christopher.adams@nokia.com>
This commit is contained in:
parent
601c7383ab
commit
c5cd60a96d
|
@ -295,4 +295,18 @@ QList<QQmlDirParser::TypeInfo> QQmlDirParser::typeInfos() const
|
|||
}
|
||||
#endif
|
||||
|
||||
QDebug &operator<< (QDebug &debug, const QQmlDirParser::Component &component)
|
||||
{
|
||||
return debug << qPrintable(QString("{%1 %2.%3}").arg(component.typeName)
|
||||
.arg(component.majorVersion)
|
||||
.arg(component.minorVersion));
|
||||
}
|
||||
|
||||
QDebug &operator<< (QDebug &debug, const QQmlDirParser::Script &script)
|
||||
{
|
||||
return debug << qPrintable(QString("{%1 %2.%3}").arg(script.nameSpace)
|
||||
.arg(script.majorVersion)
|
||||
.arg(script.minorVersion));
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
@ -160,6 +161,8 @@ private:
|
|||
typedef QList<QQmlDirParser::Component> QQmlDirComponents;
|
||||
typedef QList<QQmlDirParser::Script> QQmlDirScripts;
|
||||
|
||||
QDebug &operator<< (QDebug &, const QQmlDirParser::Component &);
|
||||
QDebug &operator<< (QDebug &, const QQmlDirParser::Script &);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ public:
|
|||
QList<QQmlError> *errors);
|
||||
|
||||
QString resolvedUri(const QString &dir_arg, QQmlImportDatabase *database);
|
||||
bool add(const QQmlDirComponents &qmldircomponentsnetwork,
|
||||
QString add(const QQmlDirComponents &qmldircomponentsnetwork,
|
||||
const QString& uri_arg, const QString& prefix,
|
||||
int vmaj, int vmin, QQmlScript::Import::Type importType,
|
||||
QQmlImportDatabase *database, QList<QQmlError> *errors);
|
||||
|
@ -493,7 +493,7 @@ QString QQmlImportsPrivate::resolvedUri(const QString &dir_arg, QQmlImportDataba
|
|||
return stableRelativePath;
|
||||
}
|
||||
|
||||
bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
|
||||
QString QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
|
||||
const QString& uri_arg, const QString& prefix, int vmaj, int vmin,
|
||||
QQmlScript::Import::Type importType,
|
||||
QQmlImportDatabase *database, QList<QQmlError> *errors)
|
||||
|
@ -540,7 +540,7 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
|
|||
url = QUrl::fromLocalFile(fi.absolutePath()).toString();
|
||||
uri = resolvedUri(dir, database);
|
||||
if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
|
||||
return false;
|
||||
return QString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -564,7 +564,7 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
|
|||
url = QUrl::fromLocalFile(fi.absolutePath()).toString();
|
||||
uri = resolvedUri(dir, database);
|
||||
if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
|
||||
return false;
|
||||
return QString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -586,7 +586,7 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
|
|||
url = QUrl::fromLocalFile(absolutePath).toString();
|
||||
uri = resolvedUri(dir, database);
|
||||
if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
|
||||
return false;
|
||||
return QString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -604,7 +604,7 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
|
|||
error.setDescription(QQmlImportDatabase::tr("module \"%1\" is not installed").arg(uri_arg));
|
||||
errors->prepend(error);
|
||||
}
|
||||
return false;
|
||||
return QString();
|
||||
}
|
||||
} else {
|
||||
if (importType == QQmlScript::Import::File && qmldircomponents.isEmpty()) {
|
||||
|
@ -619,14 +619,14 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
|
|||
error.setUrl(QUrl(importUrl));
|
||||
errors->prepend(error);
|
||||
}
|
||||
return false; // local import dirs must exist
|
||||
return QString(); // local import dirs must exist
|
||||
}
|
||||
uri = resolvedUri(dir, database);
|
||||
if (uri.endsWith(Slash))
|
||||
uri.chop(1);
|
||||
if (!typeLoader->absoluteFilePath(localFileOrQrc).isEmpty()) {
|
||||
if (!importExtension(localFileOrQrc,uri,database,&qmldircomponents,&qmldirscripts,errors))
|
||||
return false;
|
||||
return QString();
|
||||
}
|
||||
} else {
|
||||
if (prefix.isEmpty()) {
|
||||
|
@ -642,7 +642,7 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
|
|||
error.setUrl(QUrl(importUrl));
|
||||
errors->prepend(error);
|
||||
}
|
||||
return false;
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -669,7 +669,7 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
|
|||
error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin));
|
||||
errors->prepend(error);
|
||||
}
|
||||
return false;
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -686,7 +686,7 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
|
|||
QQmlError error;
|
||||
error.setDescription(QQmlImportDatabase::tr("\"%1\" is ambiguous. Found in %2 and in %3").arg(uri).arg(url).arg(it->url));
|
||||
errors->prepend(error);
|
||||
return false;
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -716,7 +716,7 @@ bool QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork,
|
|||
|
||||
s->imports.prepend(data);
|
||||
|
||||
return true;
|
||||
return data.url;
|
||||
}
|
||||
|
||||
bool QQmlImportsPrivate::find(const QString& type, int *vmajor, int *vminor, QQmlType** type_return,
|
||||
|
@ -874,9 +874,11 @@ QQmlImportDatabase::~QQmlImportDatabase()
|
|||
The \a prefix may be empty, in which case the import location is considered for
|
||||
unqualified types.
|
||||
|
||||
Returns the resolved URL of the import on success.
|
||||
|
||||
The base URL must already have been set with Import::setBaseUrl().
|
||||
*/
|
||||
bool QQmlImports::addImport(QQmlImportDatabase *importDb,
|
||||
QString QQmlImports::addImport(QQmlImportDatabase *importDb,
|
||||
const QString& uri, const QString& prefix, int vmaj, int vmin,
|
||||
QQmlScript::Import::Type importType,
|
||||
const QQmlDirComponents &qmldircomponentsnetwork,
|
||||
|
|
|
@ -93,7 +93,7 @@ public:
|
|||
QQmlType** type_return, QString* url_return,
|
||||
int *version_major, int *version_minor) const;
|
||||
|
||||
bool addImport(QQmlImportDatabase *,
|
||||
QString addImport(QQmlImportDatabase *,
|
||||
const QString& uri, const QString& prefix, int vmaj, int vmin,
|
||||
QQmlScript::Import::Type importType,
|
||||
const QQmlDirComponents &qmldircomponentsnetwork,
|
||||
|
|
|
@ -1558,7 +1558,6 @@ void QQmlTypeData::dataReceived(const QByteArray &data)
|
|||
ref.qualifier = import.qualifier;
|
||||
ref.script = blob;
|
||||
m_scripts << ref;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1657,8 +1656,8 @@ void QQmlTypeData::resolveTypes()
|
|||
import.extractVersion(&vmaj, &vmin);
|
||||
|
||||
QList<QQmlError> errors;
|
||||
if (!m_imports.addImport(importDatabase, import.uri, import.qualifier,
|
||||
vmaj, vmin, import.type, qmldircomponentsnetwork, &errors)) {
|
||||
if (m_imports.addImport(importDatabase, import.uri, import.qualifier, vmaj, vmin,
|
||||
import.type, qmldircomponentsnetwork, &errors).isNull()) {
|
||||
QQmlError error;
|
||||
if (errors.size()) {
|
||||
error = errors.takeFirst();
|
||||
|
@ -1859,8 +1858,9 @@ void QQmlScriptBlob::dataReceived(const QByteArray &data)
|
|||
import.extractVersion(&vmaj, &vmin);
|
||||
|
||||
QList<QQmlError> errors;
|
||||
if (!m_imports.addImport(importDatabase, import.uri, import.qualifier, vmaj, vmin,
|
||||
import.type, QQmlDirComponents(), &errors)) {
|
||||
QString importUrl = m_imports.addImport(importDatabase, import.uri, import.qualifier, vmaj, vmin,
|
||||
import.type, QQmlDirComponents(), &errors);
|
||||
if (importUrl.isNull()) {
|
||||
QQmlError error = errors.takeFirst();
|
||||
// description should be set by addImport().
|
||||
error.setUrl(m_imports.baseUrl());
|
||||
|
@ -1871,6 +1871,22 @@ void QQmlScriptBlob::dataReceived(const QByteArray &data)
|
|||
setError(errors);
|
||||
return;
|
||||
}
|
||||
|
||||
// Does this library contain any scripts?
|
||||
QUrl libraryUrl(importUrl);
|
||||
const QQmlDirParser *dirParser = typeLoader()->qmlDirParser(libraryUrl.path() + QLatin1String("qmldir"));
|
||||
foreach (const QQmlDirParser::Script &script, dirParser->scripts()) {
|
||||
QUrl scriptUrl = libraryUrl.resolved(QUrl(script.fileName));
|
||||
QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
|
||||
addDependency(blob);
|
||||
|
||||
ScriptReference ref;
|
||||
ref.location = import.location.start;
|
||||
ref.qualifier = script.nameSpace;
|
||||
ref.nameSpace = import.qualifier;
|
||||
ref.script = blob;
|
||||
m_scripts << ref;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1902,11 +1918,20 @@ void QQmlScriptBlob::done()
|
|||
m_scriptData->urlString = finalUrlString();
|
||||
m_scriptData->importCache = new QQmlTypeNameCache();
|
||||
|
||||
for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) {
|
||||
const ScriptReference &script = m_scripts.at(ii);
|
||||
QSet<QString> ns;
|
||||
|
||||
for (int scriptIndex = 0; !isError() && scriptIndex < m_scripts.count(); ++scriptIndex) {
|
||||
const ScriptReference &script = m_scripts.at(scriptIndex);
|
||||
|
||||
m_scriptData->scripts.append(script.script);
|
||||
m_scriptData->importCache->add(script.qualifier, ii);
|
||||
|
||||
if (!script.nameSpace.isNull()) {
|
||||
if (!ns.contains(script.nameSpace)) {
|
||||
ns.insert(script.nameSpace);
|
||||
m_scriptData->importCache->add(script.nameSpace);
|
||||
}
|
||||
}
|
||||
m_scriptData->importCache->add(script.qualifier, scriptIndex, script.nameSpace);
|
||||
}
|
||||
|
||||
m_imports.populateCache(m_scriptData->importCache, engine);
|
||||
|
|
|
@ -390,6 +390,7 @@ public:
|
|||
|
||||
QQmlScript::Location location;
|
||||
QString qualifier;
|
||||
QString nameSpace;
|
||||
QQmlScriptBlob *script;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
import QtQuick 2.0
|
||||
|
||||
import com.nokia.JsModule 1.0
|
||||
import com.nokia.JsModule 1.0 as RenamedModule
|
||||
import "testJsModuleImport.js" as TestJsModuleImport
|
||||
|
||||
QtObject {
|
||||
id: testQtObject
|
||||
|
||||
property string importedScriptStringValue: ScriptAPI.greeting();
|
||||
property string renamedScriptStringValue: RenamedModule.ScriptAPI.greeting();
|
||||
property string reimportedScriptStringValue: TestJsModuleImport.importedValue();
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
.import com.nokia.JsModule 1.0 as JsModule
|
||||
|
||||
function importedValue() {
|
||||
return JsModule.ScriptAPI.greeting();
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
var major = 1
|
||||
var minor = 0
|
||||
|
||||
function greeting() { return "Hello" }
|
||||
|
|
@ -0,0 +1 @@
|
|||
ScriptAPI 1.0 ScriptAPI.js
|
|
@ -254,6 +254,9 @@ void tst_qqmlecmascript::initTestCase()
|
|||
{
|
||||
QQmlDataTest::initTestCase();
|
||||
registerTypes();
|
||||
|
||||
QString dataDir(dataDirectory() + QLatin1Char('/') + QLatin1String("lib"));
|
||||
engine.addImportPath(dataDir);
|
||||
}
|
||||
|
||||
void tst_qqmlecmascript::assignBasicTypes()
|
||||
|
@ -3298,6 +3301,17 @@ void tst_qqmlecmascript::importScripts_data()
|
|||
<< QStringList()
|
||||
<< (QStringList() << QLatin1String("testValue"))
|
||||
<< (QVariantList() << QVariant(20));
|
||||
|
||||
QTest::newRow("import module which exports a script")
|
||||
<< testFileUrl("jsimport/testJsImport.qml")
|
||||
<< QString()
|
||||
<< QStringList()
|
||||
<< (QStringList() << QLatin1String("importedScriptStringValue")
|
||||
<< QLatin1String("renamedScriptStringValue")
|
||||
<< QLatin1String("reimportedScriptStringValue"))
|
||||
<< (QVariantList() << QVariant(QString("Hello"))
|
||||
<< QVariant(QString("Hello"))
|
||||
<< QVariant(QString("Hello")));
|
||||
}
|
||||
|
||||
void tst_qqmlecmascript::importScripts()
|
||||
|
|
Loading…
Reference in New Issue