LibWeb: Wait for initial navigation to complete before modifying iframe
If initial src of an iframe is "about:blank", it does synchronous navigation that is not supposed to be interleaved by other navigation or usage of Document.open(). Fixes crashing in navigation on https://twinings.co.uk/
This commit is contained in:
parent
aada06757b
commit
a3149c1ce9
Notes:
sideshowbarker
2024-07-17 03:05:16 +09:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/SerenityOS/serenity/commit/a3149c1ce9 Pull-request: https://github.com/SerenityOS/serenity/pull/23889 Reviewed-by: https://github.com/awesomekling
5 changed files with 40 additions and 0 deletions
|
@ -0,0 +1 @@
|
|||
PASS (didn't crash)
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="../include.js"></script>
|
||||
<body></body>
|
||||
<script>
|
||||
const iframe = document.createElement("iframe");
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
const iframeDocument = iframe.contentDocument;
|
||||
|
||||
iframeDocument.open();
|
||||
iframeDocument.write(
|
||||
"<!DOCTYPE html><html><head><title>Iframe Content</title></head><body>"
|
||||
);
|
||||
iframeDocument.write("<h1>Hello</h1>");
|
||||
iframeDocument.write("<p>from iframe</p>");
|
||||
iframeDocument.write("</body></html>");
|
||||
iframeDocument.close();
|
||||
|
||||
test(() => {
|
||||
println("PASS (didn't crash)");
|
||||
})
|
||||
</script>
|
|
@ -567,6 +567,15 @@ WebIDL::ExceptionOr<void> Document::run_the_document_write_steps(StringView inpu
|
|||
// https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-document-open
|
||||
WebIDL::ExceptionOr<Document*> Document::open(Optional<String> const&, Optional<String> 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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue