aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qv4codegen.cpp5
-rw-r--r--src/qml/compiler/qv4codegen_p.h3
-rw-r--r--src/qml/jsruntime/qv4script.cpp95
-rw-r--r--src/qml/jsruntime/qv4script_p.h6
-rw-r--r--src/qml/qml/qqmltypeloader.cpp24
-rw-r--r--src/qml/qml/qqmltypeloader_p.h7
-rw-r--r--src/qml/qml/qqmlvme.cpp32
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp63
8 files changed, 175 insertions, 60 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 0f60bdc9f3..43756a6f35 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -2577,6 +2577,11 @@ void Codegen::throwReferenceError(const SourceLocation &loc, const QString &deta
_errors << error;
}
+QList<QQmlError> Codegen::errors() const
+{
+ return _errors;
+}
+
void RuntimeCodegen::throwSyntaxError(const AST::SourceLocation &loc, const QString &detail)
{
context->throwSyntaxError(detail, _module->fileName, loc.startLine, loc.startColumn);
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index d03f91b654..ea32b5b349 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -414,7 +414,8 @@ protected:
virtual void throwSyntaxError(const AST::SourceLocation &loc, const QString &detail);
virtual void throwReferenceError(const AST::SourceLocation &loc, const QString &detail);
- QList<QQmlError> errors();
+public:
+ QList<QQmlError> errors() const;
protected:
Result _expr;
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index c2d35d5926..2350224c32 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -142,6 +142,22 @@ struct CompilationUnitHolder : public QV4::Object
DEFINE_MANAGED_VTABLE(CompilationUnitHolder);
+Script::Script(ExecutionEngine *v4, ObjectRef qml, CompiledData::CompilationUnit *compilationUnit)
+ : line(0), column(0), scope(v4->rootContext), strictMode(false), inheritContext(true), parsed(false)
+ , qml(qml.asReturnedValue()), vmFunction(0), parseAsBinding(true)
+{
+ parsed = true;
+
+ if (compilationUnit) {
+ vmFunction = compilationUnit->linkToEngine(v4);
+ Q_ASSERT(vmFunction);
+ Scope valueScope(v4);
+ ScopedValue holder(valueScope, Value::fromObject(new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit)));
+ compilationUnitHolder = holder;
+ } else
+ vmFunction = 0;
+}
+
Script::~Script()
{
}
@@ -264,6 +280,85 @@ Function *Script::function()
return vmFunction;
}
+struct PrecompilingCodeGen : public QQmlJS::Codegen
+{
+ struct CompileError {};
+
+ PrecompilingCodeGen(bool strict)
+ : QQmlJS::Codegen(strict)
+ {}
+
+ virtual void throwSyntaxError(const QQmlJS::AST::SourceLocation &loc, const QString &detail)
+ {
+ QQmlJS::Codegen::throwSyntaxError(loc, detail);
+ throw CompileError();
+ }
+
+ virtual void throwReferenceError(const QQmlJS::AST::SourceLocation &loc, const QString &detail)
+ {
+ QQmlJS::Codegen::throwReferenceError(loc, detail);
+ throw CompileError();
+ }
+};
+
+CompiledData::CompilationUnit *Script::precompile(ExecutionEngine *engine, const QUrl &url, const QString &source, bool parseAsBinding, QList<QQmlError> *reportedErrors)
+{
+ using namespace QQmlJS;
+ using namespace QQmlJS::AST;
+
+ QQmlJS::V4IR::Module module;
+
+ QQmlJS::Engine ee;
+ QQmlJS::Lexer lexer(&ee);
+ lexer.setCode(source, /*line*/1, /*qml mode*/true);
+ QQmlJS::Parser parser(&ee);
+
+ parser.parseProgram();
+
+ QList<QQmlError> errors;
+
+ foreach (const QQmlJS::DiagnosticMessage &m, parser.diagnosticMessages()) {
+ if (m.isWarning()) {
+ qWarning("%s:%d : %s", qPrintable(url.toString()), m.loc.startLine, qPrintable(m.message));
+ continue;
+ }
+
+ QQmlError error;
+ error.setUrl(url);
+ error.setDescription(m.message);
+ error.setLine(m.loc.startLine);
+ error.setColumn(m.loc.startColumn);
+ errors << error;
+ }
+
+ if (!errors.isEmpty()) {
+ if (reportedErrors)
+ *reportedErrors << errors;
+ return 0;
+ }
+
+ Program *program = AST::cast<Program *>(parser.rootNode());
+ if (!program) {
+ // if parsing was successful, and we have no program, then
+ // we're done...:
+ return 0;
+ }
+
+ PrecompilingCodeGen cg(/*strict mode*/false);
+ try {
+ cg.generateFromProgram(url.toString(), source, program, &module, parseAsBinding ? QQmlJS::Codegen::QmlBinding : QQmlJS::Codegen::GlobalCode);
+ } catch (const PrecompilingCodeGen::CompileError &) {
+ if (reportedErrors)
+ *reportedErrors << cg.errors();
+ return 0;
+ }
+
+ Compiler::JSUnitGenerator jsGenerator(&module);
+ QScopedPointer<QQmlJS::EvalInstructionSelection> isel(engine->iselFactory->create(engine->executableAllocator, &module, &jsGenerator));
+ isel->setUseFastLookups(false);
+ return isel->compile();
+}
+
ReturnedValue Script::qmlBinding()
{
if (!parsed)
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index 5442e265fd..52ad4dd78c 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -45,6 +45,8 @@
#include "qv4engine_p.h"
#include "qv4functionobject_p.h"
+#include <QQmlError>
+
QT_BEGIN_NAMESPACE
namespace QV4 {
@@ -77,6 +79,7 @@ struct Q_QML_EXPORT Script {
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
, scope(engine->rootContext), strictMode(false), inheritContext(true), parsed(false)
, qml(qml.asReturnedValue()), vmFunction(0), parseAsBinding(true) {}
+ Script(ExecutionEngine *engine, ObjectRef qml, CompiledData::CompilationUnit *compilationUnit);
~Script();
QString sourceFile;
int line;
@@ -97,6 +100,9 @@ struct Q_QML_EXPORT Script {
Function *function();
+ static CompiledData::CompilationUnit *precompile(ExecutionEngine *engine, const QUrl &url, const QString &source,
+ bool parseAsBinding,
+ QList<QQmlError> *reportedErrors = 0);
static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, ObjectRef scopeObject);
};
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 1bd3ba25d5..07639aa6ba 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2604,13 +2604,21 @@ void QQmlTypeData::scriptImported(QQmlScriptBlob *blob, const QQmlScript::Locati
}
QQmlScriptData::QQmlScriptData()
-: importCache(0), pragmas(QQmlScript::Object::ScriptBlock::None), m_loaded(false), m_program(0)
+ : importCache(0)
+ , pragmas(QQmlScript::Object::ScriptBlock::None)
+ , m_loaded(false)
+ , m_program(0)
+ , m_precompiledScript(0)
{
}
QQmlScriptData::~QQmlScriptData()
{
delete m_program;
+ if (m_precompiledScript) {
+ m_precompiledScript->deref();
+ m_precompiledScript = 0;
+ }
}
void QQmlScriptData::clear()
@@ -2663,7 +2671,8 @@ void QQmlScriptBlob::dataReceived(const Data &data)
m_metadata = QQmlScript::Parser::extractMetaData(m_source, &metaDataError);
if (metaDataError.isValid()) {
metaDataError.setUrl(finalUrl());
- m_scriptData->setError(metaDataError);
+ setError(metaDataError);
+ return;
}
m_imports.setBaseUrl(finalUrl(), finalUrlString());
@@ -2726,8 +2735,17 @@ void QQmlScriptBlob::done()
m_imports.populateCache(m_scriptData->importCache);
m_scriptData->pragmas = m_metadata.pragmas;
- m_scriptData->m_programSource = m_source.toUtf8();
+
+ QList<QQmlError> errors;
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine());
+ m_scriptData->m_precompiledScript = QV4::Script::precompile(v4, m_scriptData->url, m_source, /*parseAsBinding*/true, &errors);
+ if (m_scriptData->m_precompiledScript)
+ m_scriptData->m_precompiledScript->ref();
m_source.clear();
+ if (!errors.isEmpty()) {
+ setError(errors);
+ return;
+ }
}
void QQmlScriptBlob::scriptImported(QQmlScriptBlob *blob, const QQmlScript::Location &location, const QString &qualifier, const QString &nameSpace)
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index be1ffba09e..f6eea6c248 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -511,10 +511,6 @@ 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
@@ -523,10 +519,9 @@ private:
friend class QQmlScriptBlob;
bool m_loaded;
- QByteArray m_programSource;
+ QV4::CompiledData::CompilationUnit *m_precompiledScript;
QV4::Script *m_program;
QV4::PersistentValue m_value;
- QQmlError m_error;
};
class Q_AUTOTEST_EXPORT QQmlScriptBlob : public QQmlTypeLoader::Blob
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index f256f3a1ce..5bf679d7a3 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -1088,18 +1088,7 @@ void QQmlScriptData::initialize(QQmlEngine *engine)
QV8Engine *v8engine = ep->v8engine();
QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8engine);
- // If compilation throws an error, a surrounding catch will record it.
- // pass 0 as the QML object, we set it later before calling run()
- QV4::Script *program = new QV4::Script(v4, QV4::ObjectRef::null(), m_programSource, urlString, 1);
- try {
- program->parse();
- } catch (QV4::Exception &) {
- delete program;
- throw;
- }
-
- m_program = program;
- m_programSource.clear(); // We don't need this anymore
+ m_program = new QV4::Script(v4, QV4::ObjectRef::null(), m_precompiledScript);
addToEngine(engine);
@@ -1119,11 +1108,6 @@ QV4::PersistentValue QQmlVME::run(QQmlContextData *parentCtxt, QQmlScriptData *s
QV4::ExecutionEngine *v4 = QV8Engine::getV4(parentCtxt->engine);
QV4::Scope scope(v4);
- if (script->hasError()) {
- ep->warning(script->error());
- return rv;
- }
-
bool shared = script->pragmas & QQmlScript::Object::ScriptBlock::Shared;
QQmlContextData *effectiveCtxt = parentCtxt;
@@ -1164,18 +1148,8 @@ QV4::PersistentValue QQmlVME::run(QQmlContextData *parentCtxt, QQmlScriptData *s
ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
}
- if (!script->isInitialized()) {
- QV4::ExecutionContext *ctx = QV8Engine::getV4(parentCtxt->engine)->current;
- try {
- script->initialize(parentCtxt->engine);
- } catch (QV4::Exception &e) {
- e.accept(ctx);
- QQmlError error;
- QQmlExpressionPrivate::exceptionToError(e, error);
- if (error.isValid())
- ep->warning(error);
- }
- }
+ if (!script->isInitialized())
+ script->initialize(parentCtxt->engine);
if (!script->m_program) {
if (shared)
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 0ea6a25afb..5f923c7a21 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -3932,6 +3932,7 @@ void tst_qqmlecmascript::verifyContextLifetime(QQmlContextData *ctxt) {
void tst_qqmlecmascript::importScripts_data()
{
QTest::addColumn<QUrl>("testfile");
+ QTest::addColumn<bool>("compilationShouldSucceed");
QTest::addColumn<QString>("errorMessage");
QTest::addColumn<QStringList>("warningMessages");
QTest::addColumn<QStringList>("propertyNames");
@@ -3939,6 +3940,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("basic functionality")
<< testFileUrl("jsimport/testImport.qml")
+ << true /* compilation should succeed */
<< QString()
<< QStringList()
<< (QStringList() << QLatin1String("importedScriptStringValue")
@@ -3952,6 +3954,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("import scoping")
<< testFileUrl("jsimport/testImportScoping.qml")
+ << true /* compilation should succeed */
<< QString()
<< QStringList()
<< (QStringList() << QLatin1String("componentError"))
@@ -3959,6 +3962,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("parent scope shouldn't be inherited by import with imports")
<< testFileUrl("jsimportfail/failOne.qml")
+ << true /* compilation should succeed */
<< QString()
<< (QStringList() << QString(testFileUrl("jsimportfail/failOne.qml").toString() + QLatin1String(":6: TypeError: Cannot call method 'greetingString' of undefined")))
<< (QStringList() << QLatin1String("importScriptFunctionValue"))
@@ -3966,6 +3970,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("javascript imports in an import should be private to the import scope")
<< testFileUrl("jsimportfail/failTwo.qml")
+ << true /* compilation should succeed */
<< QString()
<< (QStringList() << QString(testFileUrl("jsimportfail/failTwo.qml").toString() + QLatin1String(":6: ReferenceError: ImportOneJs is not defined")))
<< (QStringList() << QLatin1String("importScriptFunctionValue"))
@@ -3973,6 +3978,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("module imports in an import should be private to the import scope")
<< testFileUrl("jsimportfail/failThree.qml")
+ << true /* compilation should succeed */
<< QString()
<< (QStringList() << QString(testFileUrl("jsimportfail/failThree.qml").toString() + QLatin1String(":7: TypeError: Cannot read property 'JsQtTest' of undefined")))
<< (QStringList() << QLatin1String("importedModuleAttachedPropertyValue"))
@@ -3980,6 +3986,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("typenames in an import should be private to the import scope")
<< testFileUrl("jsimportfail/failFour.qml")
+ << true /* compilation should succeed */
<< QString()
<< (QStringList() << QString(testFileUrl("jsimportfail/failFour.qml").toString() + QLatin1String(":6: ReferenceError: JsQtTest is not defined")))
<< (QStringList() << QLatin1String("importedModuleEnumValue"))
@@ -3987,6 +3994,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("import with imports has it's own activation scope")
<< testFileUrl("jsimportfail/failFive.qml")
+ << true /* compilation should succeed */
<< QString()
<< (QStringList() << QString(testFileUrl("jsimportfail/importWithImports.js").toString() + QLatin1String(":8: ReferenceError: Component is not defined")))
<< (QStringList() << QLatin1String("componentError"))
@@ -3994,6 +4002,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("import pragma library script")
<< testFileUrl("jsimport/testImportPragmaLibrary.qml")
+ << true /* compilation should succeed */
<< QString()
<< QStringList()
<< (QStringList() << QLatin1String("testValue"))
@@ -4001,6 +4010,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("pragma library imports shouldn't inherit parent imports or scope")
<< testFileUrl("jsimportfail/testImportPragmaLibrary.qml")
+ << true /* compilation should succeed */
<< QString()
<< (QStringList() << QString(testFileUrl("jsimportfail/importPragmaLibrary.js").toString() + QLatin1String(":6: ReferenceError: Component is not defined")))
<< (QStringList() << QLatin1String("testValue"))
@@ -4008,6 +4018,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("import pragma library script which has an import")
<< testFileUrl("jsimport/testImportPragmaLibraryWithImports.qml")
+ << true /* compilation should succeed */
<< QString()
<< QStringList()
<< (QStringList() << QLatin1String("testValue"))
@@ -4015,6 +4026,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("import pragma library script which has a pragma library import")
<< testFileUrl("jsimport/testImportPragmaLibraryWithPragmaLibraryImports.qml")
+ << true /* compilation should succeed */
<< QString()
<< QStringList()
<< (QStringList() << QLatin1String("testValue"))
@@ -4022,6 +4034,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("import singleton type into js import")
<< testFileUrl("jsimport/testImportSingletonType.qml")
+ << true /* compilation should succeed */
<< QString()
<< QStringList()
<< (QStringList() << QLatin1String("testValue"))
@@ -4029,6 +4042,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("import module which exports a script")
<< testFileUrl("jsimport/testJsImport.qml")
+ << true /* compilation should succeed */
<< QString()
<< QStringList()
<< (QStringList() << QLatin1String("importedScriptStringValue")
@@ -4040,6 +4054,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("import module which exports a script which imports a remote module")
<< testFileUrl("jsimport/testJsRemoteImport.qml")
+ << true /* compilation should succeed */
<< QString()
<< QStringList()
<< (QStringList() << QLatin1String("importedScriptStringValue")
@@ -4051,6 +4066,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("malformed import statement")
<< testFileUrl("jsimportfail/malformedImport.qml")
+ << false /* compilation should succeed */
<< QString()
<< (QStringList() << testFileUrl("jsimportfail/malformedImport.js").toString() + QLatin1String(":1:1: Syntax error"))
<< QStringList()
@@ -4058,6 +4074,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("malformed file name")
<< testFileUrl("jsimportfail/malformedFile.qml")
+ << false /* compilation should succeed */
<< QString()
<< (QStringList() << testFileUrl("jsimportfail/malformedFile.js").toString() + QLatin1String(":1:9: Imported file must be a script"))
<< QStringList()
@@ -4065,6 +4082,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("missing file qualifier")
<< testFileUrl("jsimportfail/missingFileQualifier.qml")
+ << false /* compilation should succeed */
<< QString()
<< (QStringList() << testFileUrl("jsimportfail/missingFileQualifier.js").toString() + QLatin1String(":1:1: File import requires a qualifier"))
<< QStringList()
@@ -4072,6 +4090,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("malformed file qualifier")
<< testFileUrl("jsimportfail/malformedFileQualifier.qml")
+ << false /* compilation should succeed */
<< QString()
<< (QStringList() << testFileUrl("jsimportfail/malformedFileQualifier.js").toString() + QLatin1String(":1:20: File import requires a qualifier"))
<< QStringList()
@@ -4079,6 +4098,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("malformed module qualifier 2")
<< testFileUrl("jsimportfail/malformedFileQualifier.2.qml")
+ << false /* compilation should succeed */
<< QString()
<< (QStringList() << testFileUrl("jsimportfail/malformedFileQualifier.2.js").toString() + QLatin1String(":1:1: Invalid import qualifier"))
<< QStringList()
@@ -4086,6 +4106,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("malformed module uri")
<< testFileUrl("jsimportfail/malformedModule.qml")
+ << false /* compilation should succeed */
<< QString()
<< (QStringList() << testFileUrl("jsimportfail/malformedModule.js").toString() + QLatin1String(":1:17: Invalid module URI"))
<< QStringList()
@@ -4093,6 +4114,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("missing module version")
<< testFileUrl("jsimportfail/missingModuleVersion.qml")
+ << false /* compilation should succeed */
<< QString()
<< (QStringList() << testFileUrl("jsimportfail/missingModuleVersion.js").toString() + QLatin1String(":1:17: Module import requires a version"))
<< QStringList()
@@ -4100,6 +4122,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("malformed module version")
<< testFileUrl("jsimportfail/malformedModuleVersion.qml")
+ << false /* compilation should succeed */
<< QString()
<< (QStringList() << testFileUrl("jsimportfail/malformedModuleVersion.js").toString() + QLatin1String(":1:17: Module import requires a version"))
<< QStringList()
@@ -4107,6 +4130,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("missing module qualifier")
<< testFileUrl("jsimportfail/missingModuleQualifier.qml")
+ << false /* compilation should succeed */
<< QString()
<< (QStringList() << testFileUrl("jsimportfail/missingModuleQualifier.js").toString() + QLatin1String(":1:1: Module import requires a qualifier"))
<< QStringList()
@@ -4114,6 +4138,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("malformed module qualifier")
<< testFileUrl("jsimportfail/malformedModuleQualifier.qml")
+ << false /* compilation should succeed */
<< QString()
<< (QStringList() << testFileUrl("jsimportfail/malformedModuleQualifier.js").toString() + QLatin1String(":1:21: Module import requires a qualifier"))
<< QStringList()
@@ -4121,6 +4146,7 @@ void tst_qqmlecmascript::importScripts_data()
QTest::newRow("malformed module qualifier 2")
<< testFileUrl("jsimportfail/malformedModuleQualifier.2.qml")
+ << false /* compilation should succeed */
<< QString()
<< (QStringList() << testFileUrl("jsimportfail/malformedModuleQualifier.2.js").toString() + QLatin1String(":1:1: Invalid import qualifier"))
<< QStringList()
@@ -4130,8 +4156,9 @@ void tst_qqmlecmascript::importScripts_data()
void tst_qqmlecmascript::importScripts()
{
QFETCH(QUrl, testfile);
+ QFETCH(bool, compilationShouldSucceed);
QFETCH(QString, errorMessage);
- QFETCH(QStringList, warningMessages);
+ QFETCH(QStringList, warningMessages); // error messages if !compilationShouldSucceed
QFETCH(QStringList, propertyNames);
QFETCH(QVariantList, propertyValues);
@@ -4149,11 +4176,19 @@ void tst_qqmlecmascript::importScripts()
if (!errorMessage.isEmpty())
QTest::ignoreMessage(QtWarningMsg, errorMessage.toLatin1().constData());
- if (warningMessages.size())
+ if (compilationShouldSucceed && warningMessages.size())
foreach (const QString &warning, warningMessages)
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
- QTRY_VERIFY(component.isReady());
+ if (compilationShouldSucceed)
+ QTRY_VERIFY(component.isReady());
+ else {
+ QVERIFY(component.isError());
+ QCOMPARE(warningMessages.size(), 1);
+ QCOMPARE(component.errors().count(), 2);
+ QCOMPARE(component.errors().at(1).toString(), warningMessages.first());
+ return;
+ }
QObject *object = component.create();
if (!errorMessage.isEmpty()) {
@@ -6653,26 +6688,12 @@ void tst_qqmlecmascript::qtbug_22843()
fileName += QLatin1String(".qml");
QQmlComponent component(&engine, testFileUrl(fileName));
+
QString url = component.url().toString();
- QString warning1 = url.left(url.length()-3) + QLatin1String("js:4:16: Expected token `;'");
- QString warning2 = url + QLatin1String(":5: TypeError: Cannot call method 'func' of undefined");
+ QString expectedError = url.left(url.length()-3) + QLatin1String("js:4:16: Expected token `;'");
- qRegisterMetaType<QList<QQmlError> >("QList<QQmlError>");
- QSignalSpy warningsSpy(&engine, SIGNAL(warnings(QList<QQmlError>)));
- for (int x = 0; x < 3; ++x) {
- warningsSpy.clear();
- // For libraries, only the first import attempt should produce a
- // SyntaxError warning; subsequent component creation should not
- // attempt to reload the script.
- bool expectSyntaxError = !library || (x == 0);
- if (expectSyntaxError)
- QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
- QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
- QObject *object = component.create();
- QVERIFY(object != 0);
- QCOMPARE(warningsSpy.count(), 1 + (expectSyntaxError?1:0));
- delete object;
- }
+ QVERIFY(component.isError());
+ QCOMPARE(component.errors().value(1).toString(), expectedError);
}