diff --git a/moli-core/tests/scripts.rs b/moli-core/tests/scripts.rs index ae0f638343..48dd9be026 100644 --- a/moli-core/tests/scripts.rs +++ b/moli-core/tests/scripts.rs @@ -6711,3 +6711,40 @@ async fn parse_time_lifecycle_queue_can_stop_cleanly_at_load_stage_after_load_mi #[path = "scripts/document_write_errors.rs"] mod document_write_errors; + +#[tokio::test(flavor = "multi_thread")] +async fn main_document_close_can_resolve_an_awaited_lifecycle_promise() -> Result<()> { + let server = FixtureServer::spawn().await?; + let browser = Browser::new(AppConfig::default())?; + let mut url = url::Url::parse(&server.url("/compat/child-dynamic-markup-document"))?; + url.query_pairs_mut() + .append_pair("markup", "
initial"); + let mut page = browser.fetch(url.as_str()).await?; + let result = tokio::time::timeout( + Duration::from_secs(10), + page.evaluate_runtime_expression_with_await_async( + r#"new Promise(resolve => { + document.open(); + document.addEventListener('DOMContentLoaded', () => resolve(JSON.stringify({ + readyState: document.readyState, + text: document.getElementById('replacement').textContent + })), {once: true}); + document.write('replacement
'); + document.close(); + })"#, + true, + ), + ) + .await??; + let observed: serde_json::Value = serde_json::from_str( + result["value"] + .as_str() + .expect("replacement lifecycle observation"), + )?; + assert_eq!( + observed, + serde_json::json!({"readyState": "interactive", "text": "replacement"}) + ); + server.shutdown().await; + Ok(()) +} diff --git a/moli-renderer-v8/src/runtime/owner_local_store/bound.rs b/moli-renderer-v8/src/runtime/owner_local_store/bound.rs index 8db6c47677..0ade1057b1 100644 --- a/moli-renderer-v8/src/runtime/owner_local_store/bound.rs +++ b/moli-renderer-v8/src/runtime/owner_local_store/bound.rs @@ -592,7 +592,10 @@ pub(in crate::runtime) async fn advance_runtime_expression_await_turn_on_entry_v ) -> (LivePageEntry, Result