Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qohosjsutils.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qohosjsutils.h"
5#include <QtCore/private/qohoscommon_p.h>
6#include <qohosutils.h>
7
8using namespace std::chrono_literals;
9
10QT_BEGIN_NAMESPACE
11
12namespace QtOhos {
13
14std::shared_ptr<void> startDelayedJsThreadTask(
15 JsState &jsState, std::function<void(JsState &)> task,
16 std::chrono::milliseconds delay)
17{
18 struct Context
19 {
20 std::function<void(JsState &)> task;
21 std::optional<int> timerId;
22 };
23
24 auto context = std::make_shared<Context>();
25 context->task = std::move(task);
26
27 int timerId = jsState.eval<QNapi::Number>(
28 "Global.setTimeout(*)",
29 {
30 [context](const CallbackInfo &cbInfo) {
31 if (context->task) {
32 auto task = std::exchange(context->task, nullptr);
33 context->timerId.reset();
34 task(cbInfo.jsState());
35 }
36 },
37 std::max(delay, std::chrono::milliseconds(0)).count(),
38 });
39 context->timerId = timerId;
40
41 return QtOhos::makeDestroyNotifier(
42 [context]() {
43 if (context->timerId.has_value()) {
44 runInJsThreadAndWait(
45 [&](JsState &jsState) {
46 jsState.eval("Global.clearTimeout(*)", {context->timerId.value()});
47 },
48 Q_FUNC_INFO);
49 context->task = nullptr;
50 context->timerId.reset();
51 }
52 });
53}
54
55int setJsTimeout(
56 JsState &jsState, std::function<void(const CallbackInfo &)> timeoutFunc,
57 std::chrono::milliseconds delay)
58{
59 int timerId = jsState.eval<QNapi::Number>(
60 "Global.setTimeout(*)", {std::move(timeoutFunc), delay.count()});
61 return timerId;
62}
63
64void clearJsTimeout(JsState &jsState, int timerId)
65{
66 jsState.eval("Global.clearTimeout(*)", {timerId});
67}
68
69QNapi::Promise makeResolvedPromise(QNapi::Value valueForResolve)
70{
71 auto promiseDeferred = QNapi::Promise::Deferred::New(valueForResolve.Env());
72 promiseDeferred.Resolve(valueForResolve);
73 return promiseDeferred.Promise();
74}
75
76std::optional<std::uint32_t> tryGetCodeFromJsBusinessError(const Napi::Error &error)
77{
78 if (!error.Value().IsObject())
79 return {};
80
81 auto errorObject = QNapi::checkedCast<QNapi::Object>(error.Value());
82 auto optErrorCode = QNapi::getOptionalPropOrEmpty<QNapi::Number>(errorObject, "code");
83
84 return !optErrorCode.IsEmpty()
85 ? std::optional(optErrorCode.Uint32Value())
86 : std::nullopt;
87}
88
89void rethrowUnlessJsBusinessErrorIs(
90 const Napi::Error &error, std::uint32_t suppressedErrorCode, const char *callerContextName)
91{
92 if (tryGetCodeFromJsBusinessError(error) != suppressedErrorCode)
93 throw;
94
95 qOhosPrintfWarning(
96 "%s: ignored expected JS business error %u",
97 callerContextName, suppressedErrorCode);
98}
99
100bool runIgnoringJsBusinessError(
101 JsState &, std::uint32_t suppressedErrorCode, const char *callerContextName,
102 const std::function<void()> &action)
103{
104 try {
105 action();
106 return true;
107 } catch (const Napi::Error &error) {
108 rethrowUnlessJsBusinessErrorIs(error, suppressedErrorCode, callerContextName);
109 return false;
110 }
111}
112
113}
114
115QT_END_NAMESPACE