Skip to content

Add MAIN_THREAD_EM_ASM_PROMISE_AWAIT - #23043

Open
hedwigz wants to merge 5 commits into
emscripten-core:mainfrom
hedwigz:inline-javascript-sync-awaitable-promises
Open

hedwigz wants to merge 5 commits into
emscripten-core:mainfrom
hedwigz:inline-javascript-sync-awaitable-promises

Conversation

@hedwigz

@hedwigz hedwigz commented Dec 1, 2024 •

Copy link
Copy Markdown

Introduce a new macro MAIN_THREAD_EM_ASM_PROMISE_AWAIT which is used to write JavaScript code that returns a promise and block the C code from progressing until the promise is resolved (or errors).

int main() {
  printf("1st print\n");
  // This call will block until the internal promise resolves (at least 1 second in this case) 
  MAIN_THREAD_EM_ASM_PROMISE_AWAIT({
    out('2nd print');
    // do some async operation that involves the main thread
    return new Promise((resolve,reject) => {
      setTimeout(() => {
        out('3rd print');
        resolve();
      }, 1000);
    });
  });
  printf("4th print\n");
  return 0;
}

The motivation for this was discussed before
We have multiple web workers, each of them calls javascript code which is async and has to be ran on the main thread and need to wait for the promise to be resolved.
I am open for suggestions on how to add this more elegantly

Comment thread src/library.js Outdated
Comment thread test/test_core.py Outdated
Comment thread test/core/test_main_thread_async_em_asm_promise_await.cpp Outdated
Comment thread src/library_pthread.js Outdated
@hedwigz

hedwigz commented Dec 6, 2024 •

Copy link
Copy Markdown
Author

@sbc100 Thanks for taking the time to review this. I addressed all of your comments and did the following:

  1. Added an error if the macro is called from main thread (and added test)
  2. Added support for receiving a return integer from the macro
  3. Added documentation
    LMK what you think :)

@hedwigz
hedwigz requested a review from sbc100 December 6, 2024 15:46
@hedwigz

hedwigz commented Dec 13, 2024

Copy link
Copy Markdown
Author

@sbc100 ping 🤞

Comment thread src/library.js Outdated
Comment thread src/library.js Outdated
Comment thread src/library.js Outdated
Comment thread src/library.js Outdated
Comment thread src/library_pthread.js Outdated
Comment thread system/lib/pthread/proxying.c Outdated
Comment thread system/lib/pthread/proxying.c

@sbc100 sbc100 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tlively would you mind taking a look, since this contains changes to proxying.c

Comment thread system/lib/pthread/proxying.c
@hedwigz

hedwigz commented Dec 14, 2024

Copy link
Copy Markdown
Author

@sbc100 @tlively 🙏 I really appreciate the thorough review and comments!
I addressed all of your comments and I think the code looks way better now.

@hedwigz
hedwigz requested review from sbc100 and tlively December 14, 2024 18:44

@tlively tlively left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, this looks a lot simpler overall, even though I agree that it's a little awkward to get the ctx into the right place. Thanks!

Comment thread system/lib/pthread/proxying.c Outdated
Comment thread system/lib/pthread/proxying.c Outdated
Comment thread system/lib/pthread/proxying.c Outdated
Comment thread system/lib/pthread/proxying.c Outdated
Comment thread system/lib/pthread/proxying.c Outdated
Comment thread system/lib/pthread/proxying.c
@hedwigz hedwigz closed this Dec 18, 2024
@hedwigz
hedwigz force-pushed the inline-javascript-sync-awaitable-promises branch from 5aef76b to 58889f9 Compare December 18, 2024 20:04
@hedwigz

hedwigz commented Dec 18, 2024 •

Copy link
Copy Markdown
Author

Great, this looks a lot simpler overall, even though I agree that it's a little awkward to get the ctx into the right place. Thanks!

I am sorry I completely messed up git while trying to rebase.

@hedwigz hedwigz reopened this Dec 18, 2024
@hedwigz
hedwigz force-pushed the inline-javascript-sync-awaitable-promises branch from 84fcbd2 to ae2357d Compare December 18, 2024 20:32
@hedwigz
hedwigz marked this pull request as ready for review December 18, 2024 20:37
@hedwigz

hedwigz commented Dec 18, 2024

Copy link
Copy Markdown
Author

@tlively any tips for passing all the CI tests?

@hedwigz
hedwigz requested a review from tlively December 18, 2024 20:37
@tlively

tlively commented Dec 18, 2024

Copy link
Copy Markdown
Member

proxying.c looks good to me.

It looks like the flake8 bot is failing because of a formatting issue. The other CI bots might be aborting early because of that issue. Merging in main to pick up any unrelated fixes could also help.

@sbc100

sbc100 commented Dec 18, 2024

Copy link
Copy Markdown
Collaborator

The fact that flake8 is being included at all in CI makes me think that perhaps you are not up-to-date on your branch? The flake8 step was replaced with a step call ruff few days back.

@sbc100

sbc100 commented Dec 18, 2024

Copy link
Copy Markdown
Collaborator

Can you try rebase onto to merging with the latest changes on main?

@hedwigz
hedwigz force-pushed the inline-javascript-sync-awaitable-promises branch from 464bc2f to 4416f4d Compare December 21, 2024 16:47
@sbc100

sbc100 commented Apr 3, 2025

Copy link
Copy Markdown
Collaborator

Any updates or blockers here? I'd like to see this land as well, we're also using workers that need to sync await some main thread code.

Hey @hybridherbst , glad to see more interest in this. The current blocker is that some wasm64 test fail. I was struggling making the test run on my machine due to the need in d8/node24

d8 you can get usinfg the jsvu tool.

node-canary you can you get from https://nodejs.org/download/v8-canary/

@hedwigz

hedwigz commented Apr 4, 2025

Copy link
Copy Markdown
Author

@sbc100 Thanks! I'll give it a go

@hedwigz
hedwigz force-pushed the inline-javascript-sync-awaitable-promises branch 4 times, most recently from 2803fc6 to be85c88 Compare April 5, 2025 17:46
@hedwigz

hedwigz commented Apr 7, 2025

Copy link
Copy Markdown
Author

@tlively @sbc100 All tests are now green :)

@hedwigz
hedwigz force-pushed the inline-javascript-sync-awaitable-promises branch 3 times, most recently from 5c1bd6b to fd5e213 Compare April 13, 2025 05:32
@hedwigz

hedwigz commented Apr 13, 2025

Copy link
Copy Markdown
Author

@sbc100 @tlively ping 😎

@sbc100 sbc100 changed the title WIP: await promise code from sync c Add MAIN_THREAD_EM_ASM_PROMISE_AWAIT Apr 16, 2025
Comment thread test/test_core.py Outdated
Comment thread test/test_core.py Outdated
Comment thread test/core/test_main_thread_async_em_asm_await_reject.cpp Outdated
Comment thread test/core/test_main_thread_async_em_asm_await_reject.cpp Outdated
Comment thread test/core/test_main_thread_async_em_asm_await_reject.cpp Outdated
Comment thread tools/link.py Outdated
@hedwigz
hedwigz force-pushed the inline-javascript-sync-awaitable-promises branch from fd5e213 to e6a8842 Compare May 1, 2025 10:49
@hedwigz
hedwigz force-pushed the inline-javascript-sync-awaitable-promises branch from f59165b to a43b9bd Compare May 24, 2025 13:22
Comment thread src/lib/libcore.js Outdated
Comment thread src/lib/libcore.js Outdated
Comment thread src/lib/libcore.js Outdated
Comment thread src/lib/libcore.js Outdated
Comment thread src/lib/libpthread.js Outdated
Comment thread src/lib/libpthread.js Outdated
Comment thread system/lib/pthread/proxying.c Outdated
Comment thread test/test_core.py Outdated
Comment thread test/test_core.py Outdated
Comment thread test/test_core.py Outdated
Comment thread test/core/test_main_thread_async_em_asm_await.cpp Outdated
Comment thread test/core/test_main_thread_async_em_asm_await_reject.cpp Outdated
@sbc100

sbc100 commented May 27, 2025

Copy link
Copy Markdown
Collaborator

Thanks for continuing to work on this.

Apologies for the review process taking so long. I had no imagined this being such an invasive change (i.e.changing the code proxying functions).

@hedwigz

hedwigz commented Jun 8, 2025

Copy link
Copy Markdown
Author

@sbc100 Thanks, I appreciate the continued work on this. I didn't have much time recently to cater to this PR. I'll hopefully get back to it soon.

@sbc100

sbc100 commented Mar 5, 2026

Copy link
Copy Markdown
Collaborator

Sorry for the long delay on this.

I've since landed a JS library feature that is kind of like this one: #26000. So I think i now have a much better understanding of the use case.

Would you have time to rebase this and we can see about landing it?

@hedwigz
hedwigz force-pushed the inline-javascript-sync-awaitable-promises branch from dfb5e54 to 7b8b384 Compare September 14, 2026 11:35
Co-authored-by: Cursor <cursoragent@cursor.com>
@hedwigz

hedwigz commented Sep 14, 2026

Copy link
Copy Markdown
Author

@sbc100 Hey, I rebased it and addressed all of your comments

@hedwigz
hedwigz requested a review from sbc100 September 14, 2026 16:17
@sbc100

sbc100 commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

@guybedford WDYT of this extra macro/tool?

Comment thread src/lib/libpthread.js
rtn.then((rtn) => __emscripten_run_js_on_main_thread_done(ctx, ctxArgs, rtn));
rtn.then(
(rtn) => __emscripten_run_js_on_main_thread_done(ctx, ctxArgs, rtn),
() => __emscripten_run_js_on_main_thread_done(ctx, ctxArgs, 0),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean we always return zero on promise rejection? Is this needed? What is we have a function that uses a zero return to mean something else?

Do you need this feature? Maybe we should leave it out for the initial version?

Inside MAIN_THREAD_EM_ASM_AWAIT: 42 3.5
Inside asyncOp
After MAIN_THREAD_EM_ASM_AWAIT
result: 2 No newline at end of file

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing newline here


int main() {
emscripten_out("Before MAIN_THREAD_EM_ASM_AWAIT");
int res = MAIN_THREAD_EM_ASM_AWAIT({

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might it be nice if we could use await inside these functions?

i.e. should we mark these function snippets as async on the JS side?

Comment thread src/lib/libcore.js
#if ASSERTIONS
assert(ENVIRONMENT_IS_PTHREAD, 'emscripten_asm_const_int_await_on_main_thread is not available on the main thread');
#endif
return runMainThreadEmAsm(emAsmAddr, sigPtr, argbuf, 2);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if these is some way we can avoid the magic number here?

How about {{{ PROXY_SYNC_ASYNC }}}?

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants