-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement emscripten_promise_any
in promise.h
#19153
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -334,13 +334,131 @@ test_all_settled(void** result, void* data, void* value) { | |
emscripten_promise_destroy(null_in[2]); | ||
|
||
em_promise_t to_finish[3] = {empty_checked, full_checked, null_checked}; | ||
em_promise_t finish_test_all = emscripten_promise_all(to_finish, NULL, 3); | ||
em_promise_t finish_test_all_settled = | ||
emscripten_promise_all(to_finish, NULL, 3); | ||
|
||
emscripten_promise_destroy(empty_checked); | ||
emscripten_promise_destroy(full_checked); | ||
emscripten_promise_destroy(null_checked); | ||
|
||
*result = finish_test_all; | ||
*result = finish_test_all_settled; | ||
return EM_PROMISE_MATCH_RELEASE; | ||
} | ||
|
||
typedef struct promise_any_state { | ||
size_t size; | ||
em_promise_t in[3]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What are these There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These are the (up to) 3 input promises. They're not actually needed after the initial call to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm confused, I don't see any mention of a limit of 3 on input promises in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, this is just used in this test file, which arbitrarily chooses to call the API with three promises. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh ok, sorry, that's what I was missing... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, this C API is a little funky because 100% of the implementation is in JS. There's no .c implementation file for the API at all. |
||
void* expected; | ||
void* err[3]; | ||
void* expected_err[3]; | ||
} promise_any_state; | ||
|
||
static em_promise_result_t | ||
check_promise_any_result(void** result, void* data, void* value) { | ||
promise_any_state* state = (promise_any_state*)data; | ||
emscripten_console_logf("promise_any result: %ld", (uintptr_t)value); | ||
assert(value == state->expected); | ||
free(state); | ||
return EM_PROMISE_FULFILL; | ||
} | ||
|
||
static em_promise_result_t | ||
check_promise_any_err(void** result, void* data, void* value) { | ||
promise_any_state* state = (promise_any_state*)data; | ||
assert(value == state->err); | ||
emscripten_console_log("promise_any reasons:"); | ||
for (size_t i = 0; i < state->size; ++i) { | ||
emscripten_console_logf("%ld", (uintptr_t)state->err[i]); | ||
assert(state->err[i] == state->expected_err[i]); | ||
} | ||
free(state); | ||
return EM_PROMISE_FULFILL; | ||
} | ||
|
||
static em_promise_result_t test_any(void** result, void* data, void* value) { | ||
emscripten_console_log("test_any"); | ||
assert(data == (void*)6); | ||
|
||
// No input should be handled ok and be rejected. | ||
promise_any_state* state = malloc(sizeof(promise_any_state)); | ||
*state = (promise_any_state){ | ||
.size = 0, .in = {}, .expected = NULL, .err = {}, .expected_err = {}}; | ||
em_promise_t empty = | ||
emscripten_promise_any(state->in, state->err, state->size); | ||
em_promise_t empty_checked = | ||
emscripten_promise_then(empty, fail, check_promise_any_err, state); | ||
emscripten_promise_destroy(empty); | ||
|
||
// The first fulfilled promise should be propagated. | ||
state = malloc(sizeof(promise_any_state)); | ||
*state = (promise_any_state){.size = 3, | ||
.in = {emscripten_promise_create(), | ||
emscripten_promise_create(), | ||
emscripten_promise_create()}, | ||
.expected = (void*)42, | ||
.err = {}, | ||
.expected_err = {}}; | ||
em_promise_t full = | ||
emscripten_promise_any(state->in, state->err, state->size); | ||
em_promise_t full_checked = | ||
emscripten_promise_then(full, check_promise_any_result, fail, state); | ||
emscripten_promise_destroy(full); | ||
emscripten_promise_resolve(state->in[0], EM_PROMISE_REJECT, (void*)41); | ||
emscripten_promise_resolve(state->in[1], EM_PROMISE_FULFILL, (void*)42); | ||
emscripten_promise_resolve(state->in[2], EM_PROMISE_FULFILL, (void*)43); | ||
emscripten_promise_destroy(state->in[0]); | ||
emscripten_promise_destroy(state->in[1]); | ||
emscripten_promise_destroy(state->in[2]); | ||
|
||
// If all promises are rejected, the result will be rejected with the reasons. | ||
state = malloc(sizeof(promise_any_state)); | ||
*state = | ||
(promise_any_state){.size = 3, | ||
.in = {emscripten_promise_create(), | ||
emscripten_promise_create(), | ||
emscripten_promise_create()}, | ||
.expected = NULL, | ||
.err = {}, | ||
.expected_err = {(void*)42, (void*)43, (void*)44}}; | ||
em_promise_t rejected = | ||
emscripten_promise_any(state->in, state->err, state->size); | ||
em_promise_t rejected_checked = | ||
emscripten_promise_then(rejected, fail, check_promise_any_err, state); | ||
emscripten_promise_destroy(rejected); | ||
emscripten_promise_resolve(state->in[0], EM_PROMISE_REJECT, (void*)42); | ||
emscripten_promise_resolve(state->in[1], EM_PROMISE_REJECT, (void*)43); | ||
emscripten_promise_resolve(state->in[2], EM_PROMISE_REJECT, (void*)44); | ||
emscripten_promise_destroy(state->in[0]); | ||
emscripten_promise_destroy(state->in[1]); | ||
emscripten_promise_destroy(state->in[2]); | ||
|
||
// Same, but now the error reason buffer is null. | ||
em_promise_t null_in[3] = { | ||
emscripten_promise_create(), | ||
emscripten_promise_create(), | ||
emscripten_promise_create(), | ||
}; | ||
em_promise_t null = emscripten_promise_any(null_in, NULL, 3); | ||
em_promise_t null_checked = | ||
emscripten_promise_then(null, fail, check_null, NULL); | ||
emscripten_promise_destroy(null); | ||
emscripten_promise_resolve(null_in[0], EM_PROMISE_REJECT, (void*)42); | ||
emscripten_promise_resolve(null_in[1], EM_PROMISE_REJECT, (void*)43); | ||
emscripten_promise_resolve(null_in[2], EM_PROMISE_REJECT, (void*)44); | ||
emscripten_promise_destroy(null_in[0]); | ||
emscripten_promise_destroy(null_in[1]); | ||
emscripten_promise_destroy(null_in[2]); | ||
|
||
em_promise_t to_finish[4] = { | ||
empty_checked, full_checked, rejected_checked, null_checked}; | ||
em_promise_t finish_test_any = emscripten_promise_all(to_finish, NULL, 4); | ||
|
||
emscripten_promise_destroy(empty_checked); | ||
emscripten_promise_destroy(full_checked); | ||
emscripten_promise_destroy(rejected_checked); | ||
emscripten_promise_destroy(null_checked); | ||
|
||
*result = finish_test_any; | ||
return EM_PROMISE_MATCH_RELEASE; | ||
} | ||
|
||
|
@@ -390,8 +508,9 @@ int main() { | |
em_promise_t test4 = emscripten_promise_then(test3, test_all, fail, (void*)4); | ||
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 assert_stack = | ||
emscripten_promise_then(test5, check_stack, fail, NULL); | ||
emscripten_promise_then(test6, check_stack, fail, NULL); | ||
em_promise_t end = emscripten_promise_then(assert_stack, finish, fail, NULL); | ||
|
||
emscripten_promise_resolve(start, EM_PROMISE_FULFILL, NULL); | ||
|
@@ -403,6 +522,7 @@ int main() { | |
emscripten_promise_destroy(test3); | ||
emscripten_promise_destroy(test4); | ||
emscripten_promise_destroy(test5); | ||
emscripten_promise_destroy(test6); | ||
emscripten_promise_destroy(assert_stack); | ||
emscripten_promise_destroy(end); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could do something more like this.. but its probably not worth it?:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, just having this assertion seems more general. For example it would work in old browsers that don't support Promise.any as well. I'd be happy to make the assertion message more useful, but I think the current message at least delivers the most important piece of information.