diff --git a/moli-core/tests/scripts/document_close.rs b/moli-core/tests/scripts/document_close.rs index 1fa5cdac8a..41703ef023 100644 --- a/moli-core/tests/scripts/document_close.rs +++ b/moli-core/tests/scripts/document_close.rs @@ -122,3 +122,39 @@ async fn child_document_close_in_written_script_drains_tail_and_finishes_load() async fn child_document_close_in_external_writer_drains_tail_and_finishes_load() -> Result<()> { written_child_script_close_finishes_load(false, false, true).await } + +#[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 page = browser + .fetch(&markup_url(&server, "
initial")) + .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 da26930ac8..ac2835c395 100644 --- a/moli-renderer-v8/src/runtime/owner_local_store/bound.rs +++ b/moli-renderer-v8/src/runtime/owner_local_store/bound.rs @@ -623,7 +623,10 @@ pub(in crate::runtime) async fn advance_runtime_expression_await_turn_on_entry_v ) -> (LivePageEntry, Result