Improved error messages for malformed .import statements
authorMatthew Vogt <matthew.vogt@nokia.com>
Fri, 6 Jul 2012 03:04:53 +0000 (13:04 +1000)
committerQt by Nokia <qt-info@nokia.com>
Tue, 10 Jul 2012 23:49:59 +0000 (01:49 +0200)
Report errors in .import statements, rather than pass them through
to V8 to yield 'Syntax error'.

Task-number: QTBUG-24867
Change-Id: I111b3bd3d198e97f42b29591f61753e86295aeb2
Reviewed-by: Glenn Watson <glenn.watson@nokia.com>
29 files changed:
src/qml/qml/qqmlscript.cpp
src/qml/qml/qqmlscript_p.h
src/qml/qml/qqmltypeloader.cpp
src/qml/qml/qqmltypeloader_p.h
src/qml/qml/qqmlvme.cpp
tests/auto/qml/qmlmin/tst_qmlmin.cpp
tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFile.js [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFile.qml [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFileQualifier.2.js [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFileQualifier.2.qml [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFileQualifier.js [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFileQualifier.qml [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedImport.js [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedImport.qml [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModule.js [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModule.qml [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleQualifier.2.js [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleQualifier.2.qml [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleQualifier.js [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleQualifier.qml [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleVersion.js [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleVersion.qml [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/missingFileQualifier.js [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/missingFileQualifier.qml [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/missingModuleQualifier.js [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/missingModuleQualifier.qml [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/missingModuleVersion.js [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/data/jsimportfail/missingModuleVersion.qml [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp

index 469b5d5..a237f9a 100644 (file)
@@ -1476,8 +1476,10 @@ static inline bool isUriToken(int token)
     return false;
 }
 
-QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QString &script)
+QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QString &script, QQmlError *error)
 {
+    Q_ASSERT(error);
+
     JavaScriptMetaData rv;
 
     QQmlScript::Object::ScriptBlock::Pragmas &pragmas = rv.pragmas;
@@ -1499,6 +1501,10 @@ QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QStri
         int startLine = l.tokenStartLine();
         int startColumn = l.tokenStartColumn();
 
+        QQmlError importError;
+        importError.setLine(startLine);
+        importError.setColumn(startColumn);
+
         token = l.lex();
 
         CHECK_LINE;
@@ -1516,32 +1522,46 @@ QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QStri
 
                 QString file = l.tokenText();
 
-                if (!file.endsWith(js))
+                if (!file.endsWith(js)) {
+                    importError.setDescription(QCoreApplication::translate("QQmlParser","Imported file must be a script"));
+                    *error = importError;
                     return rv;
+                }
+
+                bool invalidImport = false;
 
                 token = l.lex();
 
-                CHECK_TOKEN(T_AS);
-                CHECK_LINE;
+                if ((token != QQmlJSGrammar::T_AS) || (l.tokenStartLine() != startLine)) {
+                    invalidImport = true;
+                } else {
+                    token = l.lex();
 
-                token = l.lex();
+                    if ((token != QQmlJSGrammar::T_IDENTIFIER) || (l.tokenStartLine() != startLine))
+                        invalidImport = true;
+                }
 
-                CHECK_TOKEN(T_IDENTIFIER);
-                CHECK_LINE;
+
+                if (invalidImport) {
+                    importError.setDescription(QCoreApplication::translate("QQmlParser","File import requires a qualifier"));
+                    *error = importError;
+                    return rv;
+                }
 
                 int endOffset = l.tokenLength() + l.tokenOffset();
 
                 QString importId = script.mid(l.tokenOffset(), l.tokenLength());
 
-                if (!importId.at(0).isUpper())
-                    return rv;
-
                 QQmlScript::LocationSpan location =
                     locationFromLexer(l, startLine, startColumn, startOffset);
 
                 token = l.lex();
-                if (l.tokenStartLine() == startLine)
+
+                if (!importId.at(0).isUpper() || (l.tokenStartLine() == startLine)) {
+                    importError.setDescription(QCoreApplication::translate("QQmlParser","Invalid import qualifier"));
+                    *error = importError;
                     return rv;
+                }
 
                 replaceWithSpace(script, startOffset, endOffset - startOffset);
 
@@ -1557,8 +1577,11 @@ QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QStri
                 QString uri;
 
                 while (true) {
-                    if (!isUriToken(token))
+                    if (!isUriToken(token)) {
+                        importError.setDescription(QCoreApplication::translate("QQmlParser","Invalid module URI"));
+                        *error = importError;
                         return rv;
+                    }
 
                     uri.append(l.tokenText());
 
@@ -1573,34 +1596,50 @@ QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QStri
                     CHECK_LINE;
                 }
 
-                CHECK_TOKEN(T_NUMERIC_LITERAL);
+                if (token != QQmlJSGrammar::T_NUMERIC_LITERAL) {
+                    importError.setDescription(QCoreApplication::translate("QQmlParser","Module import requires a version"));
+                    *error = importError;
+                    return rv;
+                }
+
                 int vmaj, vmin;
                 ProcessAST::extractVersion(QStringRef(&script, l.tokenOffset(), l.tokenLength()),
                                            &vmaj, &vmin);
 
+                bool invalidImport = false;
+
                 token = l.lex();
 
-                CHECK_TOKEN(T_AS);
-                CHECK_LINE;
+                if ((token != QQmlJSGrammar::T_AS) || (l.tokenStartLine() != startLine)) {
+                    invalidImport = true;
+                } else {
+                    token = l.lex();
 
-                token = l.lex();
+                    if ((token != QQmlJSGrammar::T_IDENTIFIER) || (l.tokenStartLine() != startLine))
+                        invalidImport = true;
+                }
 
-                CHECK_TOKEN(T_IDENTIFIER);
-                CHECK_LINE;
+
+                if (invalidImport) {
+                    importError.setDescription(QCoreApplication::translate("QQmlParser","Module import requires a qualifier"));
+                    *error = importError;
+                    return rv;
+                }
 
                 int endOffset = l.tokenLength() + l.tokenOffset();
 
                 QString importId = script.mid(l.tokenOffset(), l.tokenLength());
 
-                if (!importId.at(0).isUpper())
-                    return rv;
-
                 QQmlScript::LocationSpan location =
                     locationFromLexer(l, startLine, startColumn, startOffset);
 
                 token = l.lex();
-                if (l.tokenStartLine() == startLine)
+
+                if (!importId.at(0).isUpper() || (l.tokenStartLine() == startLine)) {
+                    importError.setDescription(QCoreApplication::translate("QQmlParser","Invalid import qualifier"));
+                    *error = importError;
                     return rv;
+                }
 
                 replaceWithSpace(script, startOffset, endOffset - startOffset);
 
index 718faa3..e08afa8 100644 (file)
@@ -490,7 +490,7 @@ public:
     };
 
     static QQmlScript::Object::ScriptBlock::Pragmas extractPragmas(QString &);
-    static JavaScriptMetaData extractMetaData(QString &);
+    static JavaScriptMetaData extractMetaData(QString &, QQmlError *error);
 
 
 // ### private:
index e94d02c..3a24625 100644 (file)
@@ -1969,8 +1969,17 @@ void QQmlScriptBlob::dataReceived(const Data &data)
 
     m_source = QString::fromUtf8(data.data(), data.size());
 
+    m_scriptData = new QQmlScriptData();
+    m_scriptData->url = finalUrl();
+    m_scriptData->urlString = finalUrlString();
+
+    QQmlError metaDataError;
     QQmlScript::Parser::JavaScriptMetaData metadata =
-        QQmlScript::Parser::extractMetaData(m_source);
+        QQmlScript::Parser::extractMetaData(m_source, &metaDataError);
+    if (metaDataError.isValid()) {
+        metaDataError.setUrl(finalUrl());
+        m_scriptData->setError(metaDataError);
+    }
 
     m_imports.setBaseUrl(finalUrl(), finalUrlString());
 
@@ -2052,9 +2061,7 @@ void QQmlScriptBlob::done()
         return;
 
     QQmlEngine *engine = typeLoader()->engine();
-    m_scriptData = new QQmlScriptData();
-    m_scriptData->url = finalUrl();
-    m_scriptData->urlString = finalUrlString();
+
     m_scriptData->importCache = new QQmlTypeNameCache();
 
     QSet<QString> ns;
index b16421a..c05b437 100644 (file)
@@ -437,6 +437,10 @@ public:
     bool isInitialized() const { return hasEngine(); }
     void initialize(QQmlEngine *);
 
+    bool hasError() const { return m_error.isValid(); }
+    void setError(const QQmlError &error) { m_error = error; }
+    QQmlError error() const { return m_error; }
+
 protected:
     virtual void clear(); // From QQmlCleanup
 
@@ -448,6 +452,7 @@ private:
     QByteArray m_programSource;
     v8::Persistent<v8::Script> m_program;
     v8::Persistent<v8::Object> m_value;
+    QQmlError m_error;
 };
 
 class Q_AUTOTEST_EXPORT QQmlScriptBlob : public QQmlDataBlob
index 7a6d008..b33f7ee 100644 (file)
@@ -1160,10 +1160,17 @@ v8::Persistent<v8::Object> QQmlVME::run(QQmlContextData *parentCtxt, QQmlScriptD
     if (script->m_loaded)
         return qPersistentNew<v8::Object>(script->m_value);
 
+    v8::Persistent<v8::Object> rv;
+
     Q_ASSERT(parentCtxt && parentCtxt->engine);
     QQmlEnginePrivate *ep = QQmlEnginePrivate::get(parentCtxt->engine);
     QV8Engine *v8engine = ep->v8engine();
 
+    if (script->hasError()) {
+        ep->warning(script->error());
+        return rv;
+    }
+
     bool shared = script->pragmas & QQmlScript::Object::ScriptBlock::Shared;
 
     QQmlContextData *effectiveCtxt = parentCtxt;
@@ -1222,8 +1229,6 @@ v8::Persistent<v8::Object> QQmlVME::run(QQmlContextData *parentCtxt, QQmlScriptD
         Q_ASSERT(try_catch.HasCaught());
     }
 
-    v8::Persistent<v8::Object> rv;
-    
     if (try_catch.HasCaught()) {
         v8::Local<v8::Message> message = try_catch.Message();
         if (!message.IsEmpty()) {
index 6f0b2e4..dcdc895 100644 (file)
@@ -110,6 +110,14 @@ void tst_qmlmin::initTestCase()
     invalidFiles << "tests/auto/qml/qqmlecmascript/data/qtbug_22843.library.js";
     invalidFiles << "tests/auto/qml/qquickworkerscript/data/script_error_onLoad.js";
     invalidFiles << "tests/auto/qml/parserstress/tests/ecma_3/Unicode/regress-352044-02-n.js";
+    invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFileQualifier.js";
+    invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedImport.js";
+    invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModule.js";
+    invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleQualifier.js";
+    invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleVersion.js";
+    invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/missingFileQualifier.js";
+    invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/missingModuleQualifier.js";
+    invalidFiles << "tests/auto/qml/qqmlecmascript/data/jsimportfail/missingModuleVersion.js";
 }
 
 QStringList tst_qmlmin::findFiles(const QDir &d)
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFile.js b/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFile.js
new file mode 100644 (file)
index 0000000..cd06f25
--- /dev/null
@@ -0,0 +1,3 @@
+.import "other.qml" as Other
+
+function foo() { return 'bar' }
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFile.qml b/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFile.qml
new file mode 100644 (file)
index 0000000..d9ccc42
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+import "malformedFile.js" as JS
+
+Item {
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFileQualifier.2.js b/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFileQualifier.2.js
new file mode 100644 (file)
index 0000000..96ec836
--- /dev/null
@@ -0,0 +1,3 @@
+.import "other.js" as other
+
+function foo() { return 'bar' }
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFileQualifier.2.qml b/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFileQualifier.2.qml
new file mode 100644 (file)
index 0000000..88c3af7
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+import "malformedFileQualifier.2.js" as JS
+
+Item {
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFileQualifier.js b/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFileQualifier.js
new file mode 100644 (file)
index 0000000..2eb7afc
--- /dev/null
@@ -0,0 +1,3 @@
+.import "other.js" Other
+
+function foo() { return 'bar' }
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFileQualifier.qml b/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedFileQualifier.qml
new file mode 100644 (file)
index 0000000..928e883
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+import "malformedFileQualifier.js" as JS
+
+Item {
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedImport.js b/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedImport.js
new file mode 100644 (file)
index 0000000..c56c822
--- /dev/null
@@ -0,0 +1,3 @@
+.impooooort QtQuick 2.0 as QQ
+
+function foo() { return 'bar' }
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedImport.qml b/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedImport.qml
new file mode 100644 (file)
index 0000000..84f62a3
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+import "malformedImport.js" as JS
+
+Item {
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModule.js b/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModule.js
new file mode 100644 (file)
index 0000000..6affc4e
--- /dev/null
@@ -0,0 +1,3 @@
+.import QtQuick.++ 2.0 as QQ
+
+function foo() { return 'bar' }
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModule.qml b/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModule.qml
new file mode 100644 (file)
index 0000000..1170594
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+import "malformedModule.js" as JS
+
+Item {
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleQualifier.2.js b/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleQualifier.2.js
new file mode 100644 (file)
index 0000000..eced64f
--- /dev/null
@@ -0,0 +1,3 @@
+.import QtQuick 2.0 as qq
+
+function foo() { return 'bar' }
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleQualifier.2.qml b/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleQualifier.2.qml
new file mode 100644 (file)
index 0000000..e65eb5c
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+import "malformedModuleQualifier.2.js" as JS
+
+Item {
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleQualifier.js b/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleQualifier.js
new file mode 100644 (file)
index 0000000..f1116fb
--- /dev/null
@@ -0,0 +1,3 @@
+.import QtQuick 2.0 QQ
+
+function foo() { return 'bar' }
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleQualifier.qml b/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleQualifier.qml
new file mode 100644 (file)
index 0000000..68cb61c
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+import "malformedModuleQualifier.js" as JS
+
+Item {
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleVersion.js b/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleVersion.js
new file mode 100644 (file)
index 0000000..8ecc977
--- /dev/null
@@ -0,0 +1,3 @@
+.import QtQuick latest as QQ
+
+function foo() { return 'bar' }
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleVersion.qml b/tests/auto/qml/qqmlecmascript/data/jsimportfail/malformedModuleVersion.qml
new file mode 100644 (file)
index 0000000..dc3b8d8
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+import "malformedModuleVersion.js" as JS
+
+Item {
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/missingFileQualifier.js b/tests/auto/qml/qqmlecmascript/data/jsimportfail/missingFileQualifier.js
new file mode 100644 (file)
index 0000000..a21f3b1
--- /dev/null
@@ -0,0 +1,3 @@
+.import "other.js"
+
+function foo() { return 'bar' }
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/missingFileQualifier.qml b/tests/auto/qml/qqmlecmascript/data/jsimportfail/missingFileQualifier.qml
new file mode 100644 (file)
index 0000000..f600e4a
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+import "missingFileQualifier.js" as JS
+
+Item {
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/missingModuleQualifier.js b/tests/auto/qml/qqmlecmascript/data/jsimportfail/missingModuleQualifier.js
new file mode 100644 (file)
index 0000000..eb71776
--- /dev/null
@@ -0,0 +1,3 @@
+.import QtQuick 2.0
+
+function foo() { return 'bar' }
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/missingModuleQualifier.qml b/tests/auto/qml/qqmlecmascript/data/jsimportfail/missingModuleQualifier.qml
new file mode 100644 (file)
index 0000000..b23d6c1
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+import "missingModuleQualifier.js" as JS
+
+Item {
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/missingModuleVersion.js b/tests/auto/qml/qqmlecmascript/data/jsimportfail/missingModuleVersion.js
new file mode 100644 (file)
index 0000000..0ad75fa
--- /dev/null
@@ -0,0 +1,3 @@
+.import QtQuick as QQ
+
+function foo() { return 'bar' }
diff --git a/tests/auto/qml/qqmlecmascript/data/jsimportfail/missingModuleVersion.qml b/tests/auto/qml/qqmlecmascript/data/jsimportfail/missingModuleVersion.qml
new file mode 100644 (file)
index 0000000..e818c8e
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+import "missingModuleVersion.js" as JS
+
+Item {
+}
index 39174f0..66ae27e 100644 (file)
@@ -3783,6 +3783,83 @@ void tst_qqmlecmascript::importScripts_data()
             << (QVariantList() << QVariant(QString("Hello"))
                                << QVariant(QString("Hello"))
                                << QVariant(QString("Hello")));
+
+    QTest::newRow("malformed import statement")
+            << testFileUrl("jsimportfail/malformedImport.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/malformedImport.js").toString() + QLatin1String(":1: SyntaxError: Unexpected token ."))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("malformed file name")
+            << testFileUrl("jsimportfail/malformedFile.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/malformedFile.js").toString() + QLatin1String(":0:1: Imported file must be a script"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("missing file qualifier")
+            << testFileUrl("jsimportfail/missingFileQualifier.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/missingFileQualifier.js").toString() + QLatin1String(":0:1: File import requires a qualifier"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("malformed file qualifier")
+            << testFileUrl("jsimportfail/malformedFileQualifier.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/malformedFileQualifier.js").toString() + QLatin1String(":0:1: File import requires a qualifier"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("malformed module qualifier 2")
+            << testFileUrl("jsimportfail/malformedFileQualifier.2.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/malformedFileQualifier.2.js").toString() + QLatin1String(":0:1: Invalid import qualifier"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("malformed module uri")
+            << testFileUrl("jsimportfail/malformedModule.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/malformedModule.js").toString() + QLatin1String(":0:1: Invalid module URI"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("missing module version")
+            << testFileUrl("jsimportfail/missingModuleVersion.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/missingModuleVersion.js").toString() + QLatin1String(":0:1: Module import requires a version"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("malformed module version")
+            << testFileUrl("jsimportfail/malformedModuleVersion.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/malformedModuleVersion.js").toString() + QLatin1String(":0:1: Module import requires a version"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("missing module qualifier")
+            << testFileUrl("jsimportfail/missingModuleQualifier.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/missingModuleQualifier.js").toString() + QLatin1String(":0:1: Module import requires a qualifier"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("malformed module qualifier")
+            << testFileUrl("jsimportfail/malformedModuleQualifier.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/malformedModuleQualifier.js").toString() + QLatin1String(":0:1: Module import requires a qualifier"))
+            << QStringList()
+            << QVariantList();
+
+    QTest::newRow("malformed module qualifier 2")
+            << testFileUrl("jsimportfail/malformedModuleQualifier.2.qml")
+            << QString()
+            << (QStringList() << testFileUrl("jsimportfail/malformedModuleQualifier.2.js").toString() + QLatin1String(":0:1: Invalid import qualifier"))
+            << QStringList()
+            << QVariantList();
 }
 
 void tst_qqmlecmascript::importScripts()