From 699b74dc1d288af3d1aaeb02335c10c21f37f56a Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Mon, 21 Nov 2011 13:35:40 +0100 Subject: Don't crash when importing script with syntax error Task-number: QTBUG-22843 Change-Id: I2b1ed6cbbc7a566f54b441359941ea121a9033ba Reviewed-by: Aaron Kennedy --- src/declarative/qml/qdeclarativevme.cpp | 16 ++++++--- .../qdeclarativeecmascript/data/qtbug_22843.js | 5 +++ .../data/qtbug_22843.library.js | 5 +++ .../data/qtbug_22843.library.qml | 6 ++++ .../qdeclarativeecmascript/data/qtbug_22843.qml | 6 ++++ .../tst_qdeclarativeecmascript.cpp | 42 ++++++++++++++++++++++ tests/auto/declarative/qmlmin/tst_qmlmin.cpp | 2 ++ 7 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.js create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.library.js create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.library.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.qml diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index 19df52798e..313d7f1dc4 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -1239,8 +1239,11 @@ void QDeclarativeScriptData::initialize(QDeclarativeEngine *engine) QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); QV8Engine *v8engine = ep->v8engine(); - // XXX Handle errors during the script compile! + // If compilation throws an error, a surrounding v8::TryCatch will record it. v8::Local program = v8engine->qmlModeCompile(m_programSource, url.toString(), 1); + if (program.IsEmpty()) + return; + m_program = qPersistentNew(program); addToEngine(engine); @@ -1301,13 +1304,18 @@ v8::Persistent QDeclarativeVME::run(QDeclarativeContextData *parentC v8::HandleScope handle_scope; v8::Context::Scope scope(v8engine->context()); - if (!script->isInitialized()) + v8::TryCatch try_catch; + if (!script->isInitialized()) script->initialize(parentCtxt->engine); v8::Local qmlglobal = v8engine->qmlScope(ctxt, 0); - v8::TryCatch try_catch; - script->m_program->Run(qmlglobal); + if (!script->m_program.IsEmpty()) { + script->m_program->Run(qmlglobal); + } else { + // Compilation failed. + Q_ASSERT(try_catch.HasCaught()); + } v8::Persistent rv; diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.js b/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.js new file mode 100644 index 0000000000..6d19fe0571 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.js @@ -0,0 +1,5 @@ + +function func() +{ + isFinite() ) +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.library.js b/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.library.js new file mode 100644 index 0000000000..1a7c8a2e6e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.library.js @@ -0,0 +1,5 @@ +.pragma library +function func() +{ + isFinite() ) +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.library.qml b/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.library.qml new file mode 100644 index 0000000000..281765bff6 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.library.qml @@ -0,0 +1,6 @@ +import "qtbug_22843.library.js" as MyScript +import QtQuick 2.0 + +QtObject { + Component.onCompleted: MyScript.func() +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.qml b/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.qml new file mode 100644 index 0000000000..90a47c0f4b --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.qml @@ -0,0 +1,6 @@ +import "qtbug_22843.js" as MyScript +import QtQuick 2.0 + +QtObject { + Component.onCompleted: MyScript.func() +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index 4c43a02e81..1e0f1a86ca 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -225,6 +225,8 @@ private slots: void invokableObjectRet(); void qtbug_20344(); void qtbug_22679(); + void qtbug_22843_data(); + void qtbug_22843(); void revisionErrors(); void revision(); @@ -5178,6 +5180,46 @@ void tst_qdeclarativeecmascript::qtbug_22679() delete o; } +void tst_qdeclarativeecmascript::qtbug_22843_data() +{ + QTest::addColumn("library"); + + QTest::newRow("without .pragma library") << false; + QTest::newRow("with .pragma library") << true; +} + +void tst_qdeclarativeecmascript::qtbug_22843() +{ + QFETCH(bool, library); + + QString fileName("qtbug_22843"); + if (library) + fileName += QLatin1String(".library"); + fileName += QLatin1String(".qml"); + + QDeclarativeComponent component(&engine, TEST_FILE(fileName)); + QString url = component.url().toString(); + QString warning1 = url.left(url.length()-3) + QLatin1String("js:4: SyntaxError: Unexpected token )"); + QString warning2 = url + QLatin1String(":5: TypeError: Object [object Object] has no method 'func'"); + + qRegisterMetaType >("QList"); + QSignalSpy warningsSpy(&engine, SIGNAL(warnings(QList))); + 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; + } +} + QTEST_MAIN(tst_qdeclarativeecmascript) #include "tst_qdeclarativeecmascript.moc" diff --git a/tests/auto/declarative/qmlmin/tst_qmlmin.cpp b/tests/auto/declarative/qmlmin/tst_qmlmin.cpp index 38de65f826..53b0e3772a 100644 --- a/tests/auto/declarative/qmlmin/tst_qmlmin.cpp +++ b/tests/auto/declarative/qmlmin/tst_qmlmin.cpp @@ -105,6 +105,8 @@ void tst_qmlmin::initTestCase() invalidFiles << "tests/auto/declarative/qdeclarativelanguage/data/nonexistantProperty.5.qml"; invalidFiles << "tests/auto/declarative/qdeclarativefolderlistmodel/data/dummy.qml"; invalidFiles << "tests/auto/declarative/qdeclarativeecmascript/data/blank.js"; + invalidFiles << "tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.js"; + invalidFiles << "tests/auto/declarative/qdeclarativeecmascript/data/qtbug_22843.library.js"; invalidFiles << "tests/auto/declarative/qdeclarativeworkerscript/data/script_error_onLoad.js"; invalidFiles << "tests/auto/declarative/qdeclarativelanguage/data/test.js"; invalidFiles << "tests/auto/declarative/qdeclarativelanguage/data/test2.js"; -- cgit v1.2.3