aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4engine.cpp
diff options
context:
space:
mode:
authorAndrei Golubev <andrei.golubev@qt.io>2022-04-08 15:49:24 +0200
committerAndrei Golubev <andrei.golubev@qt.io>2022-04-27 15:29:24 +0200
commitb4d5b64359cc0e908fb68d4490df076475c899c3 (patch)
tree15045e1a90b00aef24488b466313b2d5b39ba5d6 /src/qml/jsruntime/qv4engine.cpp
parent52aaf0a4e78a197b1c12189db7d7bf5681946df5 (diff)
Make QQmlEngine resolve closures when executing runtime functions
QML can create a function which holds a closure in the cases like: onSignal: function() { ... } If the left-hand side is a signal handler (or similar), we want to execute the *inner* function when a signal is called, not the outer one. However, under certain conditions (e.g. we use `this`), the outer function must also be called beforehand to correctly setup the calling scope for the inner function Thus, make the QQmlEnginePrivate::executeRuntimeFunction() do that: always call an outer function first and then the inner one if present. This creates an overhead when dealing with certain signal handlers but we could optimize it later if needed Note that the case `property var prop: function() { return 42; }` where a property contains a callable function is no longer supported by the executeRuntimeFunction() routine (we always call the inner code now). This is fine since qmltc (the main beneficiary of the routine) does not rely on this functionality when dealing with property bindings Given the change, qmltc can be simplified to only work with absolute function indices, ignoring the nesting problem altogether Change-Id: I61f61587b6fe700cb695b3b7a213d9cfab0eb746 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4engine.cpp')
-rw-r--r--src/qml/jsruntime/qv4engine.cpp30
1 files changed, 15 insertions, 15 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index d6ec79941d..c8e0828f18 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -2126,30 +2126,30 @@ bool ExecutionEngine::diskCacheEnabled() const
return (!disableDiskCache() && !debugger()) || forceDiskCache();
}
-void ExecutionEngine::callInContext(Function *function, QObject *self,
- QQmlRefPointer<QQmlContextData> ctxtdata, int argc, void **args,
+void ExecutionEngine::callInContext(QV4::Function *function, QObject *self,
+ QV4::ExecutionContext *context, int argc, void **args,
QMetaType *types)
{
- QV4::Scope scope(this);
- // NB: always use scriptContext() here as this method ignores whether
- // there's already a stack frame. the method is called from C++ (through
- // QQmlEngine::executeRuntimeFunction()) and thus the caller must ensure
- // correct setup
- QV4::ExecutionContext *ctx = scriptContext();
- QV4::Scoped<QV4::QmlContext> qmlContext(scope, QV4::QmlContext::create(ctx, ctxtdata, self));
if (!args) {
Q_ASSERT(argc == 0);
void *dummyArgs[] = { nullptr };
QMetaType dummyTypes[] = { QMetaType::fromType<void>() };
- function->call(self, dummyArgs, dummyTypes, argc, qmlContext);
+ function->call(self, dummyArgs, dummyTypes, argc, context);
return;
}
-
- if (!types) // both args and types must be present
- return;
-
+ Q_ASSERT(types); // both args and types must be present
// implicitly sets the return value, which is args[0]
- function->call(self, args, types, argc, qmlContext);
+ function->call(self, args, types, argc, context);
+}
+
+QV4::ReturnedValue ExecutionEngine::callInContext(QV4::Function *function, QObject *self,
+ QV4::ExecutionContext *context, int argc,
+ const QV4::Value *argv)
+{
+ QV4::Scope scope(this);
+ QV4::ScopedObject jsSelf(scope, QV4::QObjectWrapper::wrap(this, self));
+ Q_ASSERT(jsSelf);
+ return function->call(jsSelf, argv, argc, context);
}
void ExecutionEngine::initQmlGlobalObject()