aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorAndrei Golubev <andrei.golubev@qt.io>2021-02-08 15:42:59 +0100
committerAndrei Golubev <andrei.golubev@qt.io>2021-02-12 12:00:09 +0100
commitf3281ca869420df83d618c255aa7d62e63a102d5 (patch)
tree4c990b4253313c3826dfb840cf427e8efa15b341 /src/qml
parent9c282fe2e90eec05e160241069c219c7f09f4078 (diff)
Support runtime functions evaluation by index through QQmlEngine
Add execution function that can evaluate runtime functions available in the compilation unit. Private API for now as it's unclear what would be a comprehensive solution to support all existing use cases Task-number: QTBUG-84368 Task-number: QTBUG-91039 Change-Id: Icf755b53484587d7983eaae4821c1aa0111d5c05 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/jsruntime/qv4engine.cpp28
-rw-r--r--src/qml/jsruntime/qv4engine_p.h3
-rw-r--r--src/qml/qml/qqmlengine.cpp24
-rw-r--r--src/qml/qml/qqmlengine_p.h3
4 files changed, 58 insertions, 0 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 7ae281fb1a..ee35ad2586 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -93,6 +93,7 @@
#include "qv4stackframe_p.h"
#include "qv4atomics_p.h"
#include "qv4urlobject_p.h"
+#include "qv4jscall_p.h"
#if QT_CONFIG(qml_sequence_object)
#include "qv4sequenceobject_p.h"
@@ -124,6 +125,8 @@
#include <qmetatype.h>
#include <qsequentialiterable.h>
+#include <private/qqmlengine_p.h>
+
#if USE(PTHREADS)
# include <pthread.h>
#if !defined(Q_OS_INTEGRITY)
@@ -2051,6 +2054,31 @@ bool ExecutionEngine::diskCacheEnabled() const
return (!disableDiskCache() && !debugger()) || forceDiskCache();
}
+ReturnedValue ExecutionEngine::callInContext(Function *function, QObject *self,
+ QQmlRefPointer<QQmlContextData> ctxtdata, void **args,
+ int *types)
+{
+ QV4::Scope scope(this);
+ ExecutionContext *ctx = currentStackFrame ? currentContext() : scriptContext();
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, QV4::QmlContext::create(ctx, ctxtdata, self));
+ QV4::ScopedValue selfValue(scope, QV4::QObjectWrapper::wrap(this, self));
+
+ if (!args)
+ return function->call(selfValue, nullptr, 0, qmlContext);
+
+ if (!types) // both args and types must be present
+ return Encode::undefined();
+
+ // use JSCallData to pass arguments into the function call
+ QV4::JSCallData jsCall(scope, types[0]);
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(m_qmlEngine);
+ QV4::populateJSCallArguments(ep, this, jsCall, args, types);
+
+ QV4::CallData *callData = jsCall->callData();
+ return function->call(selfValue, callData->argValues<QV4::Value>(), callData->argc(),
+ qmlContext);
+}
+
void ExecutionEngine::initQmlGlobalObject()
{
initializeGlobal();
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 6d02ffd54b..4529d09c2d 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -741,6 +741,9 @@ public:
bool diskCacheEnabled() const;
+ ReturnedValue callInContext(Function *function, QObject *self,
+ QQmlRefPointer<QQmlContextData> ctxtdata, void **args, int *types);
+
private:
#if QT_CONFIG(qml_debug)
QScopedPointer<QV4::Debugging::Debugger> m_debugger;
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index aa30c08c19..5e108f6914 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -2312,6 +2312,30 @@ bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
return typeLoader.isScriptLoaded(url);
}
+QJSValue QQmlEnginePrivate::executeRuntimeFunction(const QUrl &url, qsizetype functionIndex,
+ QObject *thisObject, void **args, int *types)
+{
+ Q_Q(QQmlEngine);
+ if (const auto unit = typeLoader.getType(url)->compilationUnit()) {
+ Q_ASSERT(functionIndex >= 0);
+ Q_ASSERT(thisObject);
+
+ if (!unit->engine)
+ unit->linkToEngine(q->handle());
+
+ if (unit->runtimeFunctions.length() <= functionIndex)
+ return QJSValue();
+
+ QQmlContext *ctx = q->contextForObject(thisObject);
+ if (!ctx)
+ ctx = q->rootContext();
+ return QJSValuePrivate::fromReturnedValue(
+ q->handle()->callInContext(unit->runtimeFunctions[functionIndex], thisObject,
+ QQmlContextData::get(ctx), args, types));
+ }
+ return QJSValue();
+}
+
#if defined(Q_OS_WIN)
// Normalize a file name using Shell API. As opposed to converting it
// to a short 8.3 name and back, this also works for drives where 8.3 notation
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index b7073ffcfd..4f1c5f26dd 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -300,6 +300,9 @@ public:
return nullptr;
}
+ QJSValue executeRuntimeFunction(const QUrl &url, qsizetype functionIndex, QObject *thisObject,
+ void **args = nullptr, int *types = nullptr);
+
private:
class SingletonInstances : private QHash<QQmlType, QJSValue>
{