LibWeb: Update update_for_history_step_application

Update 'update_for_history_step_application' to meet some of the specs
introduced in https://github.com/whatwg/html/pull/9856 and in
https://github.com/whatwg/html/pull/9990
This commit is contained in:
mobounya 2024-07-21 23:09:20 +01:00 committed by Alexander Kalenik
parent 1039561280
commit 2497f43989
Notes: github-actions[bot] 2024-07-22 08:40:39 +00:00
4 changed files with 43 additions and 19 deletions

View file

@ -4171,8 +4171,10 @@ void Document::restore_the_history_object_state(JS::NonnullGCPtr<HTML::SessionHi
}
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#update-document-for-history-step-application
void Document::update_for_history_step_application(JS::NonnullGCPtr<HTML::SessionHistoryEntry> entry, bool do_not_reactivate, size_t script_history_length, size_t script_history_index, Optional<Vector<JS::NonnullGCPtr<HTML::SessionHistoryEntry>>> entries_for_navigation_api, bool update_navigation_api)
void Document::update_for_history_step_application(JS::NonnullGCPtr<HTML::SessionHistoryEntry> entry, bool do_not_reactivate, size_t script_history_length, size_t script_history_index, Optional<Bindings::NavigationType> navigation_type, Optional<Vector<JS::NonnullGCPtr<HTML::SessionHistoryEntry>>> entries_for_navigation_api, Optional<JS::NonnullGCPtr<HTML::SessionHistoryEntry>> previous_entry_for_activation, bool update_navigation_api)
{
(void)previous_entry_for_activation;
// 1. Let documentIsNew be true if document's latest entry is null; otherwise false.
auto document_is_new = !m_latest_entry;
@ -4185,7 +4187,10 @@ void Document::update_for_history_step_application(JS::NonnullGCPtr<HTML::Sessio
// 4. Set document's history object's length to scriptHistoryLength.
history()->m_length = script_history_length;
// 5. If documentsEntryChanged is true, then:
// 5. Let navigation be history's relevant global object's navigation API.
auto navigation = verify_cast<HTML::Window>(HTML::relevant_global_object(*this)).navigation();
// 6. If documentsEntryChanged is true, then:
// NOTE: documentsEntryChanged can be false for one of two reasons: either we are restoring from bfcache,
// or we are asynchronously finishing up a synchronous navigation which already synchronously set document's latest entry.
// The doNotReactivate argument distinguishes between these two cases.
@ -4199,21 +4204,21 @@ void Document::update_for_history_step_application(JS::NonnullGCPtr<HTML::Sessio
// 3. Restore the history object state given document and entry.
restore_the_history_object_state(entry);
// 4. Let navigation be history's relevant global object's navigation API.
auto navigation = verify_cast<HTML::Window>(HTML::relevant_global_object(*this)).navigation();
// 5. If documentIsNew is false, then:
// 4. If documentIsNew is false, then:
if (!document_is_new) {
// NOTE: Not in the spec, but otherwise document's url won't be updated in case of a same-document back/forward navigation.
set_url(entry->url());
// 1. Assert: navigationType is not null.
VERIFY(navigation_type.has_value());
// AD HOC: Skip this in situations the spec steps don't account for
if (update_navigation_api) {
// 1. Update the navigation API entries for a same-document navigation given navigation, entry, and "traverse".
navigation->update_the_navigation_api_entries_for_a_same_document_navigation(entry, Bindings::NavigationType::Traverse);
// 2. Update the navigation API entries for a same-document navigation given navigation, entry, and navigationType.
navigation->update_the_navigation_api_entries_for_a_same_document_navigation(entry, navigation_type.value());
}
// 2. Fire an event named popstate at document's relevant global object, using PopStateEvent,
// 3. Fire an event named popstate at document's relevant global object, using PopStateEvent,
// with the state attribute initialized to document's history object's state and hasUAVisualTransition initialized to true
// if a visual transition, to display a cached rendered state of the latest entry, was done by the user agent.
// FIXME: Initialise hasUAVisualTransition
@ -4223,9 +4228,9 @@ void Document::update_for_history_step_application(JS::NonnullGCPtr<HTML::Sessio
auto pop_state_event = HTML::PopStateEvent::create(realm(), "popstate"_fly_string, popstate_event_init);
relevant_global_object.dispatch_event(pop_state_event);
// FIXME: 3. Restore persisted state given entry.
// FIXME: 4. Restore persisted state given entry.
// 4. If oldURL's fragment is not equal to entry's URL's fragment, then queue a global task on the DOM manipulation task source
// 5. If oldURL's fragment is not equal to entry's URL's fragment, then queue a global task on the DOM manipulation task source
// given document's relevant global object to fire an event named hashchange at document's relevant global object,
// using HashChangeEvent, with the oldURL attribute initialized to the serialization of oldURL and the newURL attribute
// initialized to the serialization of entry's URL.
@ -4240,7 +4245,7 @@ void Document::update_for_history_step_application(JS::NonnullGCPtr<HTML::Sessio
}
}
// 6. Otherwise:
// 5. Otherwise:
else {
// 1. Assert: entriesForNavigationAPI is given.
VERIFY(entries_for_navigation_api.has_value());
@ -4252,7 +4257,25 @@ void Document::update_for_history_step_application(JS::NonnullGCPtr<HTML::Sessio
}
}
// 6. If documentIsNew is true, then:
// FIXME: 7. If all the following are true:
// - previousEntryForActivation is given;
// - navigationType is non-null; and
// - navigationType is "reload" or previousEntryForActivation's document is not document, then:
// FIXME: 1. If navigation's activation is null, then set navigation's activation to a new NavigationActivation object in navigation's relevant realm.
// FIXME: 2. Let previousEntryIndex be the result of getting the navigation API entry index of previousEntryForActivation within navigation.
// FIXME: 3. If previousEntryIndex is non-negative, then set activation's old entry to navigation's entry list[previousEntryIndex].
// FIXME: 4. Otherwise, if all the following are true:
// - navigationType is "replace";
// - previousEntryForActivation's document state's origin is same origin with document's origin; and
// - previousEntryForActivation's document's initial about:blank is false,
// then set activation's old entry to a new NavigationHistoryEntry in navigation's relevant realm, whose session history entry is previousEntryForActivation.
// FIXME: 5. Set activation's new entry to navigation's current entry.
// FIXME: 6. Set activation's navigation type to navigationType.
// 8. If documentIsNew is true, then:
if (document_is_new) {
// FIXME: 1. Try to scroll to the fragment for document.
// FIXME: According to the spec we should only scroll here if document has no parser or parsing has stopped.
@ -4264,7 +4287,7 @@ void Document::update_for_history_step_application(JS::NonnullGCPtr<HTML::Sessio
m_ready_to_run_scripts = true;
}
// 7. Otherwise, if documentsEntryChanged is false and doNotReactivate is false, then:
// 9. Otherwise, if documentsEntryChanged is false and doNotReactivate is false, then:
// NOTE: This is for bfcache restoration
if (!documents_entry_changed && !do_not_reactivate) {
// FIXME: 1. Assert: entriesForNavigationAPI is given.

View file

@ -29,6 +29,7 @@
#include <LibWeb/HTML/HTMLScriptElement.h>
#include <LibWeb/HTML/History.h>
#include <LibWeb/HTML/LazyLoadingElement.h>
#include <LibWeb/HTML/NavigationType.h>
#include <LibWeb/HTML/Origin.h>
#include <LibWeb/HTML/SandboxingFlagSet.h>
#include <LibWeb/HTML/Scripting/Environments.h>
@ -593,7 +594,7 @@ public:
HTML::SourceSnapshotParams snapshot_source_snapshot_params() const;
void update_for_history_step_application(JS::NonnullGCPtr<HTML::SessionHistoryEntry>, bool do_not_reactivate, size_t script_history_length, size_t script_history_index, Optional<Vector<JS::NonnullGCPtr<HTML::SessionHistoryEntry>>> entries_for_navigation_api = {}, bool update_navigation_api = true);
void update_for_history_step_application(JS::NonnullGCPtr<HTML::SessionHistoryEntry>, bool do_not_reactivate, size_t script_history_length, size_t script_history_index, Optional<Bindings::NavigationType> navigation_type, Optional<Vector<JS::NonnullGCPtr<HTML::SessionHistoryEntry>>> entries_for_navigation_api = {}, Optional<JS::NonnullGCPtr<HTML::SessionHistoryEntry>> previous_entry_for_activation = {}, bool update_navigation_api = true);
HashMap<URL::URL, JS::GCPtr<HTML::SharedImageRequest>>& shared_image_requests();

View file

@ -1525,7 +1525,7 @@ WebIDL::ExceptionOr<void> Navigable::navigate_to_a_fragment(URL::URL const& url,
// 13. Update document for history step application given navigable's active document, historyEntry, true, scriptHistoryIndex, and scriptHistoryLength.
// AD HOC: Skip updating the navigation api entries twice here
active_document()->update_for_history_step_application(*history_entry, true, script_history_length, script_history_index, {}, false);
active_document()->update_for_history_step_application(*history_entry, true, script_history_length, script_history_index, navigation_type, {}, {}, false);
// 14. Update the navigation API entries for a same-document navigation given navigation, historyEntry, and historyHandling.
navigation->update_the_navigation_api_entries_for_a_same_document_navigation(history_entry, navigation_type);

View file

@ -710,7 +710,7 @@ TraversableNavigable::HistoryStepResult TraversableNavigable::apply_the_history_
bool const update_only = changing_navigable_continuation->update_only;
JS::GCPtr<SessionHistoryEntry> const target_entry = changing_navigable_continuation->target_entry;
bool const populated_cloned_target_session_history_entry = changing_navigable_continuation->populated_cloned_target_session_history_entry;
auto after_potential_unload = JS::create_heap_function(this->heap(), [navigable, update_only, target_entry, populated_target_entry, populated_cloned_target_session_history_entry, displayed_document, &completed_change_jobs, script_history_length, script_history_index, entries_for_navigation_api = move(entries_for_navigation_api), &heap = this->heap()] {
auto after_potential_unload = JS::create_heap_function(this->heap(), [navigable, update_only, target_entry, populated_target_entry, populated_cloned_target_session_history_entry, displayed_document, &completed_change_jobs, script_history_length, script_history_index, entries_for_navigation_api = move(entries_for_navigation_api), &heap = this->heap(), navigation_type] {
if (populated_cloned_target_session_history_entry) {
target_entry->set_document_state(populated_target_entry->document_state());
target_entry->set_url(populated_target_entry->url());
@ -724,8 +724,8 @@ TraversableNavigable::HistoryStepResult TraversableNavigable::apply_the_history_
// 2. Let updateDocument be an algorithm step which performs update document for history step application given
// targetEntry's document, targetEntry, changingNavigableContinuation's update-only, scriptHistoryLength,
// scriptHistoryIndex, navigationType, entriesForNavigationAPI, and displayedEntry.
auto update_document = [script_history_length, script_history_index, entries_for_navigation_api = move(entries_for_navigation_api), target_entry, update_only] {
target_entry->document()->update_for_history_step_application(*target_entry, update_only, script_history_length, script_history_index, entries_for_navigation_api);
auto update_document = [script_history_length, script_history_index, entries_for_navigation_api = move(entries_for_navigation_api), target_entry, update_only, navigation_type] {
target_entry->document()->update_for_history_step_application(*target_entry, update_only, script_history_length, script_history_index, navigation_type, entries_for_navigation_api);
};
// 3. If targetEntry's document is equal to displayedDocument, then perform updateDocument.