15std::shared_ptr<
void> registerOnOffMethodsBasedEventHandler(
16 QNapi::Object eventSourceObject,
const std::string &eventTypeName,
17 QNapi::CallbackFuncWrapper eventHandler, OnOffMethodsBasedEventHandlerOptions options)
21 std::function<QNapi::Value(
const CallbackInfo &)> eventHandler;
22 std::function<
bool(QNapi::Object)> eventSourceAliveCheckFunc;
23 QNapi::Reference<QNapi::Value> optExtraOnArg;
24 QNapi::Reference<QNapi::Value> optExtraOffArg;
27 auto env = eventSourceObject.Env();
29 auto sharedContext = moveToSharedPtr(
31 .eventHandler = std::move(eventHandler.callbackFunc()),
32 .eventSourceAliveCheckFunc = options.optEventSourceAliveCheckFunc
33 ? std::move(options.optEventSourceAliveCheckFunc)
37 .optExtraOnArg = options.extraOnArg.has_value()
38 ? QNapi::Reference<>::makePersistentFrom(
39 options.extraOnArg.value().mapToValue(env))
40 : QNapi::Reference<>::makeEmpty(),
41 .optExtraOffArg = options.extraOffArg.has_value()
42 ? QNapi::Reference<>::makePersistentFrom(
43 options.extraOffArg.value().mapToValue(env))
44 : QNapi::Reference<>::makeEmpty(),
47 auto jsEventHandlerRef = moveToSharedPtr(
48 QNapi::Reference<>::makePersistentFrom(
50 eventSourceObject.Env(),
51 [eventTypeName, weakContext = makeWeakPtr(sharedContext)](
const CallbackInfo &cbInfo) {
52 auto sharedContext = weakContext.lock();
54 return sharedContext->eventHandler(cbInfo);
57 "%s: got unexpected '%s' event callback call for detached handler",
58 Q_FUNC_INFO, eventTypeName.c_str());
59 return cbInfo.Env().Undefined();
63 std::vector<QNapi::ValueWrapper> onCallArgs;
64 onCallArgs.push_back(eventTypeName);
65 if (!sharedContext->optExtraOnArg.IsEmpty())
66 onCallArgs.push_back(sharedContext->optExtraOnArg.Value());
67 onCallArgs.push_back(jsEventHandlerRef->Value());
68 bool onCallSuccessful;
70 eventSourceObject.call(
"on", onCallArgs);
71 onCallSuccessful =
true;
72 }
catch (
const Napi::Error &error) {
73 onCallSuccessful =
false;
74 if (options.optOnCallExceptionHandler) {
75 options.optOnCallExceptionHandler(error);
81 if (!onCallSuccessful)
84 auto eventSourceWeakRef = moveToSharedPtr(Napi::Weak(eventSourceObject));
86 return makeProxyWithJsThreadDeleter(
87 QtOhos::makeDestroyNotifier(
88 [eventSourceWeakRef, eventTypeName, sharedContext, jsEventHandlerRef]() {
89 auto eventSourceValue = eventSourceWeakRef->Value();
90 if (eventSourceValue.IsObject()) {
91 auto eventSourceObject = QNapi::checkedCast<QNapi::Object>(eventSourceValue);
92 if (sharedContext->eventSourceAliveCheckFunc(eventSourceObject)) {
94 std::vector<QNapi::ValueWrapper> offCallArgs;
95 offCallArgs.push_back(eventTypeName);
96 if (!sharedContext->optExtraOffArg.IsEmpty())
97 offCallArgs.push_back(sharedContext->optExtraOffArg.Value());
98 offCallArgs.push_back(jsEventHandlerRef->Value());
99 eventSourceObject.call(
"off", offCallArgs);
100 }
catch (
const Napi::Error &e) {
102 "%s: got exception from off(%s, ...) call (ignoring): %s",
103 Q_FUNC_INFO, eventTypeName.c_str(), e.what());
107 "%s: not calling off(%s, ...), event source 'considered' not alive",
108 Q_FUNC_INFO, eventTypeName.c_str());
112 "%s: not calling off(%s, ...), event source not alive",
113 Q_FUNC_INFO, eventTypeName.c_str());
118std::shared_ptr<
void> startDelayedJsThreadTask(
120 std::chrono::milliseconds delay)
125 QOhosOptional<
int> timerId;
128 auto context =
std::make_shared<Context>();
129 context->task =
std::move(task);
131 int timerId = jsState.eval<QNapi::Number>(
132 "Global.setTimeout(*)",
134 [context](
const CallbackInfo &cbInfo) {
136 auto task = std::exchange(context->task,
nullptr);
137 context->timerId.reset();
138 task(cbInfo.jsState());
141 std::max(delay, std::chrono::milliseconds(0)).count(),
143 context->timerId = timerId;
145 return QtOhos::makeDestroyNotifier(
147 if (context->timerId.has_value()) {
148 runInJsThreadAndWait(
149 [&](JsState &jsState) {
150 jsState.eval(
"Global.clearTimeout(*)", {context->timerId.value()});
153 context->task =
nullptr;
154 context->timerId.reset();