69 function createNamedFunction(name, parent, obj) {
71 [name]: function(...args) {
72 return obj.call(parent, args);
77 function deepShallowClone(parent, obj, depth) {
81 if (
typeof obj ===
'function') {
83 return createNamedFunction(obj.name, parent, obj);
89 if (
typeof obj !==
'object')
92 if (Array.isArray(obj)) {
94 for (let i = 0; i < obj.length; i++)
95 arrCopy[i] = deepShallowClone(obj, obj[i], depth + 1);
101 for (
const key in obj)
102 objCopy[key] = deepShallowClone(obj, obj[key], depth + 1);
108 let control = Module.qtSuspendResumeControl;
109 let handler = (arg) => {
112 arg = deepShallowClone(arg, arg, 0);
115 control.pendingEvents.push({
121 if (control.resume) {
123 const resume = control.resume;
124 control.resume = null;
127 if (control.asyncifyEnabled) {
136 Module.qtSendPendingEvents();
140 control.eventHandlers[index] = handler;
144QWasmSuspendResumeControl::QWasmSuspendResumeControl()
147 Q_ASSERT(emscripten_is_main_runtime_thread());
149 qtSuspendResumeControlClearJs();
150 suspendResumeControlJs().set(
"asyncifyEnabled", qstdweb::haveAsyncify());
151 Q_ASSERT(!QWasmSuspendResumeControl::s_suspendResumeControl);
152 QWasmSuspendResumeControl::s_suspendResumeControl =
this;
179void QWasmSuspendResumeControl::removeEventHandler(uint32_t index)
181 m_eventHandlers.erase(index);
182 suspendResumeControlJs()[
"eventHandlers"].set(index, val::null());
203int QWasmSuspendResumeControl::sendPendingEvents()
206 Q_ASSERT(emscripten_is_main_runtime_thread());
208 emscripten::val pendingEvents = suspendResumeControlJs()[
"pendingEvents"];
209 if (pendingEvents[
"length"].as<
int>() == 0)
213 while (pendingEvents[
"length"].as<
int>() > 0) {
215 emscripten::val event = pendingEvents.call<val>(
"shift");
216 auto it = m_eventHandlers.find(event[
"index"].as<
int>());
217 Q_ASSERT(it != m_eventHandlers.end());
218 it->second(event[
"arg"]);
237QWasmEventHandler::QWasmEventHandler(emscripten::val element,
const std::string &name, std::function<
void(emscripten::val)> handler)
241 QWasmSuspendResumeControl *suspendResume = QWasmSuspendResumeControl::get();
242 Q_ASSERT(suspendResume);
243 m_eventHandlerIndex = suspendResume->registerEventHandler(std::move(handler));
244 m_element.call<
void>(
"addEventListener", m_name, suspendResume->jsEventHandlerAt(m_eventHandlerIndex));
247QWasmEventHandler::~QWasmEventHandler()
250 if (m_element.isUndefined())
253 QWasmSuspendResumeControl *suspendResume = QWasmSuspendResumeControl::get();
254 Q_ASSERT(suspendResume);
255 m_element.call<
void>(
"removeEventListener", m_name, suspendResume->jsEventHandlerAt(m_eventHandlerIndex));
256 suspendResume->removeEventHandler(m_eventHandlerIndex);
259QWasmEventHandler::QWasmEventHandler(QWasmEventHandler&& other)
noexcept
260:m_element(std::move(other.m_element))
261,m_name(std::move(other.m_name))
262,m_eventHandlerIndex(other.m_eventHandlerIndex)
264 other.m_element = emscripten::val();
265 other.m_name = emscripten::val();
266 other.m_eventHandlerIndex = 0;
269QWasmEventHandler& QWasmEventHandler::operator=(QWasmEventHandler&& other)
noexcept
271 m_element = std::move(other.m_element);
272 other.m_element = emscripten::val();
273 m_name = std::move(other.m_name);
274 other.m_name = emscripten::val();
275 m_eventHandlerIndex = other.m_eventHandlerIndex;
276 other.m_eventHandlerIndex = 0;
310 val jsHandler = QWasmSuspendResumeControl::get()->jsEventHandlerAt(m_handlerIndex);
311 using ArgType =
double;
312 ArgType timoutValue =
static_cast<ArgType>(timeout.count());
313 ArgType timerId = val::global(
"window").call<ArgType>(
"setTimeout", jsHandler, timoutValue);
314 m_timerId =
static_cast<int64_t>(std::round(timerId));
EM_ASYNC_JS(void, qtSuspendJs,(), { return new Promise(resolve=> { Module.qtSuspendResumeControl.resume=resolve;});})