From 31ab6b81060abb0db0a68c88c61ea93c7d6bdc60 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 15 Jun 2021 09:38:17 +0200 Subject: Allow AOT functions to signal an undefined result via the context undefined as value returned from bindings has the special meaning of resetting the binding. As AOT-compiled functions return the actual type of the binding rather than a QV4::Value, we cannot always encode undefined. Therefore, add a flag that tells us whether the result was supposed to be undefined. Pick-to: 6.2 Change-Id: Iac2298869dde80f6d889240dd8200b2ad83e5dc5 Reviewed-by: Fabian Kosmale --- src/qml/jsruntime/qv4function.cpp | 2 +- src/qml/jsruntime/qv4stackframe_p.h | 5 +++++ src/qml/jsruntime/qv4vme_moth.cpp | 4 +++- src/qml/qml/qqml.cpp | 7 +++++++ src/qml/qml/qqmlprivate.h | 1 + 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index 7b5685a2a0..95a7506c80 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -74,7 +74,7 @@ bool Function::call(QObject *thisObject, void **a, const QMetaType *types, int a frame.push(engine); Moth::VME::exec(&frame, engine); frame.pop(engine); - return true; + return !frame.isReturnValueUndefined(); } ReturnedValue Function::call( diff --git a/src/qml/jsruntime/qv4stackframe_p.h b/src/qml/jsruntime/qv4stackframe_p.h index 1439e9f677..9a121b48cd 100644 --- a/src/qml/jsruntime/qv4stackframe_p.h +++ b/src/qml/jsruntime/qv4stackframe_p.h @@ -90,6 +90,7 @@ struct Q_QML_PRIVATE_EXPORT CppStackFrameBase QObject *thisObject; const QMetaType *metaTypes; void **returnAndArgs; + bool returnValueIsUndefined; }; }; @@ -163,11 +164,15 @@ struct Q_QML_PRIVATE_EXPORT MetaTypesStackFrame : public CppStackFrame CppStackFrameBase::context = context; CppStackFrameBase::metaTypes = metaTypes; CppStackFrameBase::returnAndArgs = returnAndArgs; + CppStackFrameBase::returnValueIsUndefined = false; } QMetaType returnType() const { return metaTypes[0]; } void *returnValue() const { return returnAndArgs[0]; } + bool isReturnValueUndefined() const { return CppStackFrameBase::returnValueIsUndefined; } + void setReturnValueUndefined() { CppStackFrameBase::returnValueIsUndefined = true; } + const QMetaType *argTypes() const { return metaTypes + 1; } void **argv() const { return returnAndArgs + 1; } diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 009cff067a..94860f0521 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -432,8 +432,10 @@ static bool compareEqualInt(QV4::Value &accumulator, QV4::Value lhs, int rhs) void VME::exec(MetaTypesStackFrame *frame, ExecutionEngine *engine) { qt_v4ResolvePendingBreakpointsHook(); - if (engine->checkStackLimits()) + if (engine->checkStackLimits()) { + frame->setReturnValueUndefined(); return; + } ExecutionEngineCallDepthRecorder executionEngineCallDepthRecorder(engine); Function *function = frame->v4Function; diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index 2144893c2d..3b0000ab02 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -712,6 +712,13 @@ void AOTCompiledContext::setInstructionPointer(int offset) const frame->instructionPointer = offset; } +void AOTCompiledContext::setReturnValueUndefined() const +{ + if (auto *frame = engine->handle()->currentStackFrame) { + Q_ASSERT(frame->isMetaTypesFrame()); + static_cast(frame)->setReturnValueUndefined(); + } +} static void captureObjectProperty( QObject *object, const QQmlPropertyCache *propertyCache, diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index 71855df966..11c948445f 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -612,6 +612,7 @@ namespace QQmlPrivate QJSValue jsMetaType(int index) const; void setInstructionPointer(int offset) const; + void setReturnValueUndefined() const; // Run QQmlPropertyCapture::captureProperty() without retrieving the value. bool captureLookup(uint index, QObject *object) const; -- cgit v1.2.3