wasm: Fix handling of promise pool in WebPromiseManager
Promises are registered upon entry to the pool and unregistered upon exit. If all promises are in a 'pending' state, new promises can't be processed. Upon completion of a registered promise, it is unregistered, allowing space for a new promise. The code path responsible for unregistering promises when they resolve runs each time a promise's callback is called. Unfortunately, there's no guarantee that the callback will be invoked upon the promise's resolution. For instance, promises registered with only a 'catch' callback may never be triggered when the promise resolves correctly. This commit ensures that a final callback is always registered, even if the user did not provide one. This guarantees that promises are always unregistered upon resolution Fixes: QTBUG-118161 Pick-to: 6.5 Change-Id: Ifea93d692464a6ef40c4bcad60f840ca0cb650c9 Reviewed-by: Lorn Potter <lorn.potter@gmail.com> (cherry picked from commit 1e6841245dca3bda5dee050fc841c7129142dd9f) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit a625d521f70c4897ba4ebeb7f1c7195e571290fb)
This commit is contained in:
parent
ee0b32d77f
commit
129ab89c5d
@ -136,11 +136,12 @@ public:
|
|||||||
"catch",
|
"catch",
|
||||||
emscripten::val::module_property(thunkName(CallbackType::Catch, id()).data()));
|
emscripten::val::module_property(thunkName(CallbackType::Catch, id()).data()));
|
||||||
}
|
}
|
||||||
if (callbacks.finallyFunc) {
|
// Guarantee the invocation of at least one callback by always
|
||||||
target = target.call<val>(
|
// registering 'finally'. This is required by WebPromiseManager
|
||||||
"finally",
|
// design
|
||||||
emscripten::val::module_property(thunkName(CallbackType::Finally, id()).data()));
|
target = target.call<val>(
|
||||||
}
|
"finally", emscripten::val::module_property(
|
||||||
|
thunkName(CallbackType::Finally, id()).data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -321,25 +322,21 @@ void WebPromiseManager::promiseThunkCallback(int context, CallbackType type, ems
|
|||||||
auto* promiseState = &m_promiseRegistry[context];
|
auto* promiseState = &m_promiseRegistry[context];
|
||||||
|
|
||||||
auto* callbacks = &promiseState->callbacks;
|
auto* callbacks = &promiseState->callbacks;
|
||||||
bool expectingOtherCallbacks;
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CallbackType::Then:
|
case CallbackType::Then:
|
||||||
callbacks->thenFunc(result);
|
callbacks->thenFunc(result);
|
||||||
// At this point, if there is no finally function, we are sure that the Catch callback won't be issued.
|
|
||||||
expectingOtherCallbacks = !!callbacks->finallyFunc;
|
|
||||||
break;
|
break;
|
||||||
case CallbackType::Catch:
|
case CallbackType::Catch:
|
||||||
callbacks->catchFunc(result);
|
callbacks->catchFunc(result);
|
||||||
expectingOtherCallbacks = !!callbacks->finallyFunc;
|
|
||||||
break;
|
break;
|
||||||
case CallbackType::Finally:
|
case CallbackType::Finally:
|
||||||
callbacks->finallyFunc();
|
// Final callback may be empty, used solely for promise unregistration
|
||||||
expectingOtherCallbacks = false;
|
if (callbacks->finallyFunc) {
|
||||||
|
callbacks->finallyFunc();
|
||||||
|
}
|
||||||
|
unregisterPromise(context);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!expectingOtherCallbacks)
|
|
||||||
unregisterPromise(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebPromiseManager::registerPromise(
|
void WebPromiseManager::registerPromise(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user