diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.cpp b/Userland/Libraries/LibWeb/HTML/Navigable.cpp
index e8c505fbf91..a69bfc4212b 100644
--- a/Userland/Libraries/LibWeb/HTML/Navigable.cpp
+++ b/Userland/Libraries/LibWeb/HTML/Navigable.cpp
@@ -382,7 +382,7 @@ Navigable::ChosenNavigable Navigable::choose_a_navigable(StringView name, Tokeni
else {
// --> If current's active window does not have transient activation and the user agent has been configured to
// not show popups (i.e., the user agent has a "popup blocker" enabled)
- if (!active_window()->has_transient_activation() && traversable_navigable()->page().should_block_pop_ups()) {
+ if (active_window() && !active_window()->has_transient_activation() && traversable_navigable()->page().should_block_pop_ups()) {
// FIXME: The user agent may inform the user that a popup has been blocked.
dbgln("Pop-up blocked!");
}
@@ -590,6 +590,7 @@ static JS::GCPtr attempt_to_create_a_non_fetch_scheme_document(No
static WebIDL::ExceptionOr> create_navigation_params_from_a_srcdoc_resource(JS::GCPtr entry, JS::GCPtr navigable, TargetSnapshotParams const& target_snapshot_params, Optional navigation_id)
{
auto& vm = navigable->vm();
+ VERIFY(navigable->active_window());
auto& realm = navigable->active_window()->realm();
// 1. Let documentResource be entry's document state's resource.
@@ -670,6 +671,7 @@ static WebIDL::ExceptionOr> create_navigation
static WebIDL::ExceptionOr create_navigation_params_by_fetching(JS::GCPtr entry, JS::GCPtr navigable, SourceSnapshotParams const& source_snapshot_params, TargetSnapshotParams const& target_snapshot_params, CSPNavigationType csp_navigation_type, Optional navigation_id)
{
auto& vm = navigable->vm();
+ VERIFY(navigable->active_window());
auto& realm = navigable->active_window()->realm();
auto& active_document = *navigable->active_document();
@@ -1045,6 +1047,10 @@ WebIDL::ExceptionOr Navigable::populate_session_history_entry_document(
bool allow_POST,
JS::GCPtr> completion_steps)
{
+ // AD-HOC: Not in the spec but subsequent steps will fail if the navigable doesn't have an active window.
+ if (!active_window())
+ return {};
+
// FIXME: 1. Assert: this is running in parallel.
// 2. Assert: if navigationParams is non-null, then navigationParams's response is non-null.
@@ -1093,8 +1099,8 @@ WebIDL::ExceptionOr Navigable::populate_session_history_entry_document(
}
}
- // NOTE: Not in the spec but queuing task on the next step will fail because active_window() does not exist for destroyed navigable.
- if (has_been_destroyed())
+ // AD-HOC: Not in the spec but subsequent steps will fail if the navigable doesn't have an active window.
+ if (!active_window())
return {};
// 6. Queue a global task on the navigation and traversal task source, given navigable's active window, to run these steps:
@@ -1206,6 +1212,10 @@ WebIDL::ExceptionOr Navigable::populate_session_history_entry_document(
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigate
WebIDL::ExceptionOr Navigable::navigate(NavigateParams params)
{
+ // AD-HOC: Not in the spec but subsequent steps will fail if the navigable doesn't have an active window.
+ if (!active_window())
+ return {};
+
auto const& url = params.url;
auto source_document = params.source_document;
auto const& document_resource = params.document_resource;
@@ -1318,6 +1328,7 @@ WebIDL::ExceptionOr Navigable::navigate(NavigateParams params)
// 18. If url's scheme is "javascript", then:
if (url.scheme() == "javascript"sv) {
// 1. Queue a global task on the navigation and traversal task source given navigable's active window to navigate to a javascript: URL given navigable, url, historyHandling, initiatorOriginSnapshot, and cspNavigationType.
+ VERIFY(active_window());
queue_global_task(Task::Source::NavigationAndTraversal, *active_window(), JS::create_heap_function(heap(), [this, url, history_handling, initiator_origin_snapshot, csp_navigation_type, navigation_id] {
(void)navigate_to_a_javascript_url(url, to_history_handling_behavior(history_handling), initiator_origin_snapshot, csp_navigation_type, navigation_id);
}));
@@ -1334,6 +1345,7 @@ WebIDL::ExceptionOr Navigable::navigate(NavigateParams params)
// then:
if (user_involvement != UserNavigationInvolvement::BrowserUI && active_document.origin().is_same_origin_domain(source_document->origin()) && !active_document.is_initial_about_blank() && Fetch::Infrastructure::is_fetch_scheme(url.scheme())) {
// 1. Let navigation be navigable's active window's navigation API.
+ VERIFY(active_window());
auto navigation = active_window()->navigation();
// 2. Let entryListForFiring be formDataEntryList if documentResource is a POST resource; otherwise, null.
@@ -1363,8 +1375,8 @@ WebIDL::ExceptionOr Navigable::navigate(NavigateParams params)
// 20. In parallel, run these steps:
Platform::EventLoopPlugin::the().deferred_invoke([this, source_snapshot_params, target_snapshot_params, csp_navigation_type, document_resource, url, navigation_id, referrer_policy, initiator_origin_snapshot, response, history_handling, initiator_base_url_snapshot] {
- // NOTE: Not in the spec but subsequent steps will fail because destroyed navigable does not have active document.
- if (has_been_destroyed()) {
+ // AD-HOC: Not in the spec but subsequent steps will fail if the navigable doesn't have an active window.
+ if (!active_window()) {
set_delaying_load_events(false);
return;
}
@@ -1381,6 +1393,12 @@ WebIDL::ExceptionOr Navigable::navigate(NavigateParams params)
return;
}
+ // AD-HOC: Not in the spec but subsequent steps will fail if the navigable doesn't have an active window.
+ if (!active_window()) {
+ set_delaying_load_events(false);
+ return;
+ }
+
// 3. Queue a global task on the navigation and traversal task source given navigable's active window to abort a document and its descendants given navigable's active document.
queue_global_task(Task::Source::NavigationAndTraversal, *active_window(), JS::create_heap_function(heap(), [this] {
VERIFY(this->active_document());
@@ -1455,6 +1473,7 @@ WebIDL::ExceptionOr Navigable::navigate_to_a_fragment(URL::URL const& url,
(void)navigation_id;
// 1. Let navigation be navigable's active window's navigation API.
+ VERIFY(active_window());
auto navigation = active_window()->navigation();
// 2. Let destinationNavigationAPIState be navigable's active session history entry's navigation API state.
@@ -1540,6 +1559,7 @@ WebIDL::ExceptionOr Navigable::navigate_to_a_fragment(URL::URL const& url,
WebIDL::ExceptionOr> Navigable::evaluate_javascript_url(URL::URL const& url, URL::Origin const& new_document_origin, String navigation_id)
{
auto& vm = this->vm();
+ VERIFY(active_window());
auto& realm = active_window()->realm();
// 1. Let urlString be the result of running the URL serializer on url.
@@ -2058,8 +2078,13 @@ void Navigable::inform_the_navigation_api_about_aborting_navigation()
// FIXME: 1. If this algorithm is running on navigable's active window's relevant agent's event loop, then continue on to the following steps.
// Otherwise, queue a global task on the navigation and traversal task source given navigable's active window to run the following steps.
+ // AD-HOC: Not in the spec but subsequent steps will fail if the navigable doesn't have an active window.
+ if (!active_window())
+ return;
+
queue_global_task(Task::Source::NavigationAndTraversal, *active_window(), JS::create_heap_function(heap(), [this] {
// 2. Let navigation be navigable's active window's navigation API.
+ VERIFY(active_window());
auto navigation = active_window()->navigation();
// 3. If navigation's ongoing navigate event is null, then return.
diff --git a/Userland/Libraries/LibWeb/HTML/TraversableNavigable.cpp b/Userland/Libraries/LibWeb/HTML/TraversableNavigable.cpp
index 54ee97d77b4..3570b5c193c 100644
--- a/Userland/Libraries/LibWeb/HTML/TraversableNavigable.cpp
+++ b/Userland/Libraries/LibWeb/HTML/TraversableNavigable.cpp
@@ -497,6 +497,8 @@ TraversableNavigable::HistoryStepResult TraversableNavigable::apply_the_history_
// 12. For each navigable of changingNavigables, queue a global task on the navigation and traversal task source of navigable's active window to run the steps:
for (auto& navigable : changing_navigables) {
+ if (!navigable->active_window())
+ continue;
queue_global_task(Task::Source::NavigationAndTraversal, *navigable->active_window(), JS::create_heap_function(heap(), [&] {
// NOTE: This check is not in the spec but we should not continue navigation if navigable has been destroyed.
if (navigable->has_been_destroyed()) {
@@ -627,6 +629,7 @@ TraversableNavigable::HistoryStepResult TraversableNavigable::apply_the_history_
// navigable's active window to run afterDocumentPopulated.
Platform::EventLoopPlugin::the().deferred_invoke([populated_target_entry, potentially_target_specific_source_snapshot_params, target_snapshot_params, this, allow_POST, navigable, after_document_populated = JS::create_heap_function(this->heap(), move(after_document_populated))] {
navigable->populate_session_history_entry_document(populated_target_entry, *potentially_target_specific_source_snapshot_params, target_snapshot_params, {}, Empty {}, CSPNavigationType::Other, allow_POST, JS::create_heap_function(this->heap(), [this, after_document_populated, populated_target_entry]() mutable {
+ VERIFY(active_window());
queue_global_task(Task::Source::NavigationAndTraversal, *active_window(), JS::create_heap_function(this->heap(), [after_document_populated, populated_target_entry]() mutable {
after_document_populated->function()(true, populated_target_entry);
}));
@@ -753,6 +756,7 @@ TraversableNavigable::HistoryStepResult TraversableNavigable::apply_the_history_
navigable->set_ongoing_navigation({});
// 2. Queue a global task on the navigation and traversal task source given navigable's active window to perform afterPotentialUnloads.
+ VERIFY(navigable->active_window());
queue_global_task(Task::Source::NavigationAndTraversal, *navigable->active_window(), after_potential_unload);
}
// 11. Otherwise:
@@ -787,6 +791,7 @@ TraversableNavigable::HistoryStepResult TraversableNavigable::apply_the_history_
continue;
}
+ VERIFY(navigable->active_window());
queue_global_task(Task::Source::NavigationAndTraversal, *navigable->active_window(), JS::create_heap_function(heap(), [&] {
// NOTE: This check is not in the spec but we should not continue navigation if navigable has been destroyed.
if (navigable->has_been_destroyed()) {
@@ -880,6 +885,7 @@ TraversableNavigable::CheckIfUnloadingIsCanceledResult TraversableNavigable::che
}
// 5. Queue a global task on the navigation and traversal task source given traversable's active window to perform the following steps:
+ VERIFY(traversable->active_window());
queue_global_task(Task::Source::NavigationAndTraversal, *traversable->active_window(), JS::create_heap_function(heap(), [&] {
// 1. if needsBeforeunload is true, then:
if (needs_beforeunload) {
@@ -900,6 +906,7 @@ TraversableNavigable::CheckIfUnloadingIsCanceledResult TraversableNavigable::che
return;
// 3. Let navigation be traversable's active window's navigation API.
+ VERIFY(traversable->active_window());
auto navigation = traversable->active_window()->navigation();
// 4. Let navigateEventResult be the result of firing a traverse navigate event at navigation given targetEntry and userInvolvementForNavigateEvent.