diff --git a/Tests/LibWeb/Text/expected/navigation/populate-iframe-using-document-write.txt b/Tests/LibWeb/Text/expected/navigation/populate-iframe-using-document-write.txt
new file mode 100644
index 00000000000..3a2d263b041
--- /dev/null
+++ b/Tests/LibWeb/Text/expected/navigation/populate-iframe-using-document-write.txt
@@ -0,0 +1 @@
+ PASS (didn't crash)
diff --git a/Tests/LibWeb/Text/input/navigation/populate-iframe-using-document-write.html b/Tests/LibWeb/Text/input/navigation/populate-iframe-using-document-write.html
new file mode 100644
index 00000000000..92bef0e2bad
--- /dev/null
+++ b/Tests/LibWeb/Text/input/navigation/populate-iframe-using-document-write.html
@@ -0,0 +1,22 @@
+
+
+
+
diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp
index 87ae881d89b..fc113ee4ba9 100644
--- a/Userland/Libraries/LibWeb/DOM/Document.cpp
+++ b/Userland/Libraries/LibWeb/DOM/Document.cpp
@@ -567,6 +567,15 @@ WebIDL::ExceptionOr Document::run_the_document_write_steps(StringView inpu
// https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-document-open
WebIDL::ExceptionOr Document::open(Optional const&, Optional const&)
{
+ // If document belongs to a child navigable, we need to make sure its initial navigation is done,
+ // because subsequent steps will modify "initial about:blank" to false, which would cause
+ // initial navigation to fail in case it was "about:blank".
+ if (auto navigable = this->navigable(); navigable->container() && !navigable->container()->content_navigable_initialized()) {
+ HTML::main_thread_event_loop().spin_processing_tasks_with_source_until(HTML::Task::Source::NavigationAndTraversal, [navigable_container = navigable->container()] {
+ return navigable_container->content_navigable_initialized();
+ });
+ }
+
// 1. If document is an XML document, then throw an "InvalidStateError" DOMException exception.
if (m_type == Type::XML)
return WebIDL::InvalidStateError::create(realm(), "open() called on XML document."_fly_string);
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp
index 512fd0a119e..25fe51a80a0 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp
@@ -76,6 +76,12 @@ void HTMLIFrameElement::process_the_iframe_attributes(bool initial_insertion)
if (!content_navigable())
return;
+ // Make sure applying of history step caused by potential sync navigation to "about:blank"
+ // is finished. Otherwise, it might interrupt navigation caused by changing src or srcdoc.
+ if (!initial_insertion && !content_navigable_initialized()) {
+ main_thread_event_loop().spin_processing_tasks_with_source_until(Task::Source::NavigationAndTraversal, [this] { return content_navigable_initialized(); });
+ }
+
// 1. If element's srcdoc attribute is specified, then:
if (has_attribute(HTML::AttributeNames::srcdoc)) {
// 1. Set element's current navigation was lazy loaded boolean to false.
diff --git a/Userland/Libraries/LibWeb/HTML/NavigableContainer.h b/Userland/Libraries/LibWeb/HTML/NavigableContainer.h
index 1f899c22a7f..0fa07ff3859 100644
--- a/Userland/Libraries/LibWeb/HTML/NavigableContainer.h
+++ b/Userland/Libraries/LibWeb/HTML/NavigableContainer.h
@@ -51,6 +51,8 @@ public:
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#potentially-delays-the-load-event
bool currently_delays_the_load_event() const;
+ bool content_navigable_initialized() const { return m_content_navigable_initialized; }
+
protected:
NavigableContainer(DOM::Document&, DOM::QualifiedName);