Skip to content

Commit

Permalink
Implement emscripten_promise_race in promise.h (#19154)
Browse files Browse the repository at this point in the history
This function propagates the result of its first input promise to settle,
whether it is fulfilled or rejected.
  • Loading branch information
tlively authored Apr 12, 2023
1 parent 3c5bac9 commit 47cb9c6
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 1 deletion.
15 changes: 15 additions & 0 deletions src/library_promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,21 @@ mergeInto(LibraryManager.library, {
});
#if RUNTIME_DEBUG
dbg('create: ' + id);
#endif
return id;
},

emscripten_promise_race__deps: ['$promiseMap', '$idsToPromises'],
emscripten_promise_race: function(idBuf, size) {
var promises = idsToPromises(idBuf, size);
#if RUNTIME_DEBUG
dbg('emscripten_promise_race: ' + promises);
#endif
var id = promiseMap.allocate({
promise: Promise.race(promises)
});
#if RUNTIME_DEBUG
dbg('create: ' + id);
#endif
return id;
}
Expand Down
1 change: 1 addition & 0 deletions src/library_sigs.js
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ sigs = {
emscripten_promise_any__sig: 'pppp',
emscripten_promise_create__sig: 'p',
emscripten_promise_destroy__sig: 'vp',
emscripten_promise_race__sig: 'ppp',
emscripten_promise_resolve__sig: 'vpip',
emscripten_promise_then__sig: 'ppppp',
emscripten_random__sig: 'f',
Expand Down
8 changes: 8 additions & 0 deletions system/include/emscripten/promise.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@ __attribute__((warn_unused_result)) em_promise_t emscripten_promise_all_settled(
__attribute__((warn_unused_result)) em_promise_t emscripten_promise_any(
em_promise_t* promises, void** errors, size_t num_promises);

// Call Promise.race to create and return a new promise that settles once any of
// the `num_promises` input promises passed in `promises` has been settled. If
// the first input promise to settle is fulfilled, the resulting promise is
// fulfilled with the same value. Otherwise, if the first input promise to
// settle is rejected, the resulting promise is rejected with the same reason.
__attribute__((warn_unused_result)) em_promise_t
emscripten_promise_race(em_promise_t* promises, size_t num_promises);

#ifdef __cplusplus
}
#endif
41 changes: 40 additions & 1 deletion test/core/test_promise.c
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,42 @@ static em_promise_result_t test_any(void** result, void* data, void* value) {
return EM_PROMISE_MATCH_RELEASE;
}

static em_promise_result_t test_race(void** result, void* data, void* value) {
emscripten_console_log("test_race");
assert(data == (void*)7);

em_promise_t in[2] = {emscripten_promise_create(),
emscripten_promise_create()};
em_promise_t fulfill = emscripten_promise_race(in, 2);
em_promise_t fulfill_checked =
emscripten_promise_then(fulfill, expect_success, fail, NULL);
emscripten_promise_destroy(fulfill);
emscripten_promise_resolve(in[1], EM_PROMISE_FULFILL, (void*)42);
emscripten_promise_resolve(in[0], EM_PROMISE_REJECT, NULL);
emscripten_promise_destroy(in[0]);
emscripten_promise_destroy(in[1]);

in[0] = emscripten_promise_create();
in[1] = emscripten_promise_create();
em_promise_t reject = emscripten_promise_race(in, 2);
em_promise_t reject_checked =
emscripten_promise_then(reject, fail, expect_error, NULL);
emscripten_promise_destroy(reject);
emscripten_promise_resolve(in[0], EM_PROMISE_REJECT, (void*)42);
emscripten_promise_resolve(in[1], EM_PROMISE_FULFILL, NULL);
emscripten_promise_destroy(in[0]);
emscripten_promise_destroy(in[1]);

em_promise_t to_finish[2] = {fulfill_checked, reject_checked};
em_promise_t finish_test_race = emscripten_promise_all(to_finish, NULL, 0);

emscripten_promise_destroy(fulfill_checked);
emscripten_promise_destroy(reject_checked);

*result = finish_test_race;
return EM_PROMISE_MATCH_RELEASE;
}

static em_promise_result_t finish(void** result, void* data, void* value) {
emscripten_console_logf("finish");

Expand Down Expand Up @@ -509,8 +545,10 @@ int main() {
em_promise_t test5 =
emscripten_promise_then(test4, test_all_settled, fail, (void*)5);
em_promise_t test6 = emscripten_promise_then(test5, test_any, fail, (void*)6);
em_promise_t test7 =
emscripten_promise_then(test6, test_race, fail, (void*)7);
em_promise_t assert_stack =
emscripten_promise_then(test6, check_stack, fail, NULL);
emscripten_promise_then(test7, check_stack, fail, NULL);
em_promise_t end = emscripten_promise_then(assert_stack, finish, fail, NULL);

emscripten_promise_resolve(start, EM_PROMISE_FULFILL, NULL);
Expand All @@ -523,6 +561,7 @@ int main() {
emscripten_promise_destroy(test4);
emscripten_promise_destroy(test5);
emscripten_promise_destroy(test6);
emscripten_promise_destroy(test7);
emscripten_promise_destroy(assert_stack);
emscripten_promise_destroy(end);

Expand Down
3 changes: 3 additions & 0 deletions test/core/test_promise.out
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,7 @@ promise_any reasons:
42
43
44
test_race
expected success: 42
expected error: 42
finish

0 comments on commit 47cb9c6

Please sign in to comment.