aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/qml/qdeclarativevme.cpp8
-rw-r--r--src/declarative/qml/v8/qv8bindings.cpp38
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/data/v8bindingException.qml21
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp12
4 files changed, 70 insertions, 9 deletions
diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp
index c008e2a28a..a37964aacf 100644
--- a/src/declarative/qml/qdeclarativevme.cpp
+++ b/src/declarative/qml/qdeclarativevme.cpp
@@ -826,9 +826,11 @@ QObject *QDeclarativeVME::run(QList<QDeclarativeError> *errors,
CTXT->v8bindings->configBinding(instr.value, target, scope,
instr.property, instr.line,
instr.column);
- bindValues.push(binding);
- binding->m_mePtr = &bindValues.top();
- binding->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(instr.property));
+ if (binding) {
+ bindValues.push(binding);
+ binding->m_mePtr = &bindValues.top();
+ binding->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(instr.property));
+ }
QML_END_INSTR(StoreV8Binding)
QML_BEGIN_INSTR(StoreValueSource)
diff --git a/src/declarative/qml/v8/qv8bindings.cpp b/src/declarative/qml/v8/qv8bindings.cpp
index 84ed892c09..b21ddf5d2e 100644
--- a/src/declarative/qml/v8/qv8bindings.cpp
+++ b/src/declarative/qml/v8/qv8bindings.cpp
@@ -167,18 +167,41 @@ QV8Bindings::QV8Bindings(const QString &program, int index, int line,
v8::HandleScope handle_scope;
v8::Context::Scope scope(engine->context());
- v8::Local<v8::Script> script = engine->qmlModeCompile(program, compiled->name, line);
- v8::Local<v8::Value> result = script->Run(engine->contextWrapper()->sharedContext());
+ v8::Local<v8::Script> script;
+ bool compileFailed = false;
+ {
+ v8::TryCatch try_catch;
+ script = engine->qmlModeCompile(program, compiled->name, line);
+ if (try_catch.HasCaught()) {
+ // The binding was not compiled. There are some exceptional cases which the
+ // expression rewriter does not rewrite properly (e.g., \r-terminated lines
+ // are not rewritten correctly but this bug is demed out-of-scope to fix for
+ // performance reasons; see QTBUG-24064).
+ compileFailed = true;
+ QDeclarativeError error;
+ error.setDescription(QString(QLatin1String("Exception occurred during compilation of binding at line: %1")).arg(line));
+ v8::Local<v8::Message> message = try_catch.Message();
+ if (!message.IsEmpty())
+ QDeclarativeExpressionPrivate::exceptionToError(message, error);
+ QDeclarativeEnginePrivate::get(engine->engine())->warning(error);
+ compiled->v8bindings[index] = qPersistentNew(v8::Array::New());
+ }
+ }
- if (result->IsArray())
- compiled->v8bindings[index] = qPersistentNew(v8::Local<v8::Array>::Cast(result));
+ if (!compileFailed) {
+ v8::Local<v8::Value> result = script->Run(engine->contextWrapper()->sharedContext());
+ if (result->IsArray()) {
+ compiled->v8bindings[index] = qPersistentNew(v8::Local<v8::Array>::Cast(result));
+ }
+ }
}
url = compiled->url;
functions = qPersistentNew(compiled->v8bindings[index]);
bindingsCount = functions->Length();
- bindings = new QV8Bindings::Binding[bindingsCount];
-
+ if (bindingsCount)
+ bindings = new QV8Bindings::Binding[bindingsCount];
+
setContext(context);
}
@@ -195,6 +218,9 @@ QDeclarativeAbstractBinding *QV8Bindings::configBinding(int index, QObject *targ
const QDeclarativePropertyData &p,
int line, int column)
{
+ if (bindingsCount <= index) // initialization failed.
+ return 0;
+
QV8Bindings::Binding *rv = bindings + index;
rv->line = line;
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/v8bindingException.qml b/tests/auto/declarative/qdeclarativeecmascript/data/v8bindingException.qml
new file mode 100644
index 0000000000..ff203e23e3
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeecmascript/data/v8bindingException.qml
@@ -0,0 +1,21 @@
+import QtQuick 2.0
+
+// This test uses a multi-line string which has \r-terminated
+// string fragments. The expression rewriter deliberately doesn't
+// handle \r-terminated string fragments (see QTBUG-24064) and thus
+// this test ensures that we don't crash when we encounter a
+// non-compilable binding such as this one.
+
+Item {
+ id: root
+
+ Component {
+ id: comp
+ Text {
+ property var value: ","
+ text: 'multi line ' + value + 'str ings'
+ }
+ }
+
+ Component.onCompleted: comp.createObject(root, { "value": undefined })
+}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
index 219eac6e14..1c42d9d425 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
+++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
@@ -113,6 +113,7 @@ private slots:
void exceptionClearsOnReeval();
void exceptionSlotProducesWarning();
void exceptionBindingProducesWarning();
+ void compileInvalidBinding();
void transientErrors();
void shutdownErrors();
void compositePropertyType();
@@ -1562,6 +1563,17 @@ void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
delete object;
}
+void tst_qdeclarativeecmascript::compileInvalidBinding()
+{
+ // QTBUG-23387: ensure that invalid bindings don't cause a crash.
+ QDeclarativeComponent component(&engine, testFileUrl("v8bindingException.qml"));
+ QString warning = component.url().toString() + ":16: SyntaxError: Unexpected token ILLEGAL";
+ QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ delete object;
+}
+
static int transientErrorsMsgCount = 0;
static void transientErrorsMsgHandler(QtMsgType, const char *)
{