@@ -270,82 +270,83 @@ var LibraryPThread = {
270270 PThread . tlsInitFunctions . forEach ( ( f ) => f ( ) ) ;
271271 } ,
272272 // Loads the WebAssembly module into the given Worker.
273- // onFinishedLoading: A callback function that will be called once all of
274- // the workers have been initialized and are
275- // ready to host pthreads.
276- loadWasmModuleToWorker : ( worker ) => new Promise ( ( onFinishedLoading ) => {
277- worker . onmessage = ( e ) => {
278- var d = e [ 'data' ] ;
279- var cmd = d . cmd ;
280- #if PTHREADS_DEBUG
281- dbg ( `main thread: received message '${ cmd } ' from worker. ${ d } ` ) ;
282- #endif
283-
284- // If this message is intended to a recipient that is not the main
285- // thread, forward it to the target thread.
286- if ( d . targetThread && d . targetThread != _pthread_self ( ) ) {
287- var targetWorker = PThread . pthreads [ d . targetThread ] ;
288- if ( targetWorker ) {
289- targetWorker . postMessage ( d , d . transferList ) ;
290- } else {
291- err ( `worker sent message (${ cmd } ) to pthread (${ d . targetThread } ) that no longer exists` ) ;
273+ // @returns : A promise the resolves once the worker has loaded the wasm module
274+ // and is ready to run a pthread.
275+ loadWasmModuleToWorker : ( worker ) => {
276+ worker . loaded = new Promise ( ( onFinishedLoading ) => {
277+ worker . onmessage = ( e ) => {
278+ var d = e [ 'data' ] ;
279+ var cmd = d . cmd ;
280+ #if PTHREADS_DEBUG
281+ dbg ( `main thread: received message '${ cmd } ' from worker. ${ d } ` ) ;
282+ #endif
283+
284+ // If this message is intended to a recipient that is not the main
285+ // thread, forward it to the target thread.
286+ if ( d . targetThread && d . targetThread != _pthread_self ( ) ) {
287+ var targetWorker = PThread . pthreads [ d . targetThread ] ;
288+ if ( targetWorker ) {
289+ targetWorker . postMessage ( d , d . transferList ) ;
290+ } else {
291+ err ( `worker sent message (${ cmd } ) to pthread (${ d . targetThread } ) that no longer exists` ) ;
292+ }
293+ return ;
292294 }
293- return ;
294- }
295295
296- if ( d === 'setimmediate' ) {
297- // Worker wants to postMessage() to itself to implement setImmediate()
298- // emulation.
299- worker . postMessage ( d ) ;
300- return ;
301- }
296+ if ( d === 'setimmediate' ) {
297+ // Worker wants to postMessage() to itself to implement setImmediate()
298+ // emulation.
299+ worker . postMessage ( d ) ;
300+ return ;
301+ }
302302
303- switch ( cmd ) {
304- case { { { CMD_CHECK_MAILBOX } } } :
305- checkMailbox ( ) ;
306- break ;
307- case { { { CMD_SPAWN_THREAD } } } :
308- spawnThread ( d ) ;
309- break ;
310- case { { { CMD_CLEANUP_THREAD } } } :
311- // cleanupThread needs to be run via callUserCallback since it calls
312- // back into user code to free thread data. Without this it's possible
313- // the unwind or ExitStatus exception could escape here.
314- callUserCallback ( ( ) => cleanupThread ( d . thread ) ) ;
303+ switch ( cmd ) {
304+ case { { { CMD_CHECK_MAILBOX } } } :
305+ checkMailbox ( ) ;
306+ break ;
307+ case { { { CMD_SPAWN_THREAD } } } :
308+ spawnThread ( d ) ;
309+ break ;
310+ case { { { CMD_CLEANUP_THREAD } } } :
311+ // cleanupThread needs to be run via callUserCallback since it calls
312+ // back into user code to free thread data. Without this it's possible
313+ // the unwind or ExitStatus exception could escape here.
314+ callUserCallback ( ( ) => cleanupThread ( d . thread ) ) ;
315315#if MAIN_MODULE
316- case { { { CMD_MARK_AS_FINISHED } } } :
317- markAsFinished ( d . thread ) ;
318- break ;
316+ case { { { CMD_MARK_AS_FINISHED } } } :
317+ markAsFinished ( d . thread ) ;
318+ break ;
319319#endif
320- case { { { CMD_LOADED } } } :
320+ case { { { CMD_LOADED } } } :
321321#if ENVIRONMENT_MAY_BE_NODE
322- if ( ENVIRONMENT_IS_NODE && ! worker . strongref ) {
323- // Once worker is loaded & idle, mark it as weakly referenced,
324- // so that mere existence of a Worker in the pool does not prevent
325- // Node.js from exiting the app.
326- worker. unref ( ) ;
327- }
328- #endif
329- onFinishedLoading ( worker ) ;
330- break ;
322+ if ( ENVIRONMENT_IS_NODE && ! worker . strongref ) {
323+ // Once worker is loaded & idle, mark it as weakly referenced,
324+ // so that mere existence of a Worker in the pool does not prevent
325+ // Node.js from exiting the app.
326+ worker. unref ( ) ;
327+ }
328+ #endif
329+ onFinishedLoading ( ) ;
330+ break ;
331331#if ENVIRONMENT_MAY_BE_NODE
332- case { { { CMD_UNCAUGHT_EXN } } } :
333- // Message handler for Node.js specific out-of-order behavior:
334- // https://github.com/nodejs/node/issues/59617
335- // A pthread sent an uncaught exception event. Re-raise it on the main thread.
336- worker . onerror ( d . error ) ;
337- break ;
338- #endif
339- case { { { CMD_CALL_HANDLER } } } :
340- Module [ d . handler ] ( ...d . args ) ;
341- break ;
342- default :
343- // The received message looks like something that should be handled by this message
344- // handler, (since there is a e.data.cmd field present), but is not one of the
345- // recognized commands:
346- if ( cmd ) err ( `worker sent an unknown command ${ cmd } ` ) ;
347- }
348- } ;
332+ case { { { CMD_UNCAUGHT_EXN } } } :
333+ // Message handler for Node.js specific out-of-order behavior:
334+ // https://github.com/nodejs/node/issues/59617
335+ // A pthread sent an uncaught exception event. Re-raise it on the main thread.
336+ worker . onerror ( d . error ) ;
337+ break ;
338+ #endif
339+ case { { { CMD_CALL_HANDLER } } } :
340+ Module [ d . handler ] ( ...d . args ) ;
341+ break ;
342+ default :
343+ // The received message looks like something that should be handled by this message
344+ // handler, (since there is a e.data.cmd field present), but is not one of the
345+ // recognized commands:
346+ if ( cmd ) err ( `worker sent an unknown command ${ cmd } ` ) ;
347+ }
348+ } ;
349+ } ) ;
349350
350351 worker . onerror = ( e ) => {
351352 var message = 'worker sent an error!' ;
@@ -442,7 +443,9 @@ var LibraryPThread = {
442443 'workerID' : worker . workerID ,
443444#endif
444445 } ) ;
445- } ) ,
446+
447+ return worker . loaded ;
448+ } ,
446449
447450#if PTHREAD_POOL_SIZE
448451 async loadWasmModuleToAllWorkers ( ) {
@@ -729,7 +732,11 @@ var LibraryPThread = {
729732#endif
730733 // Ask the worker to start executing its pthread entry point function.
731734 worker . postMessage ( msg , threadParams . transferList ) ;
735+ #if ASYNCIFY
736+ return worker . loaded ;
737+ #else
732738 return 0 ;
739+ #endif
733740 } ,
734741
735742 _emscripten_init_main_thread_js : ( tb ) => {
@@ -774,6 +781,11 @@ var LibraryPThread = {
774781 // allocations from __pthread_create_js we could also remove this.
775782 __pthread_create_js__noleakcheck : true ,
776783#endif
784+ // Pthread creation is async when possible. This allows us to return to the
785+ // event loop and wait for the Worker to be created.
786+ // This is needed in browsers where synchronous worker creation is still not
787+ // possible: <BUG_LINK>
788+ __pthread_create_js__async : 'auto' ,
777789 __pthread_create_js__deps : [ '$spawnThread' , '$pthreadCreateProxied' ,
778790 'emscripten_has_threading_support' ,
779791#if OFFSCREENCANVAS_SUPPORT
0 commit comments