70 function createNamedFunction(name, parent, obj) {
72 [name]: function(...args) {
73 return obj.call(parent, args);
78 function deepShallowClone(parent, obj, depth) {
82 if (
typeof obj ===
'function') {
84 return createNamedFunction(obj.name, parent, obj);
90 if (
typeof obj !==
'object')
93 if (Array.isArray(obj)) {
95 for (let i = 0; i < obj.length; i++)
96 arrCopy[i] = deepShallowClone(obj, obj[i], depth + 1);
102 for (
const key in obj)
103 objCopy[key] = deepShallowClone(obj, obj[key], depth + 1);
109 let control = Module.qtSuspendResumeControl;
110 let handler = (arg) => {
113 arg = deepShallowClone(arg, arg, 0);
116 control.pendingEvents.push({
122 if (control.exclusiveEventHandler > 0) {
124 if (index != control.exclusiveEventHandler)
127 const resume = control.resume;
128 control.resume = null;
130 }
else if (control.resume) {
132 const resume = control.resume;
133 control.resume = null;
136 if (control.asyncifyEnabled) {
145 Module.qtSendPendingEvents();
149 control.eventHandlers[index] = handler;
153QWasmSuspendResumeControl::QWasmSuspendResumeControl()
156 Q_ASSERT(emscripten_is_main_runtime_thread());
158 qtSuspendResumeControlClearJs();
159 suspendResumeControlJs().set(
"asyncifyEnabled", qstdweb::haveAsyncify());
160 QWasmSuspendResumeControl::s_suspendResumeControl =
this;
186void QWasmSuspendResumeControl::removeEventHandler(uint32_t index)
188 m_eventHandlers.erase(index);
189 suspendResumeControlJs()[
"eventHandlers"].set(index, val::null());
216int QWasmSuspendResumeControl::sendPendingEvents()
219 Q_ASSERT(emscripten_is_main_runtime_thread());
221 emscripten::val control = suspendResumeControlJs();
222 emscripten::val pendingEvents = control[
"pendingEvents"];
224 if (control[
"exclusiveEventHandler"].as<
int>() > 0)
225 return sendPendingExclusiveEvent();
227 if (pendingEvents[
"length"].as<
int>() == 0)
231 while (pendingEvents[
"length"].as<
int>() > 0) {
233 emscripten::val event = pendingEvents.call<val>(
"shift");
234 auto it = m_eventHandlers.find(event[
"index"].as<
int>());
235 if (it != m_eventHandlers.end())
236 it->second(event[
"arg"]);
243int QWasmSuspendResumeControl::sendPendingExclusiveEvent()
245 emscripten::val control = suspendResumeControlJs();
246 int exclusiveHandlerIndex = control[
"exclusiveEventHandler"].as<
int>();
247 control.set(
"exclusiveEventHandler", 0);
248 emscripten::val event = control[
"pendingEvents"].call<val>(
"pop");
249 int eventHandlerIndex = event[
"index"].as<
int>();
250 Q_ASSERT(exclusiveHandlerIndex == eventHandlerIndex);
251 auto it = m_eventHandlers.find(eventHandlerIndex);
252 Q_ASSERT(it != m_eventHandlers.end());
253 it->second(event[
"arg"]);
270QWasmEventHandler::QWasmEventHandler(emscripten::val element,
const std::string &name, std::function<
void(emscripten::val)> handler)
274 QWasmSuspendResumeControl *suspendResume = QWasmSuspendResumeControl::get();
275 Q_ASSERT(suspendResume);
276 m_eventHandlerIndex = suspendResume->registerEventHandler(std::move(handler));
277 m_element.call<
void>(
"addEventListener", m_name, suspendResume->jsEventHandlerAt(m_eventHandlerIndex));
280QWasmEventHandler::~QWasmEventHandler()
283 if (m_element.isUndefined())
286 QWasmSuspendResumeControl *suspendResume = QWasmSuspendResumeControl::get();
287 Q_ASSERT(suspendResume);
288 m_element.call<
void>(
"removeEventListener", m_name, suspendResume->jsEventHandlerAt(m_eventHandlerIndex));
289 suspendResume->removeEventHandler(m_eventHandlerIndex);
292QWasmEventHandler::QWasmEventHandler(QWasmEventHandler&& other)
noexcept
293:m_element(std::move(other.m_element))
294,m_name(std::move(other.m_name))
295,m_eventHandlerIndex(other.m_eventHandlerIndex)
297 other.m_element = emscripten::val();
298 other.m_name = emscripten::val();
299 other.m_eventHandlerIndex = 0;
302QWasmEventHandler& QWasmEventHandler::operator=(QWasmEventHandler&& other)
noexcept
304 m_element = std::move(other.m_element);
305 other.m_element = emscripten::val();
306 m_name = std::move(other.m_name);
307 other.m_name = emscripten::val();
308 m_eventHandlerIndex = other.m_eventHandlerIndex;
309 other.m_eventHandlerIndex = 0;
343 val jsHandler = QWasmSuspendResumeControl::get()->jsEventHandlerAt(m_handlerIndex);
344 using ArgType =
double;
345 ArgType timoutValue =
static_cast<ArgType>(timeout.count());
346 ArgType timerId = val::global(
"window").call<ArgType>(
"setTimeout", jsHandler, timoutValue);
347 m_timerId =
static_cast<int64_t>(std::round(timerId));
EM_ASYNC_JS(void, qtSuspendJs,(), { return new Promise(resolve=> { Module.qtSuspendResumeControl.resume=resolve;});})