diff options
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 5 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 3 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4script.cpp | 95 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4script_p.h | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 24 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader_p.h | 7 | ||||
-rw-r--r-- | src/qml/qml/qqmlvme.cpp | 32 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 63 |
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); } |