diff --git a/godot/src/test/testing_api.gd b/godot/src/test/testing_api.gd index b5711b54..4f4c1437 100644 --- a/godot/src/test/testing_api.gd +++ b/godot/src/test/testing_api.gd @@ -167,6 +167,10 @@ func async_take_and_compare_snapshot( dcl_rpc_sender ) + var pending_promises := Global.content_provider.get_pending_promises() + if not pending_promises.is_empty(): + await PromiseUtils.async_all(Global.content_provider.get_pending_promises()) + # TODO: make this configurable var hide_player := true diff --git a/rust/decentraland-godot-lib/src/content/content_provider.rs b/rust/decentraland-godot-lib/src/content/content_provider.rs index 73176d45..36bce7f4 100644 --- a/rust/decentraland-godot-lib/src/content/content_provider.rs +++ b/rust/decentraland-godot-lib/src/content/content_provider.rs @@ -429,6 +429,16 @@ impl ContentProvider { } Variant::nil() } + + #[func] + pub fn get_pending_promises(&self) -> Array> { + Array::from_iter( + self.cached + .iter() + .filter(|(_, entry)| !entry.promise.bind().is_resolved()) + .map(|(_, entry)| entry.promise.clone()), + ) + } } impl ContentProvider { diff --git a/rust/decentraland-godot-lib/src/dcl/js/engine.rs b/rust/decentraland-godot-lib/src/dcl/js/engine.rs index 8b07f73d..15719be8 100644 --- a/rust/decentraland-godot-lib/src/dcl/js/engine.rs +++ b/rust/decentraland-godot-lib/src/dcl/js/engine.rs @@ -30,6 +30,7 @@ pub fn ops() -> Vec { vec![ op_crdt_send_to_renderer::DECL, op_crdt_recv_from_renderer::DECL, + op_run_async::DECL, ] } @@ -79,6 +80,11 @@ fn op_crdt_send_to_renderer(op_state: Rc>, messages: &[u8]) { .expect("error sending scene response!!") } +#[op(v8)] +async fn op_run_async(op_state: Rc>) { + let _ = op_state.borrow_mut(); +} + #[op(v8)] async fn op_crdt_recv_from_renderer(op_state: Rc>) -> Vec> { let dying = op_state.borrow().borrow::().0; diff --git a/rust/decentraland-godot-lib/src/dcl/js/js_modules/utils.js b/rust/decentraland-godot-lib/src/dcl/js/js_modules/utils.js new file mode 100644 index 00000000..7d1ee07c --- /dev/null +++ b/rust/decentraland-godot-lib/src/dcl/js/js_modules/utils.js @@ -0,0 +1,3 @@ +module.exports.run_async = async function () { + await Deno.core.ops.op_run_async(); +} \ No newline at end of file diff --git a/rust/decentraland-godot-lib/src/dcl/js/mod.rs b/rust/decentraland-godot-lib/src/dcl/js/mod.rs index b8653db6..f514cc1a 100644 --- a/rust/decentraland-godot-lib/src/dcl/js/mod.rs +++ b/rust/decentraland-godot-lib/src/dcl/js/mod.rs @@ -254,6 +254,17 @@ pub(crate) fn scene_thread( Ok(script) => script, }; + let utils_script = rt.block_on(async { + runtime.execute_script("", ascii_str!("require (\"~utils.js\")")) + }); + let utils_script = match utils_script { + Err(e) => { + tracing::error!("[scene thread {scene_id:?}] utils script load error: {}", e); + return; + } + Ok(script) => script, + }; + let result = rt.block_on(async { run_script(&mut runtime, &script, "onStart", |_| Vec::new()).await }); if let Err(e) = result { @@ -261,9 +272,14 @@ pub(crate) fn scene_thread( return; } - rt.block_on(async { - let _ = runtime.run_event_loop(false).await; + // instead of using run_event_loop for polling, this is a workaround to resolve pending promises + let result = rt.block_on(async { + run_script(&mut runtime, &utils_script, "run_async", |_| Vec::new()).await }); + if let Err(e) = result { + tracing::error!("[scene thread {scene_id:?}] script load running: {}", e); + return; + } let start_time = std::time::SystemTime::now(); let mut elapsed = Duration::default(); @@ -382,6 +398,7 @@ fn op_require( match module_spec.as_str() { // user module load "~scene.js" => Ok(state.take::().0), + "~utils.js" => Ok(include_str!("js_modules/utils.js").to_owned()), // core module load "~system/CommunicationsController" => { Ok(include_str!("js_modules/CommunicationsController.js").to_owned())