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;
int startLine = l.tokenStartLine();
int startColumn = l.tokenStartColumn();
+ QQmlError importError;
+ importError.setLine(startLine);
+ importError.setColumn(startColumn);
+
token = l.lex();
CHECK_LINE;
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);
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());
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);
};
static QQmlScript::Object::ScriptBlock::Pragmas extractPragmas(QString &);
- static JavaScriptMetaData extractMetaData(QString &);
+ static JavaScriptMetaData extractMetaData(QString &, QQmlError *error);
// ### private:
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());
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;
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
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
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;
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()) {
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)
--- /dev/null
+.import "other.qml" as Other
+
+function foo() { return 'bar' }
--- /dev/null
+import QtQuick 2.0
+import "malformedFile.js" as JS
+
+Item {
+}
--- /dev/null
+.import "other.js" as other
+
+function foo() { return 'bar' }
--- /dev/null
+import QtQuick 2.0
+import "malformedFileQualifier.2.js" as JS
+
+Item {
+}
--- /dev/null
+.import "other.js" Other
+
+function foo() { return 'bar' }
--- /dev/null
+import QtQuick 2.0
+import "malformedFileQualifier.js" as JS
+
+Item {
+}
--- /dev/null
+.impooooort QtQuick 2.0 as QQ
+
+function foo() { return 'bar' }
--- /dev/null
+import QtQuick 2.0
+import "malformedImport.js" as JS
+
+Item {
+}
--- /dev/null
+.import QtQuick.++ 2.0 as QQ
+
+function foo() { return 'bar' }
--- /dev/null
+import QtQuick 2.0
+import "malformedModule.js" as JS
+
+Item {
+}
--- /dev/null
+.import QtQuick 2.0 as qq
+
+function foo() { return 'bar' }
--- /dev/null
+import QtQuick 2.0
+import "malformedModuleQualifier.2.js" as JS
+
+Item {
+}
--- /dev/null
+.import QtQuick 2.0 QQ
+
+function foo() { return 'bar' }
--- /dev/null
+import QtQuick 2.0
+import "malformedModuleQualifier.js" as JS
+
+Item {
+}
--- /dev/null
+.import QtQuick latest as QQ
+
+function foo() { return 'bar' }
--- /dev/null
+import QtQuick 2.0
+import "malformedModuleVersion.js" as JS
+
+Item {
+}
--- /dev/null
+.import "other.js"
+
+function foo() { return 'bar' }
--- /dev/null
+import QtQuick 2.0
+import "missingFileQualifier.js" as JS
+
+Item {
+}
--- /dev/null
+.import QtQuick 2.0
+
+function foo() { return 'bar' }
--- /dev/null
+import QtQuick 2.0
+import "missingModuleQualifier.js" as JS
+
+Item {
+}
--- /dev/null
+.import QtQuick as QQ
+
+function foo() { return 'bar' }
--- /dev/null
+import QtQuick 2.0
+import "missingModuleVersion.js" as JS
+
+Item {
+}
<< (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()