aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp22
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h2
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp13
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp12
4 files changed, 42 insertions, 7 deletions
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index e233b65f4e..89e09d6542 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -37,6 +37,7 @@
#include <private/qv4compileddata_p.h>
#include <private/qqmlpropertybinding_p.h>
#include <private/qqmlpropertycachemethodarguments_p.h>
+#include <private/qqmlsignalnames_p.h>
#include <QtQml/qjsvalue.h>
#include <QtCore/qjsonarray.h>
@@ -60,6 +61,7 @@ Q_LOGGING_CATEGORY(lcBindingRemoval, "qt.qml.binding.removal", QtWarningMsg)
Q_LOGGING_CATEGORY(lcObjectConnect, "qt.qml.object.connect", QtWarningMsg)
Q_LOGGING_CATEGORY(lcOverloadResolution, "qt.qml.overloadresolution", QtWarningMsg)
Q_LOGGING_CATEGORY(lcMethodBehavior, "qt.qml.method.behavior")
+Q_LOGGING_CATEGORY(lcSignalHandler, "qt.qml.signalhandler")
// The code in this file does not violate strict aliasing, but GCC thinks it does
// so turn off the warnings for us to have a clean build
@@ -3179,6 +3181,26 @@ void Heap::QmlSignalHandler::init(QObject *object, int signalIndex)
DEFINE_OBJECT_VTABLE(QmlSignalHandler);
+ReturnedValue QmlSignalHandler::call(const Value *thisObject, const Value *argv, int argc) const
+{
+ const QString handlerName = QQmlSignalNames::signalNameToHandlerName(
+ object()->metaObject()->method(signalIndex()).name());
+ qCWarning(lcSignalHandler).noquote()
+ << QStringLiteral("Property '%1' of object %2 is a signal handler. You should "
+ "not call it directly. Make it a proper function and call "
+ "that or emit the signal.")
+ .arg(handlerName, thisObject->toQStringNoThrow());
+
+ Scope scope(engine());
+ Scoped<QObjectMethod> method(
+ scope, QObjectMethod::create(
+ scope.engine->rootContext(),
+ static_cast<Heap::QObjectWrapper *>(nullptr),
+ signalIndex()));
+
+ return method->call(thisObject, argv, argc);
+}
+
void QmlSignalHandler::initProto(ExecutionEngine *engine)
{
if (engine->signalHandlerPrototype()->d_unchecked())
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 7a2dbe7745..2cd2faedf8 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -411,6 +411,8 @@ struct Q_QML_EXPORT QmlSignalHandler : public QV4::Object
int signalIndex() const { return d()->signalIndex; }
QObject *object() const { return d()->object(); }
+ ReturnedValue call(const Value *thisObject, const Value *argv, int argc) const;
+
static void initProto(ExecutionEngine *v4);
};
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 8b3f89414b..c51c94ffe4 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -1503,10 +1503,17 @@ ReturnedValue Runtime::CallPropertyLookup::call(ExecutionEngine *engine, const V
// ok to have the value on the stack here
Value f = Value::fromReturnedValue(l->getter(l, engine, base));
- if (!f.isFunctionObject())
- return engine->throwTypeError();
+ if (Q_LIKELY(f.isFunctionObject()))
+ return checkedResult(engine, static_cast<FunctionObject &>(f).call(&base, argv, argc));
+
+ if (QmlSignalHandler *handler = f.as<QmlSignalHandler>())
+ return checkedResult(engine, handler->call(&base, argv, argc));
- return checkedResult(engine, static_cast<FunctionObject &>(f).call(&base, argv, argc));
+ const QString message = QStringLiteral("Property '%1' of object %2 is not a function")
+ .arg(engine->currentStackFrame->v4Function->compilationUnit
+ ->runtimeStrings[l->nameIndex]->toQString())
+ .arg(base.toQStringNoThrow());
+ return engine->throwTypeError(message);
}
ReturnedValue Runtime::CallValue::call(ExecutionEngine *engine, const Value &func, Value *argv, int argc)
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 1ea0a569fb..696368fa3f 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -794,15 +794,19 @@ QV4::ReturnedValue VME::interpret(JSTypesStackFrame *frame, ExecutionEngine *eng
// ok to have the value on the stack here
Value f = Value::fromReturnedValue(l->getter(l, engine, STACK_VALUE(base)));
- if (Q_UNLIKELY(!f.isFunctionObject())) {
- QString message = QStringLiteral("Property '%1' of object %2 is not a function")
- .arg(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]->toQString())
+ if (Q_LIKELY(f.isFunctionObject())) {
+ acc = static_cast<FunctionObject &>(f).call(stack + base, stack + argv, argc);
+ } else if (QmlSignalHandler *handler = f.as<QmlSignalHandler>()) {
+ acc = handler->call(stack + base, stack + argv, argc);
+ } else {
+ const QString message = QStringLiteral("Property '%1' of object %2 is not a function")
+ .arg(engine->currentStackFrame->v4Function->compilationUnit
+ ->runtimeStrings[l->nameIndex]->toQString())
.arg(STACK_VALUE(base).toQStringNoThrow());
acc = engine->throwTypeError(message);
goto handleUnwind;
}
- acc = static_cast<FunctionObject &>(f).call(stack + base, stack + argv, argc);
CHECK_EXCEPTION;
MOTH_END_INSTR(CallPropertyLookup)